Origin trial for Foldable APIs

Chrome is trialing two APIs, the Device Posture API and the Viewport Segments Enumeration API, which are available as an origin trial from Chrome 125. These are known collectively as the Foldable APIs, designed to help developers target foldable devices. This post introduces these APIs, and provides information about how to start testing them.

There are mainly two different physical form factors: devices with a single flexible screen (seamless), and devices with two screens (with seam, also known as dual screen devices).

Schematic drawing of a device with a single flexible screen (seamless) on the left, and a device with two screens (with seam, also known as dual screen) on the right.

These devices present challenges and opportunities to developers. They provide additional ways in which content can be viewed. For example, a user might hold a seamless device like a book and then change to using it like a tablet with a flat screen. Devices with two screens have a physical join between the screens that may need to be accounted for.

These new APIs provide ways for developers to provide better user experiences for these devices. Each API exposes the needed web platform primitives in two ways, through CSS and JavaScript.

Device Posture API

Foldable devices have capabilities that allow them to change their_ posture_, or the physical state of the device. They can change their form factor allowing content authors to provide a different user experience, and these new APIs make sure web content can react to the various folding states.

There are two device postures a device can be in:

  • folded: Laptop or book postures.

Schematic drawing of devices in flat or tablet postures, and a seamless curved display.

  • continuous: Flat, tablet, or even seamless curved displays.

Schematic drawing of devices in laptop or book postures.

CSS

The Device Posture API specification defines a new CSS media-feature—device-posture. This media feature resolves to a set of fixed postures. These postures consist of a number of predefined values that each encompass a physical state of the device.

The values of the device-posture feature match the previous description of possible postures:

  • folded
  • continuous

New postures could be added in future if new devices come to the market.

Examples:

/* Using the device in a 'book' posture. */
@media (device-posture: folded) { ... }

/* Using the device in a 'flat' posture, or any typical device like a laptop or
desktop device. */
@media (device-posture: continuous) { ... }

JavaScript

To query a device's posture, a new DevicePosture object is available.

const { type } = navigator.devicePosture;
console.log(`The current device is of type ${type}.`);

To react to device posture changes, such as a user fully opening a device and therefore moving from folded to continuous, subscribe to change events.

navigator.devicePosture.addEventListener('change', (e) => {
  console.log(`The device posture changed to type ${e.type}`);
});

Viewport Segments API

The viewport segments are CSS environment variables that define the position and dimensions of a logically separate region of the viewport. Viewport segments are created when the viewport is split by one or more hardware features (such as a fold or a hinge between separate displays) that act as a divider. Segments are the regions of the viewport that can be treated as logically distinct by the author.

CSS

The number of logical divisions are exposed through two new media features, defined in the CSS Media Queries Level 5 specification: vertical-viewport-segments and horizontal-viewport-segments. They resolve to the number of segments the viewport is broken into.

In addition new environment variables have been added to query the dimensions of each logical division. These variables are:

  • env(viewport-segment-width x y)
  • env(viewport-segment-height x y)
  • env(viewport-segment-top x y)
  • env(viewport-segment-left x y)
  • env(viewport-segment-bottom x y)
  • env(viewport-segment-right x y)

Each variable has two dimensions, which represent the x and y position, respectively, in the two-dimensional grid created by the hardware features separating the segments.

Diagram showing horizontal and vertical segments. The first horizontal segment is x 0 and y 0, the second x 1 and y 0. The first vertical segment is x 0 and y 0, the second x 0 and y 1.
The first horizontal segment is x 0 and y 0, the second x 1 and y 0. The first vertical segment is x 0 and y 0, the second x 0 and y 1.

The following code snippet is a simplified example of creating a split UX where we have two content sections (col1 and col2) on each side of the fold.

<style>
  /* Segments are laid out horizontally. */
  @media (horizontal-viewport-segments: 2) {
    #segment-css-container {
      flex-direction: row;
    }

    #col1 {
      display: flex;
      flex: 0 0 env(viewport-segment-right 0 0);
      background-color: steelblue;
    }

    #fold {
      width: calc(env(viewport-segment-left 1 0) - env(viewport-segment-right 0 0));
      background-color: black;
      height: 100%;
    }

    #col2 {
      display: flex;
      background-color: green;
    }
  }

  /* Segments are laid out vertically. */
  @media (vertical-viewport-segments: 2) {
    #segment-css-container {
      flex-direction: column;
    }

    #col1 {
      display: flex;
      flex: 0 0 env(viewport-segment-bottom 0 0);
      background-color: pink;
    }

    #fold {
      width: 100%;
      height: calc(env(viewport-segment-top 0 1) - env(viewport-segment-bottom 0 0));
      background-color: black;
    }

    #col2 {
      display: flex;
     background-color: seagreen;
    }
  }
</style>

<div id="segment-css-container">
   <div id="col1"></div>
   <div id="fold"></div>
   <div id="col2"></div>
 </div>

The following photos show what the experience looks like on a physical device.

Foldable phone in vertical book posture.

Foldable phone in horizontal book posture.

Foldable tablet in horizontal book posture.

JavaScript

To get the number of viewport segments, check the segments entry in the visualViewport.

const segments = window.visualViewport.segments;
console.log('The viewport has the following segments:', segments);

Each entry in the segments array represents each logical segment of the viewport with a DOMArray describing the coordinates and size. The segments field is a snapshot of the given state when queried, in order to receive updated values you need to listen to posture changes or resize events and requery the segments property.

Try the Foldable APIs

The Foldable APIs are available in an origin trial from Chrome 125 through Chrome 128. See Get started with origin trials for background information on origin trials.

For local testing, the Foldable APIs can be enabled with the Experimental Web Platform features flag at chrome://flags/#enable-experimental-web-platform-features. It can also be enabled by running Chrome from the command line with --enable-experimental-web-platform-features.

Demos

For demos, see the demos repository. If you don't have a physical device to test with, you can choose the Galaxy Z Fold 5 or Asus Zenbook Fold emulated device in Chrome DevTools and flip between Continuous and Folded. You can also visualize the hinge when applicable.

Chrome DevTools emulating a foldable device.