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

This document is a work in progress.

Introduction

For web applications, the Screen Orientation API exposes the type and angle of a device's current screen orientation, and can provide notification if the device's orientation changes. This allows web applications to programmatically adapt the user experience for many possible screen orientations (in concert with CSS). The API also allows locking the screen to a particular orientation. This is useful in applications such as computer games where users physically rotate the device but the screen orientation itself mustn't change.

Goals

Examples

Locking to a specific orientation and unlocking

In this example, clicking the "Lock" button makes a request to go into fullscreen and then lock the screen to the opposite orientation. Pressing the "Unlock" button unlocks the screen so it rotates if the user turns the device.

The developer console logs the change in orientation type and angle.

  <script>
  function fullScreenCheck() {
    if (document.fullscreenElement) return;
    return document.documentElement.requestFullscreen();
  }
  
  function updateDetails(lockButton) {
    const buttonOrientation = getOppositeOrientation();
    lockButton.textContent = `Lock to ${buttonOrientation}`;
  }
  
  function getOppositeOrientation() {
    const { type } = screen.orientation;
    return type.startsWith("portrait") ? "landscape" : "portrait";
  }
  
  async function rotate(lockButton) {
    try {
      await fullScreenCheck();
    } catch (err) {
      console.error(err);
    }
    const newOrientation = getOppositeOrientation();
    await screen.orientation.lock(newOrientation);
    updateDetails(lockButton);
  }
  
  function show() {
    const { type, angle } = screen.orientation;
    console.log(`Orientation type is ${type} & angle is ${angle}.`);
  }
  
  screen.orientation.addEventListener("change", () => {
    show();
    updateDetails(document.getElementById("button"));
  });
  
  window.addEventListener("load", () => {
    show();
    updateDetails(document.getElementById("button"));
  });
  </script>
  
  <button onclick="rotate(this)" id="button">
    Lock
  </button>
  <button onclick="screen.orientation.unlock()">
    Unlock
  </button>
  

Locking the screen before calling a function

This example waits to go into fullscreen, then locks to landscape before calling ready().

  <script>
  function ready() {
    const { type } = screen.orientation;
    console.log(`Fullscreen and locked to ${type}. Ready!`);
  }
  
  async function start() {
    await document.body.requestFullscreen();
    await screen.orientation.lock("landscape");
    ready();
  }
  </script>
  <button onclick="start()">
    Start
  </button>
  

Alerting the user if the Screen Orientation API is not supported

In this example, if the Screen Orientation API is not supported, or the document is not fullscreen and the screen orientation lock rejects, the user is alerted to rotate their screen manually to landscape.

  <script>
  function start() {
    /* Start application when in correct orientation */
  }
  async function rotate() {
    try {
      await screen.orientation.lock("landscape");
      start();
    } catch (err) {
      console.error(err);
    }
    const matchLandscape = matchMedia("(orientation: landscape)");
    if (matchLandscape.matches) return start(); 
    addEventListener("orientationchange", function listener() {
      matchLandscape.addListener(function mediaChange(e) {
        if (!e.matches) return; 
        removeEventListener("orientationchange", listener);
        matchLandscape.removeListener(mediaChange);
        start();
      });
    });
    alert("To start, please rotate your screen to landscape.");
  }
  </script>
  <button onclick="start()">
    Start
  </button>
  

Extensions to the Screen interface

The CSSOM View Module specification defines the Screen interface, which this specification extends:

          partial interface Screen {
            [SameObject] readonly attribute ScreenOrientation orientation;
          };
        

orientation attribute

The orientation attribute is an instance of ScreenOrientation. This attribute provides the current orientation, current angle and whether there was an onchange event. The user agent MUST run the updating orientation algorithm steps to initialize the values and return the orientation attribute.

ScreenOrientation interface

          [Exposed=Window]
          interface ScreenOrientation : EventTarget {
            Promise<void> lock(OrientationLockType orientation);
            void unlock();
            readonly attribute OrientationType type;
            readonly attribute unsigned short angle;
            attribute EventHandler onchange;
          };
        
          enum OrientationLockType {
            "any",
            "natural",
            "landscape",
            "portrait",
            "portrait-primary",
            "portrait-secondary",
            "landscape-primary",
            "landscape-secondary"
          };

          enum OrientationType {
            "portrait-primary",
            "portrait-secondary", 
            "landscape-primary",
            "landscape-secondary"
          };
      

The OrientationLockType enum represents the screen orientations to which a screen can be locked: the "any" enum value represents the any orientation, the "natural" enum represents the natural orientation, the "landscape" enum represents the landscape orientation, the "portrait" enum represents the portrait orientation, the "portrait-primary" enum represents the portrait-primary orientation, the "portrait-secondary" enum represents the portrait-secondary orientation, the "landscape-primary" enum represents the landscape-primary orientation, and the "landscape-secondary" enum represents the landscape-secondary orientation.

The OrientationType enum represents the actual current screen orientation that the screen is in irrespective of which lock is applied: the "portrait-primary" enum represents the portrait-primary orientation, the "portrait-secondary" enum represents the portrait-secondary orientation, the "landscape-primary" enum represents the landscape-primary orientation, and the "landscape-secondary" enum represents the landscape-secondary orientation.

lock() method: Lock screen to a specific orientation

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

unlock() method: Unlock screen to default 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.

type attribute: Get current orientation

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

angle attribute: Get orientation angle

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

angle represents how far the user has turned the device counterclockwise from the natural orientation. When the device is rotated 90° counterclockwise, the screen compensates by rotating 90° clockwise, so angle returns 90.

The screen orientation values table shows how the angle changes depending on the how the device is rotated.

The value returned by this property is always in the range 0-359. It never returns negative values.

onchange attribute: Handle orientation changes

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

Extensions to the Document interface

Internal Slots

Internal Slot Description
[[\orientationLock]] The [[\orientationLock]] represents a document's orientation lock as an unordered set of orientationType.
[[\defaultOrientation]] An unordered set of orientations to which the screen orientation is locked when not explicitly locked by this API or any other means.
[[\orientationPendingPromise]] Either null or a promise. When assigned a Promise, that promise represents a request to lock the screen to one of the supported orientations. The promise resolves after locking the orientation succeeds or rejects if locking fails.

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 an [[\orientationPendingPromise]].

Screen orientation types and locks

Landscape-primary is an orientation where the screen width is greater than the screen height. If the device's natural orientation is landscape, then it is in landscape-primary when held in that position. If the device's natural orientation is portrait, the user agent sets landscape-primary from the two options as shown screen orientation values table.

Landscape-secondary is an orientation where the screen width is greater than the screen height. If the device's natural orientation is landscape, it is in landscape-secondary when rotated 180º from its natural orientation. If the device's natural orientation is portrait, the user agent sets landscape-secondary from the two options as shown in the screen orientation values table.

Portrait-primary is an orientation where the screen width is less than or equal to the screen height. If the device's natural orientation is portrait, then it is in portrait-primary when held in that position. If the device's natural orientation is landscape, the user agent sets portrait-primary from the two options as shown in the screen orientation values table.

Portrait-secondary is an orientation where the screen width is less than or equal to the screen height. If the device's natural orientation is portrait, then it is in portrait-secondary when rotated 180º from its natural position. If the device's natural orientation is landscape, the user agent sets portrait-secondary from the two options as shown in the screen orientation values table.

Portrait is an orientation where the screen width is less than or equal to the screen height and depending on platform convention locking the screen to portrait can represent portrait-primary, portrait-secondary or both.

Landscape is an orientation where the screen width is greater than the screen height and depending on platform convention locking the screen to landscape can represent landscape-primary, landscape-secondary or both.

Natural is an orientation that refers to either portrait-primary or landscape-primary depending on the device's usual orientation.

Any is an orientation that means the screen can be locked to any one of portrait-primary, portrait-secondary, landscape-primary and landscape-secondary.

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.

One primary orientation will always be determined by the natural orientation of the device and this will then determine the secondary value of its related orientation.

For example a device held in its natural portrait orientation would have a current orientation of portrait-primary and its portrait-secondary orientation would be its position when rotated 180°.

The user agent can associate the other *-primary and *-secondary values at will. For example, it can be based on the device preferred angles, the user's preferred orientations or the current orientation when the application starts.

The screen orientation values table presents the possible orientation types: portrait-primary, portrait-secondary, landscape-primary and landscape-secondary. The table shows 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.

The screen orientation values table
Natural Orientation Primary Orientation 1 Secondary Orientation 1 Primary Orientation 2 Secondary Orientation 2
Portrait portrait-primary
Angle 0
portrait-secondary
Angle 180
landscape-primary
User agent to set at either Angle 90 or Angle 270
landscape-secondary
Set at the angle not used for landscape-primary
Landscape landscape-primary
Angle 0
landscape-secondary
Angle 180
portrait-primary
User agent to set at either Angle 90 or Angle 270
portrait-secondary
Set at the angle not used for portrait-primary

Once the user agent has set the primary and secondary values from the options in the screen orientation values table, the current orientation type and the current orientation angle relation MUST be kept consistent for any given document.

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.

Locking the screen orientation

The user agent MAY require a document and its associated browsing context to meet one or more pre-lock 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.

The [[\orientationLock]] internal slot represents the document's' orientation lock.

An orientation lock is in place when the screen has successfully been locked to a specific orientation.

Default orientation

