LEARNING OBJECTIVES ⌵
- Programmatically lock the display orientation using
screen.orientation.lock()with specific lock types (landscape,portrait,any,natural). - Understand why calling
lock()requires a Fullscreen API state or standalone PWA context. - Handle
DOMExceptionerror types (NotSupportedError,SecurityError,AbortError) with asynchronoustry...catchblocks. - Programmatically unlock orientation using
screen.orientation.unlock()during cleanup routines.
📖 The Mental Model & Story (Intuitive Foundation)
Imagine a passenger sitting on a high-speed train playing a flight simulator on their tablet. As the train sways around sharp mountain curves, the tablet's physical accelerometer thinks the device is rotating and continuously flips the game viewport upside down and sideways, breaking the flight controls.
+----------------------------------+
| USER ENTERS FULLSCREEN |
| document.documentElement |
| .requestFullscreen() |
+----------------------------------+
│
▼
+----------------------------------+
| REQUEST ORIENTATION LOCK |
| screen.orientation.lock( |
| 'landscape-primary' |
| ) |
+----------------------------------+
│
┌───────────────────┴───────────────────┐
▼ ▼
[ PROMISE RESOLVES ✅ ] [ PROMISE REJECTS ❌ ]
- Hardware display is - Not in Fullscreen
pinned to landscape - User denied permission
- OS ignores physical tilts - OS/Browser unsupported (iOS)
To prevent unwanted display rotation in games, video players, and VR experiences, browsers provide screen.orientation.lock(). However, because locking the entire screen orientation takes control away from the user, browsers enforce strict security boundaries: your web app can only lock the orientation if it has received user interaction and entered Fullscreen mode or is installed as a Progressive Web App (PWA).
Technical Deep Dive & Specifications
The lock() Method Signature & Parameters
The lock() method returns a standard JavaScript Promise that resolves with undefined when the lock is active or rejects with a DOMException if the lock fails:
screen.orientation.lock(orientationLockType: OrientationLockType): Promise<void>;
screen.orientation.unlock(): void;
type OrientationLockType =
| "any" // Unlocks any orientation (both portrait and landscape)
| "natural" // Natural hardware baseline (portrait on phones, landscape on PCs)
| "landscape" // Either landscape-primary or landscape-secondary
| "portrait" // Either portrait-primary or portrait-secondary
| "portrait-primary" // Upright portrait only
| "portrait-secondary" // Inverted portrait only
| "landscape-primary" // Sideways landscape only
| "landscape-secondary"; // Inverted sideways landscape only
The Orientation Lock Type Hierarchy
[ ANY ]
(Allows all 4 physical rotations)
│
┌───────────────────┴───────────────────┐
▼ ▼
[ PORTRAIT ] [ LANDSCAPE ]
(0° or 180° only) (90° or 270° only)
│ │ │ │
┌─────┘ └─────┐ ┌─────┘ └─────┐
▼ ▼ ▼ ▼
[ portrait-primary ] [ portrait-secondary ] [ landscape-primary ] [ landscape-secondary ]
(Upright) (Inverted) (Rotated 90°) (Rotated 270°)
Security & Prerequisite Requirements Matrix
Why does screen.orientation.lock() fail? Browsers enforce three strict prerequisites:
| Requirement | Why It Is Mandated | Result if Missing |
|---|---|---|
| Secure Context (HTTPS) | Prevents man-in-the-middle scripts from hijacking display controls. | Throws SecurityError |
| Fullscreen Mode or Installed PWA | A standard web tab cannot hijack the entire OS screen unless the user agreed to full immersion. | Throws NotSupportedError / SecurityError |
| Transient User Activation | Must be triggered inside a click, tap, or touch event handler. | Throws SecurityError |
DOMException Error Handling Reference
try {
await screen.orientation.lock('landscape');
} catch (error) {
switch (error.name) {
case 'NotSupportedError':
console.warn('Orientation locking not supported on this device/browser.');
break;
case 'SecurityError':
console.warn('Locked out: Must enter Fullscreen or run as installed PWA.');
break;
case 'AbortError':
console.warn('Lock request was aborted by another concurrent orientation change.');
break;
default:
console.error('Orientation lock failed:', error);
}
}
💻 Interactive Code Playground
Starter Code
Line-by-Line Code Breakdown
- Lines 134–146: Manages entering and exiting Fullscreen mode via
document.documentElement.requestFullscreen(), fulfilling the mandatory browser prerequisite. - Lines 149–153: Evaluates feature detection for
screen.orientation.lockto prevent fatal runtime errors on iOS Safari or legacy browsers. - Lines 155–158: Executes
await screen.orientation.lock(lockMode)inside an asynchronoustry...catchwrapper. - Lines 159–165: Catches specific
DOMExceptiontypes (SecurityError,NotSupportedError) and gives actionable diagnostic feedback. - Lines 174–180: Calls
screen.orientation.unlock()to release hardware display constraints, restoring natural OS sensor responsiveness.
Expected Browser Render Output
🔒 Screen Orientation Lock
Locking screen orientation requires Fullscreen mode on mobile web browsers.
[ Current: portrait-primary (0°) ]
[ 1️⃣ Enter Fullscreen Mode ]
[ 🔒 Lock Landscape ] [ 🔒 Lock Portrait ]
[ 🔒 Lock Landscape-Primary] [ 🔒 Lock Natural ]
[ 🔓 Unlock Orientation ]
System ready. Enter fullscreen before locking.
[10:20:10 AM] ℹ️ Requesting lock("landscape")...
[10:20:10 AM] ❌ SecurityError: Must enter Fullscreen mode before locking orientation.🏋️ Hands-On Exercise
🎯 The Challenge: Build an Auto-Locking Arcade Game Launcher
Instructions:
- Build an HTML page with a "Launch Arcade Mode" button.
- When the user clicks the button:
- Request Fullscreen on the game canvas container.
- Attempt to lock the orientation to
'landscape-primary'. - If
lock()fails (e.g. on desktop or iOS), fall back gracefully by rendering an in-game UI notification asking the player to turn their device.
- When the user exits fullscreen (listens to
fullscreenchange), automatically unlock the orientation viascreen.orientation.unlock().
🏁 Starter Code Sandbox
⚠️ Common Pitfalls
- Invoking
lock()Outside Fullscreen or PWA Mode: Callingscreen.orientation.lock()on a standard un-fullscreened web page will trigger an unhandledPromiserejection withSecurityErrororNotSupportedError. - Forgetting iOS Safari Incompatibility: As of modern iOS versions, Apple WebKit does not implement
screen.orientation.lock(). Never assume the promise exists without checking'lock' in screen.orientation. - Failing to Unlock on Exit: If you lock the screen inside an experience and forget to call
unlock(), the user may remain trapped in landscape orientation even after closing your modal dialog.
💡 Pro Tips
- Declare Orientation in Web App Manifest: For Progressive Web Apps, you can declaratively enforce orientation without writing JavaScript by adding
"orientation": "landscape"or"orientation": "portrait"inside yourmanifest.json. - Handle Transient Abort Rejections: If a user violently flips their phone while
lock()is executing, the browser may reject with anAbortError. Always wrap yourlock()call in a resilienttry...catchblock.
📌 Key Takeaways
screen.orientation.lock()locks the browser display to a chosen orientation subtype (e.g.'landscape','portrait-primary').- Programmatic locking strictly requires a Fullscreen state or an Installed PWA context.
screen.orientation.unlock()releases hardware display locking and restores normal accelerometer orientation tracking.- Always handle
NotSupportedError,SecurityError, andAbortErrorDOMExceptionrejections. - Always tie orientation unlocking to the
fullscreenchangeevent. - --