env() — Safe Areas & Environment Variables
Modern phones have notches, camera cutouts, home-indicator bars, and rounded corners that eat into the usable screen area. The env() function exposes these device-specific safe measurements to CSS, so a fixed header or footer can avoid being cut off or overlapped by hardware and system UI.
The four safe-area-inset values
Variable | Protects against |
|---|---|
| Notches, camera cutouts, and status bars at the top |
| Rounded corners / notches in landscape orientation |
| The home-indicator bar on notched iPhones |
| Rounded corners / notches in landscape orientation |
.app-footer {
padding-bottom: env(safe-area-inset-bottom);
}
.app-header {
padding-top: env(safe-area-inset-top);
}env(safe-area-inset-*) values are all zero unless the page opts in to actually drawing under the notch/home indicator in the first place, via the viewport meta tag.<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
viewport-fit=cover tells the browser "let my content extend edge-to-edge," which is exactly when the insets become non-zero and meaningful.Combining insets with existing spacing
A fixed footer usually already has its own padding for visual breathing room — the safe-area inset needs to be added on top of that, not replace it, otherwise content sits flush against the safe-area boundary with no spacing on devices that have zero inset (most Android phones, older iPhones).
.app-footer {
/* calc() combines a fixed design spacing value with the dynamic inset */
padding-bottom: calc(16px + env(safe-area-inset-bottom));
}
/* max() is often cleaner: takes whichever is larger */
.app-footer-alt {
padding-bottom: max(16px, env(safe-area-inset-bottom));
}Approach | Result on a notch-free device | Result on a notched device |
|---|---|---|
| 16px padding | 16px + inset padding |
| 16px padding | whichever is larger — inset if it exceeds 16px |
Fallback values
env() accepts a second argument as a fallback for browsers or contexts where the environment variable is not defined at all (not just zero — truly absent).
.app-footer {
padding-bottom: env(safe-area-inset-bottom, 16px);
}titlebar-area for installed PWAs
Desktop PWAs that customize their own title bar (via the window-controls-overlay display mode) get additional env() variables describing the space the operating system reserves for window controls, so custom title bar content doesn't overlap the minimize/maximize/close buttons.
.custom-titlebar {
position: fixed;
top: env(titlebar-area-y, 0);
left: env(titlebar-area-x, 0);
width: env(titlebar-area-width, 100%);
height: env(titlebar-area-height, 33px);
}Full example: a notch-safe app shell
.app-shell {
display: flex;
flex-direction: column;
min-height: 100dvh;
}
.app-header {
padding: max(12px, env(safe-area-inset-top))
max(16px, env(safe-area-inset-right))
12px
max(16px, env(safe-area-inset-left));
}
.app-content {
flex: 1;
padding-inline: max(16px, env(safe-area-inset-left))
max(16px, env(safe-area-inset-right));
}
.app-footer {
padding: 12px
max(16px, env(safe-area-inset-right))
max(12px, env(safe-area-inset-bottom))
max(16px, env(safe-area-inset-left));
}Add
viewport-fit=coverto the viewport meta tag first — without it every inset stays zeroCombine insets with
max()(design spacing vs device inset) rather than replacing your normal paddingAlways provide a fallback value for browsers that do not support a given
env()variableTest on an actual notched device or the browser DevTools device toolbar with a notched preset — the insets are invisible on a desktop simulator without one
Testing without a physical notched device
Not every developer has an iPhone with a notch on hand. Chrome DevTools lets you simulate the safe-area insets directly, without a physical device, through its device toolbar sensor emulation.
Open DevTools → toggle the device toolbar (Ctrl/Cmd+Shift+M)
Choose a notched device preset from the dropdown (e.g. an iPhone model with a notch)
Reload the page — the emulated device profile reports the expected safe-area-inset values
Confirm your fixed header/footer padding grows appropriately in the emulated notch area
Other env() use cases beyond safe areas
Safe-area insets are the most common use of env(), but the function itself is a general mechanism for exposing browser/OS environment values to CSS — more variables have been proposed and shipped for specific platform integrations over time.
Variable | Context |
|---|---|
safe-area-inset-* | Notches, home indicators, rounded corners on mobile |
titlebar-area-* | Custom title bar space in installed PWAs using window-controls-overlay |
keyboard-inset-* | Proposed: space taken up by an on-screen virtual keyboard |
env() variable with a sensible fallback value, and verify actual support before depending on it for anything critical.