The Screen Orientation API provides the ability to read the screen orientation type and angle, to be informed when the screen orientation state changes, and be able to lock the screen orientation to a specific state.

This document is still in a work in progress state. You can have a look at the opened issues. If you see any problem that is not in that list, feel free to discuss it in the mailing list or file an issue .

This specification defines conformance criteria that apply to a single product: the user agent that implements the interfaces that it contains.

Implementations that use ECMAScript to expose the APIs defined in this specification MUST implement them in a manner consistent with the ECMAScript Bindings defined in the Web IDL specification [[!WEBIDL]].

Dependencies

The following concepts and interfaces are defined in [[!HTML]]:

Promise objects are defined in [[!ECMASCRIPT]].

fullscreen element stack is defined in [[!FULLSCREEN]].

now visible algorithm is defined in [[!PAGE-VISIBILITY]].

Interface definitions

Extensions to the Screen interface

The CSSOM View specification defines a Screen interface [[!CSSOM-VIEW]], which this specification extends:
readonly attribute ScreenOrientation orientation

The orientation object is an instance of ScreenOrientation, which is described below.

ScreenOrientation interface

Promise<void> lock(OrientationLockType orientation)
void unlock()
readonly attribute OrientationType type
readonly attribute unsigned short angle
attribute EventHandler onchange

When the lock() method is invoked, the user agent MUST run the apply an orientation lock steps to the responsible document using orientation.

When the unlock() method is invoked, the user agent MUST run the steps to lock the orientation of the responsible document to the responsible document's default orientation.

unlock() does not return a Promise because it is equivalent to locking to the default 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, the user agent MUST return the responsible document's current orientation type.

When getting the angle attribute, the user agent MUST return the responsible document's current orientation angle.

The onchange attribute is an event handler whose corresponding event handler event type is change.

OrientationType enum

portrait-primary
portrait-secondary
landscape-primary
landscape-secondary

OrientationLockType enum

any
natural
landscape
portrait
portrait-primary
portrait-secondary
landscape-primary
landscape-secondary

Concepts

The term screen is equivalent to the screen of the output device associated to the Window, as per [[!CSSOM-VIEW]].

Algorithms defined in this specification assume that for each document there is a pending promise, which is initially set to null, which is a Promise object whose associated operation is to lock the screen orientation.

When queuing a task, the screen orientation task source is used.

Reading the screen orientation

All documents have a current orientation type and a current orientation angle. Both of them SHOULD be initialized when the document is created, otherwise they MUST be initialized the first time they are accessed and before their value is read. The user agent MUST update the orientation information of the document to initialize them.

For a given document, the current orientation type and the current orientation angle are strongly linked in the sense that for any given type, there will be a specific angle associated. However, the user agent can associate *-primary and *-secondary values at will. For example, if 90 is associated with landscape-primary and 270 with landscape-secondary for one document , another one MAY get the opposite relationship.

orientation.angle and orientation.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 steps to update the orientation information of a document are as follows:

  1. If the screen width is greater than the screen height, set the document's current orientation type to landscape-primary or landscape-secondary.
  2. Otherwise, if the screen width is less than or equal to the screen height, set the document's current orientation type to portrait-primary or portrait-secondary.
  3. Set the document's current orientation angle to the clockwise angle in degrees between the orientation of the viewport as it is drawn and the natural orientation of the device (i.e., the top of the physical screen). This is the opposite of the physical rotation. In other words, if you turn a device 90 degrees on the right, screen orientation angle would be 270 degrees.

The decision whether the document's current orientation type should be set to *-primary or *-secondary is up to the user agent. For example, it can be based on the device preferred angles, the user's preferred orientations or the current orientation when the application starts. However, a user agent MUST keep the screen orientation types and the screen orientation angles relation consistent for any given document.

Locking the screen orientation

The user agent MAY require a document and its associated browsing context to meet one or more security conditions in order to be able to lock the screen orientation. For example, a user agent might require a document's top-level browsing context to be fullscreen (see Interaction with FullScreen API) in order to allow an orientation lock.

The user agent MAY reject all attempts to lock the screen orientation if the platform conventions do not expect applications to be able to change the screen orientation. For example, on most desktop platforms, applications can not change the screen orientation.

If the user agent supports locking the screen orientation, it MUST allow the screen to be locked to all of the states of the OrientationLockType enum.

A document's orientation lock is the orientation lock that applies on its top-level browsing context. An orientation lock is an unordered set of OrientationType.