The default orientation is the set of orientations to which the screen is locked when there is no current orientation lock.

From 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, this does not mean that the [[\defaultOrientation]] only contains the item any.

Interactions with other specifications

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

Interaction with Fullscreen API

As a pre-lock condition, a user agent MAY restrict locking the screen orientation exclusively to when the top-level browsing context's document's fullscreen element is not null. When that pre-lock condition applies, whenever the document's fullscreen element 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 Web Application Manifest

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

Interaction with CSS Device Adaptation

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

Interaction with Web Content Accessibility Guidelines

The Web Content Accessibility Guidelines includes a Success Criterion related to screen orientation.

​The intent of this Success Criterion is to ensure that all essential content and functionality is available regardless of the display orientation (portrait or landscape). Some websites and applications automatically set the screen to a particular display orientation and expect that users will respond by rotating their device to match.

However, some users may have their devices mounted in a fixed orientation (e.g. on the arm of a power wheelchair). Therefore, websites and applications need to support both orientations by making sure essential content and functionality is available in each orientation. While the order of content and method of functionality may have differences the content and functionality must always be available. When a particular orientation is essential, the user needs to be advised of the orientation requirements.​

Algorithms

Updating orientation algorithm

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 a device is turned 90 degrees on the right, the current orientation angle would be 270 degrees. The screen orientation values table gives the options for each orientation and possible associated angles.

Locking orientation algorithm

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 [[\orientationPendingPromise]] is not null:
      1. Let doc be the document which has a not null [[\orientationPendingPromise]].
      2. Reject doc's [[\orientationPendingPromise]] with DOMException whose name is AbortError.
      3. Set doc's [[\orientationPendingPromise]] 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 pre-lock 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 current orientation angle is 0.
    any
    Append portrait-primary, portrait-secondary, landscape-primary and landscape-secondary to orientations.
  6. Set doc's [[\orientationPendingPromise]] to a newly-created promise.
  7. Return doc's [[\orientationPendingPromise]] 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, as part of the next animation frame task, 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 Screen orientation change algorithm.

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 [[\orientationLock]], 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.

Active orientation lock algorithm

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 [[\orientationLock]].
  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 [[\orientationLock]].
  3. Otherwise, the active orientation lock SHOULD be the latest focused document's [[\orientationLock]], 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 [[\orientationLock]].

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

Screen orientation change algorithm

Whenever the viewport's angle changes, the user agent MUST run the following steps as part of the next animation frame task:

  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.
  3. If the orientation change was triggered by a user gesture such as the user turning the device, as opposed to a call to lock(), the task MUST be annotated with process user orientation change when running the next step.
  4. Fire an event named change at doc's screen.orientation object.
  5. If doc's [[\orientationPendingPromise]] is not null:
    1. Resolve doc's [[\orientationPendingPromise]] with undefined.
    2. Set doc's [[\orientationPendingPromise]] to null .

Whenever a document becomes visible per [[!PAGE-VISIBILITY]], in other words after the now visible algorithm is run, the user agent MUST run the following substeps as part of the next animation frame task:

  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 orientation change was triggered by a user gesture such as the user turning the device, as opposed to a call to lock(), the task MUST be annotated with process user orientation change when running the next step.
    2. Fire an event named change at the document's screen.orientation object.
    3. If the document's [[\orientationPendingPromise]] is not null:
      1. Resolve the document's [[\orientationPendingPromise]] with undefined.
      2. Set the document's [[\orientationPendingPromise]] to null.

An algorithm is triggered by a user generated orientation change if the task in which the algorithm is running is annotated with process user orientation change.

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.

Privacy and Security Considerations

Access to aspects of a user’s local computing environment

The screen orientation type and angle of the device can be accessed with the API specified in this document, and can be a potential fingerprinting vector.

The screen orientation type can already be known by using the screen width and height. In practice, the additional information provided with the API concerning the angle of the device and the primary or secondary screen orientation is unlikely to be used by any competent attack.

Dependencies

The following concepts and interfaces are defined in [[HTML]]: event handler, event handler event type, task, Window, Document, browsing context, top-level browsing context, browsing context's active document, navigated browsing context, active sandboxing flag set, sandboxed orientation lock browsing context flag, responsible document, list of the descendant browsing contexts.

The following is defined in [[FULLSCREEN]]: fullscreen element.

The following is defined in [[PAGE-VISIBILITY]]: now visible algorithm.

The following is defined in [[DOM]]: fire an event, EventTarget

The following is defined in [[WEBIDL]]: promise

The following is used but not defined in [[FULLSCREEN]]: animation frame task.

This should now be updated since the animation frame task issue is recently resolved and the timing is now defined.

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

Acknowledgments

Thanks to Marcos Cáceres, 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.