Chrome on Android edge-to-edge migration guide

Published: Feb 28, 2025

Edge-to-edge is an Android feature that lets applications span the entire width and height of the display by drawing behind the Android system bars.

Before Chrome 135, Chrome on Android did not draw edge-to-edge. This guide explains the effect this change has on websites and what you as a developer can do to embrace this change.

Bars everywhere

Android comes with system bars provided by the operating system itself.

Together, the status bar, caption bar, and navigation bar are called the system bars. They display important information such as battery level, the time, and notification alerts, and provide direct device interaction from anywhere.

At the top of the screen you can find the status bar, which contains notification icons and system icons.

Illustration of the top part of an Android device with the system bar highlighted.
The status bar on Android highlighted (source).

At the bottom of the screen you can find the navigation bar, which lets you control navigation using back, home, and overview controls. This can be the classic three-button navigation or the modern gesture navigation bar.

Illustration of the bottom part of an Android device with the gesture navigation bar visible.
The gesture navigation bar (source).

In addition to the Android system bars, Chrome itself comes with an address bar which dynamically expands and retracts itself as you scroll.

Chrome goes edge-to-edge

When you visit a website, that website gets presented in a rectangle known as the (layout) viewport.

In Chrome on Android, prior to Chrome 135, that layout viewport is drawn between the top status bar and the bottom gesture navigation bar. The presence of Chrome's address bar (or lack thereof) can affect the size of the viewport, but the viewport will never expand into the top system bar or bottom gesture navigation bar.

Illustrations of an Android device with Chrome on Android that is not edge-to-edge. The illustration on the left shows Chrome with the address bar expanded. Sitting between the address bar and the gesture navigation bar is a box highlighted in green whose size is 100svh. The illustration on the right shows Chrome with the address bar retracted. Sitting between the status bar and the gesture navigation bar is a box highlighted in green whose size is 100lvh. The viewport itself has a dashed blue outline.
The minimum and maximum size of the viewport in Chrome on Android prior to Chrome 135. These sizes are known as the small and large viewport. The viewport itself has a dashed blue outline.

From Chrome 135, the viewport is allowed to extend into Android's gesture navigation bar. This is the behavior described as edge-to-edge.

Illustrations of the viewport in Chrome on Android that is not edge-to-edge (on the left) and in Chrome on Android that is edge-to-edge (on the right). Each visualization has a blue box that represents an element that is sized to a height of 100vh. The text on the left clarifies what happens when chrome is not edge-to-edge. It reads 'The viewport remains clamped between the top status bar and bottom gesture navigation bar'. The text on the right clarifies what happens when chrome is edge-to-edge. It reads 'The viewport extends into the gesture navigation bar'.
The large viewport shown in Chrome on Android that is not edge-to-edge (left) and in Chrome that is edge-to-edge (right). In Chrome with edge-to-edge support, the viewport extends into the gesture navigation bar area when Chrome's dynamic toolbars are retracted.

Chrome behavior without edge-to-edge

The following recording shows Chrome on Android without edge-to-edge support, Chrome's address bar (at the top) dynamically gets out of the way as the page is scrolled. However, the Android-native top status bar and Android-native navigation bar at the bottom remain fixed in place.

Old behavior: Chrome on Android without edge-to-edge support and https://developer.chrome.com/ loaded.

Here, the size of the layout viewport changes as Chrome's address bar retracts or expands.

Chrome behavior with edge-to-edge

From Chrome 135, Chrome can draw web content up to the bottom device edge by extending the viewport into the gesture navigation bar area.

Dynamic edge-to-edge with "the chin"

By default, Chrome edge-to-edge shows a new dynamic bottom bar known as "the chin" over the gesture navigation bar area. Just like the Chrome address bar, this chin moves out of the way as you start scrolling and affects the size of the viewport.

In the following recording of Chrome on Android with edge-to-edge support, both the Chrome address bar and chin dynamically retract as the page scrolls down. This causes the viewport to expand, allowing web content to be drawn up to the bottom edge of the device.

New behavior: Chrome on Android with edge-to-edge support and https://developer.chrome.com/ loaded. Notice how the bottom chin slides out of the way as page scrolls.

This chin behavior is the new default Chrome behavior from Chrome 135 onwards.

Going edge-to-edge by default with an opt-in

Websites that were built for edge-to-edge can indicate that by tweaking the viewport meta tag. When enabled, the viewport will extend up to the bottom edge by default without the chin ever being visible.

New behavior with edge-to-edge opt-in: The viewport extends up to the bottom edge upon page load. No chin is present.

A page can indicate it supports edge-to-edge using the viewport meta tag and its viewport-fit key.

To opt-in to edge-to-edge, set viewport-fit to the value of cover.

<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />

Learn more about the various values of viewport-fit on MDN.

Dealing with content that might get obstructed by the gesture navigation bar

In edge-to-edge mode you should consider any content that might get obstructed by the gesture navigation bar.

In most cases, you won't need to do anything because the bottom chin moves out of the way by itself. Users can still reach all content on your website like they did before.

However, if you opt-in to going edge-to-edge by default or you have an element that is positioned at the bottom of the viewport, you may need to account for that content potentially being covered.

.stuck-to-the-bottom-of-the-viewport {
  position: fixed;
  bottom: 0;
}

When the chin is present, the content will initially be reachable by users but will get obstructed by Android's navigation bar as the chin goes away.

Illustrations of an Android device with Chrome on Android that is edge-to-edge. The illustration on the left shows Chrome with the chin visible. The bottom-anchored content (shown in red) sits just on top of it. The illustration on the right shows Chrome with the chin not visible. There, the bottom anchored content sits against the bottom edge of the device. The text along with it clarifies that bottom-positioned content is now obstructed by the gesture navigation bar.
Illustration of a website with a bottom-positioned element with `bottom: 0`. When the chin is visible, the bottom-positioned element sits above Android's navigation bar. When the chin has moved away, the element gets positioned behind Android's navigation bar which partially obscures it at that point.

To mitigate, use the safe area insets to either always position the affected elements above the Android-native bottom gesture navigation bar, or to have their background extend into that area.

The safe area insets

Browser Support

  • Chrome: 69.
  • Edge: 79.
  • Firefox: 65.
  • Safari: 11.

Source

The safe area insets are four environment variables that define a rectangle by its top, right, bottom, and left insets from the edge of the viewport.

Combined these four values form the safe area rectangle in which it is safe to place content so that it does not get obstructed by things such as the Android gesture navigation bar.

Illustration of an Android device with Chrome in edge-to-edge mode. The chin has slide out view. Shown inside Chrome is the safe area retangle, painted in yellow. Its bottom edge sits just above the gesture navigation bar. Painted in the gesture navigation bar is the bottom part of the viewport, painted in blue. The text along with it reads that the safe area rectangle is inset in the viewport by the safe-area-bottom-inset which prevents content from getting painted underneath the gesture navigation bar.
Illustration of Chrome in edge-to-edge mode with the viewport and the safe area rectangle painted in yellow. Because the chin is retracted, the safe area bottom inset prevents the safe area rectangle from reaching into the gesture navigation bar. As a result you see the viewport peek from underneath that gesture navigation bar.

Using the safe area bottom inset

For elements that are positioned at the bottom of the viewport, use the safe-area-inset-bottom as the value for the bottom property to prevent it from getting positioned underneath the gesture navigation bar. The value returned by safe-area-inset-bottom gets dynamically updated as the chin moves out of the way, resulting in the bottom-positioned elements nicely staying above Android's gesture navigation bar.

.stuck-to-the-bottom-of-the-viewport {
  position: fixed;
  bottom: env(safe-area-inset-bottom, 0px);
}
Illustration of an Android device with Chrome in edge-to-edge mode. In the visualization on the left the Chin is visible and the bottom-anchored content sits just above it. In the visualization on the right the chin is not visible and the bottom-anchored content is positioned at the same place as one the left. This causes regular content to be visible from underneath the gesture navigation bar.
Illustrations of a website with a bottom-positioned element that uses the bottom safe area inset with the bottom property. When the chin is visible, the bar sits above Android's gesture navigation bar. When the chin goes away, the element also sits above it.

As you can see in the illustrations, the outcome is not perfect yet: when the chin is moved out of the way, the remaining page content becomes visible in the gesture navigation bar area. This is because in this state the viewport extends into the gesture navigation bar area.

To prevent content from getting painted underneath bottom-anchored content, a commonly used approach is to set the padding-bottom to the safe-area-inset-bottom. That way the bottom-anchored element automatically grows as the chin hides itself. While this does work, this approach is not recommended as it results in layout thrashing while the chin moves out of the way.

Don't set the padding to a safe-area-inset value.

.stuck-to-the-bottom-of-the-viewport {
  position: fixed;
  bottom: 0;
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

Using the safe area bottom inset and the safe area bottom maximum inset

Instead, the recommended approach is to use a combination of safe-area-inset-bottom and safe-area-max-inset-bottom. Unlike the dynamic safe-area-inset-bottom which dynamically updates as the chin moves out of the way, the safe-area-max-inset-bottom represents the maximum value of the safe-area-inset-bottom.

Use this safe-area-max-inset-bottom to grow the bottom-anchored element upfront, and combine it with safe-area-inset-bottom to pull the element down so that it sits behind the chin.

Use the safe-area-max-inset-bottom in combination with the safe-area-inset-bottom

:root {
  --safe-area-max-inset-bottom: env(safe-area-max-inset-bottom, 36px);
  --bottom-bar-height: 50px;
}

.stuck-to-the-bottom-of-the-viewport {
  position: fixed;
  bottom: 0;
  height: var(--bottom-bar-height);
  padding-bottom: var(--safe-area-max-inset-bottom);
  bottom: calc(env(safe-area-inset-bottom, 0px) - var(--safe-area-max-inset-bottom));
}

body {
  padding-bottom: calc(var(--bottom-bar-height) + var(--safe-area-max-inset-bottom));
}

Try a live demo

The visual result is the same as the padding-bottom: env(safe-area-inset-bottom, 0px); approach but it performs much better. Because only the computed value for bottom needs to change as the chin moves away, no layout thrashing occurs.

Illustration of an Android device with Chrome in edge-to-edge mode. In the visualization on the left the Chin is visible and the bottom-anchored content sits just above it. In the visualization on the right the chin is not visible and the bottom-anchored content visually grew to take up the space where the chin originally was. This results in a nice visual effect and prevents regular page content from becoming visible from underneath the gesture navigation bar area.
Illustrations of a website with a bottom-anchored element that takes the safe area insets into account. When the chin is visible (left) the element sits above the chin. When the chin is not visible, the element visually bleeds into Android's gesture navigation bar.

Try out edge-to-edge before Chrome 135

To try edge-to-edge before its public stable release, you need to enable quite a few Chrome feature flags through chrome://flags:

  • EdgeToEdgeBottomChin (optionally set it to "Enabled Debug" will color half the chin in pink to more clearly distinguish it from other UI)
  • DrawCutOutEdgeToEdge
  • BottomBrowserControlsRefactor (don't set to "Enabled" but set to "Enabled Dispatch yOffset")
  • DynamicSafeAreaInsets
  • DynamicSafeAreaInsetsOnScroll
  • EdgeToEdgeWebOptIn
  • DrawKeyNativeEdgeToEdge
  • EdgeToEdgeSafeAreaConstraint (don't set to "Enabled" but set to "Enabled Scrollable Variation")

Make sure the following flags are not enabled:

  • DrawNativeEdgeToEdge
  • EdgeToEdgeEverywhere

Restart Chrome twice.

We want your feedback

If you have feedback on Chrome and its edge-to-edge implementation, please reach out to us by filing a Chromium bug in the "UI > Browser > Mobile > EdgeToEdge" component. We appreciate your feedback.