The steps to apply an orientation lock to a document using orientation are as follows:

  1. If the user agent does not support locking the screen orientation, return a Promise rejected with a DOMException whose name is NotSupportedError and abort these steps.
  2. The following sub-steps MAY be run asynchronously for performance reasons, for example, if the user agent has browsing contexts living in different processes:
    1. Let browsing contexts be the list of the descendant browsing contexts of the top-level browsing context's document.
    2. If one of the browsing contexts's document's pending promise is not null:
      1. Let doc be the document which has a not null pending promise.
      2. Reject doc's pending promise with DOMException whose name is AbortError.
      3. Set doc's pending promise to null .
  3. If the document's active sandboxing flag set has the sandboxed orientation lock browsing context flag set, or user agent doesn't meet the security conditions to perform an orientation change, return a Promise rejected with a DOMException whose name is SecurityError and abort these steps.
  4. Let orientations be an empty list.
  5. Depending on orientation value, do the following:
    portrait-primary or portrait-secondary or landscape-primary or landscape-secondary
    Append orientation to orientations.
    landscape
    Depending on platform convention, append landscape-primary, or landscape-secondary, or both to orientations.
    portrait
    Depending on platform convention, append portrait-primary, or portrait-secondary, or both to orientations.
    natural
    Append portrait-primary or landscape-primary to orientations such as the associated screen orientation angle is 0.
    any
    Append portrait-primary, portrait-secondary, landscape-primary and landscape-secondary to orientations.
  6. Set pending-promise to be a newly-created Promise.
  7. Return pending-promise and continue asynchronously.
  8. Lock the orientation of the document to orientations.
  9. If locking the orientation did not result in a change of orientation, queue a task to resolve pending-promise with undefined and set pending-promise to null.
If locking the orientation results in an orientation change, the promise will be resolved when the orientation will change as described in the Handling screen orientation changes section.

When the user agent has to lock the orientation of a document to orientations, it MUST run the following steps:

  1. Set the document's orientation lock to orientations.
  2. If the active orientation lock is not the document's orientation lock, abort these steps.
  3. If the active orientation lock value is equal to orientations value, abort these steps.
  4. If orientations contains only one value, run the following sub-steps:
    1. Let orientation be the value contained in orientations.
    2. Change how the viewport is drawn so that the document's current orientation type will be equal to orientation.
    3. After the change has happened, prevent the document's top-level browsing context's screen orientation from changing until those steps are run again.
    4. Abort these steps.
  5. If the document's current orientation type is not part of orientations, change how the viewport is drawn such as the document's current orientation type will be equal to one of orientations' values.
  6. Otherwise, depending on platform conventions, change how the viewport is drawn in order to make it match another screen orientation type. However, it has to be part of orientations.
  7. Allow the user to change the screen orientation to any value part of orientations and only those values until those steps are run again. The method to define the current screen orientation has to match the platform conventions.

Screen orientation lock lifetime

To determine the active orientation lock, the user agent MUST run the following steps:

  1. If there is only one top-level browsing context with a document that is visible per [[!PAGE-VISIBILITY]], the active orientation lock is the document's orientation lock.
  2. Otherwise, if there are more than one top-level browsing context with a document that is visible per [[!PAGE-VISIBILITY]] but only one of those documents is focused, the active orientation lock is the focused document's orientation lock.
  3. Otherwise, the active orientation lock SHOULD be the latest focused document's orientation lock, unless stated otherwise by the platform conventions.

Whenever the active orientation lock changes, the user agent MUST run the steps to lock the orientation of the document to the document's orientation lock.

Whenever a top-level browsing context is navigated, the user agent MUST lock the orientation of the document to the document's default orientation.

Handling screen orientation changes

Whenever the viewport is drawn at a different angle compared to the device's natural orientation, the user agent MUST asynchronously run the following steps:

  1. Let browsing contexts be the list of the descendant browsing contexts of the top-level browsing context's document.
  2. For each browsing context in browsing contexts, run the following sub-steps:
    1. Let doc be the browsing context's active document.
    2. If doc is not visible per [[!PAGE-VISIBILITY]], abort these steps.
    3. Update the orientation information of doc.
    4. If doc's pending promise is not null:
      1. Resolve doc's pending promise with undefined.
      2. Set doc's pending promise to null .
    5. Queue a task to fire a simple event named change at doc 's screen.orientation object.

Whenever a document becomes visible per [[!PAGE-VISIBILITY]], in other words after the now visible algorithm is run, the user agent MUST asynchronously run the following steps:

  1. Let type and angle be respectively the document's current orientation type and current orientation angle.
  2. Update the orientation information of the document.
  3. If type is different from the document's current orientation type or angle from the document 's current orientation angle, run the following sub-steps:
    1. If the document's pending promise is not null:
      1. Resolve the document's pending promise with undefined.
      2. Set the document's pending promise to null.
    2. Queue a task to fire a simple event named change at the document's screen.orientation object.

