![Alexis Menard](https://web.dev/images/authors/alexismenard.jpg) Alexis Menard [X](https://twitter.com/darktears) [GitHub](https://github.com/darktears) ![Thomas Steiner](https://web.dev/images/authors/thomassteiner.jpg) Thomas Steiner [GitHub](https://github.com/tomayac) [LinkedIn](https://www.linkedin.com/in/thomassteinerlinkedin) [Mastodon](https://toot.cafe/@tomayac) [Bluesky](https://bsky.app/profile/tomayac.com) [Homepage](https://blog.tomayac.com/)

<br />

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.

> [!NOTE]
> **Note:** These APIs were developed during the past few years in collaboration with Microsoft, Intel, Samsung, and Google.

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.](https://developer.chrome.com/static/blog/foldable-apis-ot/origintrialfor--n9jyqlkzs6.png)

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.](https://developer.chrome.com/static/blog/foldable-apis-ot/origintrialfor--72p8u41jozf.png)

- `continuous`: Flat, tablet, or even seamless curved displays.

![Schematic drawing of devices in laptop or book postures.](https://developer.chrome.com/static/blog/foldable-apis-ot/origintrialfor--8remnu094pv.png)

### CSS

The Device Posture API specification defines a new CSS
media-feature---[device-posture](https://www.w3.org/TR/device-posture/#the-device-posture-media-feature).
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:

```css
/* 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.

```javascript
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.

```javascript
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.](https://developer.chrome.com/static/blog/foldable-apis-ot/origintrialfor--eaocssmg9t.png) 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.

```html
<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.](https://developer.chrome.com/static/blog/foldable-apis-ot/origintrialfor--0q2yl8eip1da.png)

![Foldable phone in horizontal book posture.](https://developer.chrome.com/static/blog/foldable-apis-ot/origintrialfor--720mkhgdpf.png)

![Foldable tablet in horizontal book posture.](https://developer.chrome.com/static/blog/foldable-apis-ot/origintrialfor--vlejcdqk5rg.jpg)

### JavaScript

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

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

> [!NOTE]
> **Note:** During the origin trial, `window.visualViewport.segments` will work. The final shape of the API still needs to be determined, as per the [CSS Working Group's discussion](https://github.com/w3c/csswg-drafts/issues/9237#issuecomment-2160730855).

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](https://developer.chrome.com/origintrials#/view_trial/4188910603407982593)
from Chrome 125 through Chrome 128. See
[Get started with origin trials](https://developer.chrome.com/docs/web-platform/origin-trials.md.txt)
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](https://github.com/foldable-devices/demos). 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.](https://developer.chrome.com/static/blog/foldable-apis-ot/origintrialfor--3liyahcdkkl.png)

## Related links

- **Device Posture API**
  - [Mozilla Position](https://github.com/mozilla/standards-positions/issues/882)
  - [WebKit Position](https://github.com/WebKit/standards-positions/issues/328)
  - [Chrome Status Entry](https://chromestatus.com/feature/5185813744975872)
  - [W3C Specification](https://www.w3.org/TR/device-posture/)
- **Viewport Segments API**
  - [Mozilla Position](https://github.com/mozilla/standards-positions/issues/883)
  - [WebKit Position](https://github.com/WebKit/standards-positions/issues/327)
  - [Chrome Status Entry](https://chromestatus.com/feature/5170498990243840)
  - [W3C CSS Media Query Specification](https://www.w3.org/TR/mediaqueries-5/#mf-horizontal-viewport-segments) and [W3C CSS Environment Variable Specification](https://drafts.csswg.org/css-env-1/#viewport-segments)