~ 2 min read

Using calc() in Media Query Conditions


TIL that calc() works inside @media query conditions for static calculations, but CSS custom properties (var()) cannot be used in media query conditions.

What Works: Static calc()

You can use calc() directly in media queries with hardcoded values:

/* This works! */
@media (min-width: calc(100px * 2 + 2rem)) {
  .container {
    display: grid;
  }
}

Browser Support: Widely supported

What Doesn’t Work: CSS Custom Properties

According to the CSS Variables Level 1 spec, var() cannot be used in media query conditions:

/* ❌ This does NOT work */
:root {
  --breakpoint: 768px;
}

@media (min-width: var(--breakpoint)) {
  /* This will fail */
}

/* ❌ This also does NOT work */
@media (min-width: calc(var(--breakpoint) + 100px)) {
  /* This will fail too */
}

Why? Media queries exist in global scope and aren’t attached to HTML elements, so they can’t access CSS custom properties—even from :root. When SASS/SCSS nests @media blocks, they’re hoisted to the document base during compilation, further illustrating this separation.

Workarounds

For SASS/SCSS Users

Use SASS variables for media queries (replaced at build-time) and CSS variables everywhere else:

$mobile-breakpoint: 600px;

@media (max-width: calc($mobile-breakpoint + 2rem)) {
  /* ✅ Works */
}

For PostCSS Users

The @csstools/postcss-design-tokens plugin lets you use design tokens from JSON files, including in media queries:

// tokens.json
{
  "viewport": {
    "mobile": { "value": "600px" },
    "tablet": { "value": "900px" }
  },
  "spacing": {
    "small": { "value": "16px" }
  }
}
@design-tokens url('./tokens.json') format('style-dictionary3');

.container {
  padding: design-token('spacing.small');
}

/* ✅ This works in media queries! */
@media (min-width: design-token('viewport.mobile')) {
  .container {
    padding: design-token('spacing.small' to rem);
  }
}

This compiles to standard CSS with your token values replaced.

Note on deprecated postcss-env-function: Custom Environment Variables were never formally specified and are no longer included in postcss-preset-env. If you’re still using it, consider migrating to @csstools/postcss-design-tokens.

Future: Native env() Variables

The CSS Environment Variables Module Level 1 spec proposes native env() support for media queries. While browsers support env() for reading predefined values (like safe area insets), you cannot declare custom environment variables yet.


Headshot of Nam Le

Hi, I'm Nam Le. I'm a software engineer based in HCM city, Vietnam. You can follow me on Twitter, see some of my work on GitHub, or connect with me on LinkedIn.