Developers need to be aware that a screen.orientation object from a document that is not visible, as per [[!PAGE-VISIBILITY]], will not receive an orientation change event. This is to prevent unnecessary changes to layout, etc. in the non-visible web application.

This section could be improved if the [[PAGE-VISIBILITY]] specification had a hook for when the document becomes visible and hidden. issue 77.
This section could use the animation frame taska if and when it is ready. issue 40.

Default orientation

A document's default orientation is the set of orientations to which the screen orientation is locked when it is not explicitly locked by this API or any other means.

For the perspective of a document, locking to the default orientation is equivalent to unlocking because it means that it no longer has a lock applied. However, it does not mean that the default orientation has to be any.

Extension to the HTML sandboxing model

This section is monkey patching the [[!HTML]] specification. It is meant to be merged into the [[!HTML]] specification as soon as this document is stable enough. See issue 69.

The [[!HTML]] specification defines a sandboxing flag set which is extended with this value:

The sandboxed orientation lock browsing context flag
This flag disables the ability to lock the screen orientation.

The algorithm to parse a sandboxing directive is also extended in step 3 such that:

Finally, the iframe's sandbox attribute MUST add allow-orientation-lock amongst its allowed values.

Interactions with other specifications

This section explains how this specification interacts with other related specifications of the platform.

Interaction with FullScreen API

As a security condition, a user agent MAY restrict locking the screen orientation exclusively to when the top-level browsing context's document's fullscreen element stack is not empty. When that security condition applies, whenever the document's fullscreen element stack is empty and a screen orientation lock is applied, the user agent MUST lock the orientation of the document to the document's default orientation.

This section could be improved if the [[FULLSCREEN]] specification had a hook for when the document is no longer fullscreen. See issue 62 .

Interaction with DeviceOrientation

The DeviceOrientation specification [[DEVICE-ORIENTATION]] defines a deviceorientation event that can be used to discover the physical orientation of the device. Such event can be used to draw things on the screen that could point to a specific direction. A basic example being a compass application. Another example would be an application giving direction to the user or an augmented reality game pointing to an objective.

Drawing on the screen in order to point to a physical location requires to know the device orientation and the orientation of the screen in the device coordinates. Without the APIs defined in this specification, a developer has to assume that the document's current orientation angle is 0. With the help of the APIs described in this specification, the developer can apply an orientation lock to a document using natural to make that assumption a certitude. Otherwise, reading the document's current orientation angle via screen.orientation.angle and listening to the change event can help the developer to compensate the screen orientation angle.

Interaction with Web Application Manifest

The Web Application Manifest specification [[appmanifest]] allows web applications to set the document's default orientation.

Interaction with CSS Device Adaptation

The CSS Device Adaptation specification [[CSS-ADAPTATION]] defines, independently of this document, a way to lock the screen orientation for a web page using CSS.

Examples

This example shows the current screen orientation to the console every time the screen orientation state changes.

<script>
  var show = function() {
     console.log("Orientation type is " + screen.orientation.type);
     console.log("Orientation angle is " + screen.orientation.angle);
  }

  screen.orientation.addEventListener("change", show);
  window.onload = show;
</script>

<button onclick='screen.orientation.unlock()'>
  Unlock
</button>
<button onclick="screen.orientation.lock('portrait')">
  Lock to portrait
</button>
<button onclick="screen.orientation.lock('landscape')">
  Lock to landscape
</button>

This example waits to be fullscreen before locking the screen orientation and starting.

<script>
  var start = function() {
    document.onfullscreenchange = function() {
      screen.orientation.lock('natural').then(startInternal);
    }
    document.documentElement.requestFullscreen();
  }
</script>
<button onclick='start();'>
  Start
</button>

This example asks the user to manually rotate the device if the Screen Orientation API is not available.

<script>
  var start = function() {
    screen.orientation.lock('landscape-primary').then(
      startInternal,
      function() {
        alert('To start, rotate your screen to landscape.');

        var orientationChangeHandler = function() {
          if (!screen.orientation.type.startsWith('landscape')) {
            return;
          }
          screen.orientation.removeEventListener('change', orientationChangeHandler);
          startInternal();
        }

        screen.orientation.addEventListener('change', orientationChangeHandler);
      });
  }
  window.onload = start;
</script>

Acknowledgments

Thanks to Marcos Cáceres, Christophe Dumez, Anne van Kesteren and Chundong Wang for their useful comments.

Special thanks to Chris Jones and Jonas Sicking for their contributions to the initial design of this API.