Skip to content

Manifest · Manifest member

orientation manifest member

Published Updated

Limited availabilityNot supported in Firefox (Desktop), Safari (macOS), Safari (iOS)W3C

orientation asks the browser to lock an installed web app’s top-level windows to a default screen orientation, such as portrait or landscape, for as long as the app runs in an app-like display mode. It is a declarative counterpart to screen.orientation.lock(): the manifest sets the starting lock once at launch, the API changes it at runtime.

Chrome 39 on Android, Samsung Internet 4.0, Android WebView 39, and Firefox 79 for Android apply the member to installed apps (BCD html.manifest.orientation). Desktop Chrome 39 and Edge 79 parse it but do not lock a desktop window, Safari on iOS and macOS ignore it, and Firefox 157 on desktop installs nothing from the manifest. The lock only takes effect in fullscreen, standalone, or minimal-ui; a page opened in a browser tab is not rotated by its manifest.

  • Type: string, one of the OrientationLockType values: any, natural, landscape, landscape-primary, landscape-secondary, portrait, portrait-primary, or portrait-secondary.
  • Default: absent, which means no lock. The window follows the device’s sensor and the user’s rotation-lock setting, exactly as a browser tab does.
  • Example value: "portrait".

natural is the device’s own default (portrait on most phones, landscape on most tablets and every laptop). portrait and landscape allow either of the two variants in that axis, so a phone turned upside down stays readable; the -primary and -secondary forms pin a single one. any is written when a manifest wants to say explicitly that it does not care, and is treated the same as leaving the member out.

A value outside the list is dropped, not an error for the whole manifest: Chromium logs unknown 'orientation' value ignored. and continues with no lock. The lock is a property of the app window, so it applies to every in-scope document the window shows and not to the same URLs opened in a browser tab.

The declaration is one line; the interesting code is what the page does when the lock is not honoured.

A data-entry app whose forms are laid out for a phone held upright locks to portrait. On Chrome for Android the installed app ignores the device rotating; in a browser tab, on desktop, and on iOS the same manifest has no effect and the layout must still work in landscape.

{
"name": "Field Journal",
"short_name": "Journal",
"start_url": "/",
"display": "standalone",
"orientation": "portrait"
}

portrait rather than portrait-primary is the better choice for a phone app: it lets the screen flip 180 degrees when the user turns the device around, which portrait-primary would block.

Reading the current orientation and reacting to changes

Section titled “Reading the current orientation and reacting to changes”

The manifest lock is invisible to script, but the orientation it produces is not. The Screen Orientation API reports it through screen.orientation.type; browsers without the API (Safari on iOS before 16.4) take the fallback branch and are read through a media query, which is also what fires on every rotation in both branches.

function currentOrientation() {
if ('orientation' in screen && screen.orientation?.type) {
return screen.orientation.type; // e.g. "portrait-primary"
}
// Fallback: no Screen Orientation API; derive the axis from the viewport.
return matchMedia('(orientation: portrait)').matches ? 'portrait' : 'landscape';
}
const query = matchMedia('(orientation: portrait)');
query.addEventListener('change', () => {
document.documentElement.dataset.orientation = currentOrientation();
});
document.documentElement.dataset.orientation = currentOrientation();

Because the manifest lock holds the app in one axis, the change listener fires only in the environments that did not honour the lock, which makes it the natural place to switch to a two-column layout.

Locking at runtime where the manifest is ignored

Section titled “Locking at runtime where the manifest is ignored”

screen.orientation.lock() can impose the same lock from script, with two constraints the manifest does not have: on Android the document must be in fullscreen first, and desktop browsers reject the call with NotSupportedError (MDN, ScreenOrientation.lock()). The fallback is to do nothing and rely on the responsive layout.

async function lockPortraitIfPossible() {
if (!('orientation' in screen) || typeof screen.orientation.lock !== 'function') {
return 'unsupported'; // Safari: no lock(); layout stays responsive
}
try {
await document.documentElement.requestFullscreen();
await screen.orientation.lock('portrait');
return 'locked';
} catch (err) {
// Desktop Chrome and Edge reject as not supported; a sandboxed iframe rejects as a security error.
return err.name;
}
}

Call it from a click handler: both requestFullscreen() and the lock require user activation, and the returned string tells the UI whether to keep its rotate-the-device hint.

Specifications

SpecificationStatus
Web App Manifest: orientationW3C
  • Legend
  • Yes
  • Partial
  • Flag
  • No
  • Unknown
Browser / PlatformSupportVersionsConfidenceSourceNotes
Chrome (Desktop)Yes39highsource—
Chrome (Android)Yes39highsource1
Edge (Desktop)Yes79highsource2
Firefox (Desktop)No—highsource3
Firefox (Android)Yes79highsource—
Safari (macOS)No—highsource4
Safari (iOS)No—highsource56
Samsung InternetYes4.0highsource7
WebView (Android)Yes39highsource8
  1. Derived by browser-compat-data mirroring from Chrome.
  2. Derived by browser-compat-data mirroring from Chrome.
  3. No Firefox support is recorded in browser-compat-data.
  4. No Safari support is recorded in browser-compat-data.
  5. No Safari on iOS support is recorded in browser-compat-data.
  6. Derived by browser-compat-data mirroring from Safari.
  7. Derived by browser-compat-data mirroring from Chrome Android.
  8. Derived by browser-compat-data mirroring from Chrome Android.

Source data: /compatibility/manifest-orientation.json · Global usage: 74 % (StatCounter 2026-05)

Source: spec · MDN · Last verified 2026-10-03 · Confidence: high (computed from sources)