Stacked mobile devices with text the reads CSS ENV()

CSS Has Environment Variables Now

Here's What You Need to Know About env()

JS
Jesse Stewart
Feb 20, 20263 min read

CSS is developing faster than most of us can keep up. One feature I recently discovered: the env() CSS function. Yes, there are environment variables in CSS, similar to what you'd use in Node.js.

TL;DR

CSS env() gives you access to browser-provided environment variables — safe area insets for notches and rounded screens, titlebar dimensions for desktop PWAs, keyboard insets for virtual keyboards, and viewport segments for foldable devices. But it doesn't stop there. With PostCSS, you can define your own environment variables in a single shared module and use them in both CSS and TypeScript — eliminating the "I updated it in one place but forgot the other" class of bugs entirely. The safe area insets have universal browser support today, the other browser-provided variables are landing in Chromium, and custom env variables work anywhere PostCSS does. If you're building for the modern web, env() should be in your toolkit.

The Syntax

Loading...

Simple. Clean. Two arguments — the variable name and an optional fallback value for when the variable isn't defined (or equals zero).

All Available Environment Variables

There are more env() variables than you might expect. Here's the full list from the spec.

Safe Area Insets (widely supported)

  • safe-area-inset-top
  • safe-area-inset-right
  • safe-area-inset-bottom
  • safe-area-inset-left

These are the OGs — the reason env() exists. They represent the space between the edge of the viewport and the area of the screen that's actually safe to render content in. They ensure your web content isn't obscured by device-specific UI elements like display notches (hello, iPhone), rounded screen corners, and system navigation bars (gesture bars on Android, the Dynamic Island on newer iPhones, etc.).

Loading...

safe-area-inset Demo

There are also static max counterparts in the spec:

  • safe-area-max-inset-top
  • safe-area-max-inset-right
  • safe-area-max-inset-bottom
  • safe-area-max-inset-left

These represent the maximum value the dynamic insets could ever reach — useful when you want to reserve space for a retractable system bar even when it's currently hidden. Limited browser support for now.

Titlebar Area (Chromium, for desktop PWAs)

  • titlebar-area-x
  • titlebar-area-y
  • titlebar-area-width
  • titlebar-area-height

These kick in when your PWA uses the window-controls-overlay display override in its manifest. They let you position content where the title bar would normally be, while keeping it clear of the minimize/maximize/close buttons:

Loading...

titlebar-area Demo

Keyboard Insets (Chromium, VirtualKeyboard API)

  • keyboard-inset-top
  • keyboard-inset-right
  • keyboard-inset-bottom
  • keyboard-inset-left
  • keyboard-inset-width
  • keyboard-inset-height

These provide the position and dimensions of the on-screen virtual keyboard relative to the viewport. If you've ever built a chat input that gets buried behind the keyboard on mobile, these are your fix:

Loading...

keyboard-inset Demo

Note: these require opting into the VirtualKeyboard API via JavaScript (navigator.virtualKeyboard.overlaysContent = true).

Viewport Segments (experimental, for foldables)

  • viewport-segment-top
  • viewport-segment-right
  • viewport-segment-bottom
  • viewport-segment-left
  • viewport-segment-width
  • viewport-segment-height

These are for multi-screen and foldable devices (think Samsung Galaxy Fold, Microsoft Surface Duo). They're indexed — you pass two integers after the name to specify which segment you're targeting:

Loading...

The first integer is the horizontal index, the second is vertical. Very limited browser support.

viewport-segment Demo

Preferred Text Scale (emerging)

  • preferred-text-scale

Represents the user's preferred text scale factor from their OS or browser settings. If text-size-adjust: auto would double the text size, this resolves to 2. Could be useful for responsive typography that truly respects user preferences.

A Real Problem This Solves

Imagine you're building a PWA with a fixed bottom navigation bar. On an iPhone with a home indicator gesture bar, your nav sits underneath the system UI. Your users are tapping the bottom of your nav and accidentally going home instead.

With env(), you fix this in one line:

Loading...

The browser knows the exact dimensions of the device's safe area and injects the correct value. No JavaScript measurement hacks, no device-specific media queries, no maintaining a lookup table of device dimensions.

Don't Forget the Viewport Meta Tag

None of this works without opting in. You need to tell the browser you want to render into the full viewport, including behind system UI:

Loading...

The key part is viewport-fit=cover. Without it, the browser letterboxes your content into the safe area by default and the env() values will all be zero. You're essentially telling the browser: "I'll handle the safe areas myself, thanks."

Using It in Practice

Here's a more complete example — a full-bleed layout that respects all safe areas:

Loading...

You can also use env() inside calc(), which is where it gets interesting:

Loading...

This gives you a 60px nav bar that extends into the unsafe area with padding, so the background color fills the space but your actual content stays visible.

Tailwind CSS

If you're working in Tailwind, you can use arbitrary values:

Loading...

Or define them as CSS variables and reference them in your Tailwind config for something more reusable:

Loading...

Why the Fallback Matters

In regular desktop browsers (or devices without notches/rounded corners), these safe area variables typically resolve to zero. That's fine for padding — zero padding is usually what you want on a rectangular screen.

But if you're using env() in a calc() to define a height or position, a zero value might break your layout. That's where the fallback earns its keep:

Loading...

Browser Support

env() has solid support across modern browsers. Safari led the charge (Apple needed it for the iPhone X notch), and Chrome, Firefox, and Edge all followed. You're safe to use it in production today.

JS
Jesse Stewart

Creative software engineer and motorsports instructor.

CSS Has Environment Variables Now - Jesse Stewart