Copyright © 2024 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
This document specifies an API that allows web applications to request and be notified of changes of the posture of a device.
This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
Vendors interested in implementing this specification before it eventually reaches the Candidate Recommendation phase should subscribe to the repository on GitHub and take part in the discussions.
This document was published by the Devices and Sensors Working Group as a Working Draft using the Recommendation track.
Publication as a Working Draft does not imply endorsement by W3C and its Members.
This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 03 November 2023 W3C Process Document.
The device posture is the physical position in which a device holds which may be derived from sensors in addition to the angle. New types of mobile devices are appearing that have some sort of capabilities that allow them to change their posture. The most common types of devices are the ones that can fold (their screen or around their screen), allowing them to physically alter their form factor. The main interest in knowing the posture of a device is to enable new user experiences with responsive design.
Among the described "folding" devices, there are mainly two different physical form factors: devices with a single flexible screen (seamless), and devices with two screens (with seam). They can both fold around a hinge, and the current specification applies to both types. It should be clarified as well that both seamless and (devices) with seam can be of different dimension ranging from mobile and tablets to laptop sizes. It should also be noted that different devices will have different default orientations (portrait or landscape), and that the fold might happen in a vertical or horizontal way.
From enhancing the usability of a website by avoiding the area of a fold, to enabling innovative use cases for the web, knowing the posture of a device can help developers tailor their content to different devices.
Content can be consumed and browsed even when the device is not flat, in which case the developer might want to provide a different layout for it depending on the posture state in which the device is being used.
The following internal slots are added to the Document
interface.
Internal slot | Description |
---|---|
[[CurrentPosture]] | The device's current posture. |
WebIDL[SecureContext, Exposed=(Window)]
interface DevicePosture
: EventTarget {
readonly attribute DevicePostureType
type
;
attribute EventHandler onchange
;
};
enum DevicePostureType
{
"continuous
",
"folded
"
};
When getting the type attribute, the user agent MUST return the value
of this's relevant global object's associated Document's
internal slot [[CurrentPosture]]
.
The onchange
attribute is an event handler IDL attribute
for the onchange
event handler, whose event handler event type is "change".
This specification defines the following posture values:
Continuous posture: The continuous posture refers to a "flat" position. This is the default case for most devices not allowing different postures.
It includes devices with no folds, hinges or similar capabilities.
Due to the nature of hardware innovation, it also includes devices
with dual, foldable, rollable or curved screens, as long as they
are in a posture where the Document
is expected to be displayed
with a flat layout.
Examples of these are:
In some cases, devices can run several apps and be in a physical posture other than flat, but as long as the browser does not span through several screens/sections, the corresponding posture is continuous.
Examples of these are:
When a foldable is used in a half-folded state (like a book), implementers might need to take into account the effect of text direction and writing mode on the layout and presentation.
For example, right-to-left languages (those that use scripts such as Arabic, Hebrew, Syriac, and others) and many vertical writing modes used by, for example, East Asian languages progress pages in the opposite order to that used by an English book, with the lower numbered page on the right.
See Chinese, Japanese, and Korean differences in writing modes for more information.
In the API, the posture values are represented by the
DevicePostureType
enum values.
The
media feature represents, via a CSS
media query [MEDIAQ], the posture of the device. All
navigables reflect the posture of their
top-level traversable.
device-posture
continuous
| folded
A user agent MUST reflect the applied posture of the web application via a CSS media query [MEDIAQ].
Every instance of Document
has an internal slot
[[CurrentPosture]]
, which 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 run the device posture change steps with document set to the Document
and disallowRecursion set to true to initialize it.
For a given Document
, the current posture is derived from
the current hinge angle and the screen orientation,
and potentially other implementation-specific signals.
These tables are non-normative.
The values are approximations and might differ per device. For instance, a device might not yield exactly 180° when laying flat, but instead values ranging from 175° to 185°. Device makers SHOULD make sure that the physical device postures map correctly to the postures defined by this specification. Device makers are also allowed to determine the posture using more sensors than just the hinge angle. For example, they can also detect if keyboard is docked on the bottom half of the screen or not. Another example is to detect whether the kickstand is deployed or not.
Some devices might also lack one or more of the postures due to physical constraints or device design, in which case the device SHOULD make sure that all combinations of angles and device orientation (which can be locked by [SCREEN-ORIENTATION] and host OS), as well as device specific signals, maps into one of the defined postures.
Posture | Angle value |
---|---|
continuous | < ~180° |
folded | ~180° |
The steps to calculate the device posture information of a
Document
document are as follows:
DevicePostureType
value determined in an
implementation-defined way based on the current hinge angle
value, current screen orientation,
as well as potential implementation-specific signals, according to
the posture values table.
When the user agent determines that the screen(s)' fold angle, orientation or device-specific signals have changed for a top-level traversable, it MUST run the device posture change steps with the top-level traversable's active document.
The device posture change steps for a Document
document and an
optional boolean disallowRecursion (default false)
are as follows:
[[CurrentPosture]]
, abort these steps.
[[CurrentPosture]]
to posture.
change
" at the
DevicePosture
object associated with document's relevant global object's associated Navigator
.
This specification defines the following page visibility change steps given visibility state and document:
From https://html.spec.whatwg.org/#update-the-visibility-state
It would be better if specification authors sent a pull request to add calls from here into their specifications directly, instead of using the page visibility change steps hook, to ensure well-defined cross-specification call order. As of the time of this writing the following specifications are known to have page visibility change steps, which will be run in an unspecified order: Device Posture API and Web NFC. [DEVICEPOSTURE] [WEBNFC]
No new security considerations have been reported on this specification.
This section is non-normative.
When this API is used simultaneously in different browsing contexts on the same device it may be possible to correlate the user across those two contexts, creating unanticipated tracking mechanisms. However, because the posture value is typically stable for a long time it could only be used to verify that two users are not the same, but it would not help to identify a given user given the fact that there are multiple types and models of foldable devices.
The added entropy is comparable to the pointer API which tells whether the user's primary input is touch-based or not. Such a primary input can change on devices where the keyboard can be removed/added or the tablet mode is activated/deactivated.
This theoretical attack is mitigated by 10.2.1 Data minimization, 10.2.2 User attention and 10.2.3 User-mediated action.
Cross-origin iframes have access to the posture through this API and therefore could use this information to identify users similarly to as mentioned in 10.1.1 Identifying users across contexts. The same mitigations apply.
One question I have is the value of exposing the posture to iframes. I'll be happy to hear use cases where it could be useful.
In Chromium right now, Device Posture CSS MQs and JS API are exposed to iframes. Viewport Segments are exposed to iframe through CSS MQs (and working), but the JS APIs (visual viewport segments
property) is defined but returns null.
In most cases the embedder will react to the posture/viewport segments changes and move the iframe around (for example to avoid the iframe being in the fold).
I'm not sure the iframe itself needs all the information. For example, in Chromium, the viewport segments are not recalculated relatively to the iframe coordinate space, so the values make little sense. The only use case I can think of is if the iframe is basically the size of the viewport and then all of the data make sense.
Thoughts?
The API exposes a high-level abstraction referred to as a
posture that can be either
"continuous
" or
"folded
". Devices that do not support
different postures default to "continuous
".
This means at most one bit of entropy is added to the fingerprint.
At most, because revealing this one bit will require a significant,
explicit physical action by the user to manipulate the physical
posture of the device required to trigger a change.
While implementations can use a variety of low-level information to determine the most appropriate high-level posture, no low-level details are exposed through this API. Furthermore, there is no one-to-one mapping from any fine-grained low-level sensor reading to a high-level posture state. An implementation can use e.g. a hinge angle sensor, other sensors, information about whether a keyboard is docked, or whether the kickstand is deployed, or any combination of such information, to determine the most approriate posture for the given form factor. This abstraction ensures only a minimum amount of information necessary to implement the intended functionality is exposed adhering to the data minimization principles.
Posture value change events are only fired for each active document whose visibility state is "visible" as explained in device posture change steps, and polling the value while that is not the case, will return a stale value as the value is only updated while the visibility state is "visible" or just changed to "visible".
A user's significant and explicit physical action to modify the device posture is required for a posture change. Significant, because the action must cross the implementation-defined threshold per posture values table, and explicit, because the underlying operating system adapts to posture changes similarly matching user's learned expectations for an outcome of such an action.
Window
. If the device is folded, the
element will be laid out across the fold, leading to a subpar user
experience. An alternative is to display that element either on top
or below the fold area.
posture
: The idea of foldable devices is their
versatility and the ability for the user to change the posture as
they see fit. Similarly to the orientation,
it is important to not always choose for the user as they might have
other needs but allowing them to choose the UI that fits their needs
better. Ideally it is preferred to make the UI configurable.
The Device Posture API pose a challenge to test authors, as fully exercising interface requires physical hardware devices. To address this challenge this document defines a [WEBDRIVER2] extension commands that allows users to control the reported device posture and simulate a real device.
To support the extension commands below and their integration with 8. Algorithms, top-level traversables must have the following internal slots:
Internal slot | Description |
---|---|
[[PostureOverride]] |
Overrides the current posture provided by the hardware.
Possible values:
|
HTTP Method | URI Template |
---|---|
POST | /session/{session id}/deviceposture |
This extension command changes device posture to a specific
DevicePostureType
.
Parameter name | Value type | Required |
---|---|---|
posture | String | yes |
The remote end steps are:
continuous
" nor
"folded
", return error with WebDriver error code invalid argument.
null
.
HTTP Method | URI Template |
---|---|
DELETE | /session/{session id}/deviceposture |
This extension command removes device posture override and returns device posture control back to hardware.
The remote end steps are:
null
, return success
with data null
.
null
.
null
.
This section is non-normative.
This is a simple use case of the posture being printed on the console.
navigator.devicePosture.addEventListener("change", () => {
console.log(`The current posture is: ${navigator.devicePosture.type}!`);
})
The device is being used for a video call web service. It can be folded into the laptop posture to enable a hands-free when placed on a surface. The UA detects the posture and the UI is enhanced. Similar examples can be drafted for content to adapt to any posture. See the explainer for other key scenarios.
@media (device-posture: folded) and (vertical-viewport-segments: 2) {
body {
display: flex;
flex-flow: column nowrap;
}
.videocall-area, .videocall-controls {
flex: 1 1 env(viewport-segment-bottom 0 0);
}
}
As one of the valid device-posture values will always be true, you can use the following snippet to detect whether a user agent supports the media feature:
@media (device-posture) {
/*The browser supports device-posture feature*/
}
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MUST and SHOULD in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
This specification defines conformance criteria for a single product: a user agent that implements the interfaces that it contains.
WebIDL[SecureContext, Exposed=(Window)]
partial interface Navigator {
[SameObject] readonly attribute DevicePosture
devicePosture
;
};
[SecureContext, Exposed=(Window)]
interface DevicePosture
: EventTarget {
readonly attribute DevicePostureType
type
;
attribute EventHandler onchange
;
};
enum DevicePostureType
{
"continuous
",
"folded
"
};
This section is non-normative.
We would like to offer our sincere thanks to Daniel Appelquist, Jo Balletti, Michael Blix, Paul Grenier and Laura Morinigo for their contributions to this work.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: