The Screen Orientation specification standardizes the types and angles for a device's screen orientation, and provides a means for locking and unlocking it. The API, defined by this specification, exposes the current type and angle of the device's screen orientation, and dispatches events when it changes. This enables web applications to programmatically adapt the user experience for multiple screen orientations, working alongside CSS. The API also allows for the screen orientation to be locked under certain preconditions. This is particularly useful for applications such as computer games, where users physically rotate the device, but the screen orientation itself should not change.
This document is a work in progress.
In this example clicking the "Lock" button requests to go into fullscreen and then locks the screen to the opposite orientation. clicking the "unlock" button unlocks the screen.
<script> function updateLockButton() { const lockButton = document.getElementById("button"); const newOrientation = getOppositeOrientation(); lockButton.textContent = `Lock to ${newOrientation}`; } function getOppositeOrientation() { return screen .orientation .startsWith("portrait") ? "landscape" : "portrait"; } async function rotate(lockButton) { if (!document.fullscreenElement) { await document.documentElement.requestFullscreen(); } const newOrientation = getOppositeOrientation(); await screen.orientation.lock(newOrientation); updateLockButton(lockButton); } screen.orientation.addEventListener("change", updateLockButton); window.addEventListener("load", updateLockButton); </script> <button onclick="rotate(this)" id="button"> Lock to... </button> <button onclick="screen.orientation.unlock()"> Unlock </button>
To lock the screen orientation to an {{OrientationLockType}} |orientation| means that the screen can only be rotated by the user to a specific [=screen orientation=] - possibly at the exclusion of other orientations. The possible orientations to which the screen can be rotated is determined by the user agent, a user preference, the operating system's conventions, or the screen itself. For example, locking the orientation to [=landscape=] means that the screen can be rotated by the user to [=landscape-primary=] and maybe [=landscape-secondary=] if the system allows it, but won't change the orientation to [=portrait-secondary=] orientation.
To unlock the screen orientation the end user is unrestricted to rotate the screen to any [=screen orientation=] that the system allows.
A screen can be in, or [=locked=] to, one of the following screen orientations:
The screen of the output device has the following associated concepts:
The screen orientation values table presents the possible value for the [=Screen/current orientation type=] and [=Screen/current orientation angle=]. The table specifies the [=primary=] and [=secondary=] values that are determined by the device's [=natural=] orientation and the possibilities available to the [=user agent=] for setting the other primary and secondary orientation values.
In the natural orientation is... | Primary Orientation | Secondary Orientation | Primary Orientation (alternative) | Secondary Orientation (alternative) |
---|---|---|---|---|
Portrait |
[=portrait-primary=] angle `0` |
portrait-secondary angle `180` |
landscape-primary angle `90` or angle `270` |
landscape-secondary The angle not used for [=landscape-primary=]. |
[=Landscape=] |
[=landscape-primary=] angle `0` |
landscape-secondary angle `180` |
[=portrait-primary=] angle `90` or angle `270` |
portrait-secondary The angle not used for [=portrait-primary=]. |
{{ScreenOrientation/angle}} and {{ScreenOrientation/type}} relationship Never assume any cross-devices relationship between the screen orientation type and the screen orientation angle. Any assumption would be wrong given that a device might have `90` and `270` as the angles for `landscape` types but another device will have `0` and `180`, depending on its [=natural=] orientation. Instead, it is recommended to check during runtime the relationship between angle and type.
The {{Document}} interface is extended with the following internal slots:
Internal Slot | Description |
---|---|
[[\orientationPendingPromise]] | Either `null` or a {{Promise}}. When assigned a {{Promise}}, that promise represents a request to lock the screen orientation. |
partial interface Screen { [SameObject] readonly attribute ScreenOrientation orientation; };
The {{Window}} object has an associated `ScreenOrientation`, which is a {{Screen}}'s {{Screen/orientation}} object (i.e., the {{ScreenOrientation}} instance at `window.screen.orientation`).
[Exposed=Window] interface ScreenOrientation : EventTarget { Promise<undefined> lock(OrientationLockType orientation); undefined unlock(); readonly attribute OrientationType type; readonly attribute unsigned short angle; attribute EventHandler onchange; };
Internal Slot | Description |
---|---|
[[\angle]] | Represents the screen's last known [=Screen/current orientation angle=] in degrees as an {{unsigned short}}. |
[[\initialType]] | Represents the screen's [=Screen/current orientation type=] when the [=browsing context=] was created. |
[[\type]] | Represents the screen's last known [=Screen/current orientation type=] as an {{OrientationType}} enum value. |
When the {{lock()}} method is invoked with {{OrientationLockType}} |orientation:OrientationLockType|, the [=user agent=] MUST run the following steps.
The [=user agent=] MAY require a [=document=] and its associated [=Document/browsing context=] to meet one or more pre-lock conditions in order to [=lock the screen orientation=]. See [[[#appmanifest-interaction]]] and [[[#fullscreen-interaction]]].
When the {{unlock()}} method is invoked, the [=user agent=] MUST run the following steps:
{{unlock()}} does not return a promise because it is equivalent to locking to the [=default screen orientation=] which might or might not be known by the [=user agent=]. Hence, the [=user agent=] can not predict what the new orientation is going to be and even if it is going to change at all.
When getting, the {{type}} attribute returns [=this=]'s {{ScreenOrientation/[[type]]}}.
When getting, the {{angle}} attribute returns [=this=]'s {{ScreenOrientation/[[angle]]}}.
The {{onchange}} attribute is an [=event handler IDL attribute=] for the {{onchange}} [=event handler=], whose [=event handler event type=] is change.
enum OrientationLockType { "any", "natural", "landscape", "portrait", "portrait-primary", "portrait-secondary", "landscape-primary", "landscape-secondary" };
The {{OrientationLockType}} enum represents the screen orientations to which a screen can be potentially [=locked=].
enum OrientationType { "portrait-primary", "portrait-secondary", "landscape-primary", "landscape-secondary" };
The {{OrientationType}} enum values are used to represent the screen's [=Screen/current orientation type=].
When a [=browsing context=] |context| is created, the [=user agent=] MUST:
When steps require to reject and nullify the current lock promise of {{Document}} |document| with a {{DOMString}} |exceptionName|, the [=user agent=] MUST:
When steps require to apply orientation lock of {{OrientationLockType?}} |orientation| to {{Document}} |document|, the [=user agent=] MUST perform do the following steps:
This can happen if the user has set a preference that prevents web applications from changing the screen orientation, or if the underlying platform, rather than the user agent, does not allow locking the screen orientation to the given |orientation|.
When a user-agent determines that the screen's orientation has changed for a [=top-level browsing context=], or the user moves the [=top-level browsing context=] to a different screen, then run the [=screen orientation change steps=] with the [=top-level browsing context=]'s [=navigable/active document=].
The screen orientation change steps for {{Document}} |document:Document| are as follows:
[[HTML]]'s update the visibility state runs the [=screen orientation change steps=].
Whenever the [=unloading document cleanup steps=] run with a |document|, the user agent MUST run the following steps:
The fully unlock the screen orientation steps for {{Document}} |document:Document| are as follows:
A user agent SHOULD restrict the use of {{ScreenOrientation/lock()}} to simple fullscreen documents as a [=pre-lock condition=]. [[fullscreen]]
When a [=document=] exits fullscreen, it also runs the [=fully unlock the screen orientation steps=]. [[fullscreen]]
The [[[appmanifest]]] specification allows web applications to set the [=default screen orientation=] via the the [=manifest/orientation=] member.
A user agent SHOULD require [=installed web applications=] to be presented in the "fullscreen" [=display mode=] as a [=pre-lock condition=].
As users can have their devices mounted in a fixed orientation (e.g. on the arm of a wheelchair), developers that expect users to rotate their device when [=locking the screen orientation=] need to be aware of the [[[WCAG21]]]'s Orientation Success Criterion. The criterion makes it essential that content and functionality is available regardless of the [=screen orientation=]. When a particular orientation is essential, web applications must advise the user of the orientation requirements.
A screen's [=Screen/current orientation type|type=] and [=Screen/current orientation angle|angle=] are a potential fingerprinting vector. The following mitigation help protect a user's privacy by not revealing how a device is being held, and also prevents the [=secondary=] orientation type and associated angles from being user for fingerprinting purposes.
To resist fingerprinting (e.g., in private browsing), user agents MAY:
Thanks Christophe Dumez, Anne van Kesteren, Chundong Wang, Fuqiao Xue, and Chaals McCathie Nevile for their useful comments.
Special thanks to Chris Jones and Jonas Sicking for their contributions to the initial design of this API.