CSS custom-media: name your media queries once

Firefox Nightly now has a flag for CSS custom-media queries. Anyone who has built a large WordPress theme knows the specific annoyance this fixes: repeating a string like (prefers-reduced-motion: no-preference) across a dozen files and trusting that you typed it the same way every time.

The at-rule comes from the Media Queries Level 5 specification, and it lets you give a media query a name. Define the breakpoint once, then refer to the name instead of the condition. In Firefox it still sits behind the layout.css.custom-media.enabled flag, but it changes how you organize a stylesheet.

The problem with hardcoded media queries

We have faked this for years with Sass variables or PostCSS plugins. Native support means less processing overhead and cleaner interaction with features like CSS Cascade Layers. Mostly it kills the copy-paste habit that leaves a codebase carrying four slightly different versions of the same breakpoint.

Here is how a repeated accessibility query usually ends up in a stylesheet today, verbose and easy to break during a refactor.

/* The Naive, Repetitive Approach */
@media (prefers-reduced-motion: no-preference) {
  .hero-animation {
    animation: slideIn 1s ease;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .button-hover {
    transition: transform 0.2s;
  }
}

Open Props and its @custom-media recipes

Adam Argyle’s Open Props has been ahead of this for a while. It ships more than 45 predefined media queries covering common UI states, so you pull in the recipe instead of writing the condition again. What comes out the other side is a stylesheet you can read.

/* The Modern @custom-media Way */
@custom-media --motionOK (prefers-reduced-motion: no-preference);
@custom-media --ipad (width <= 1024px);

@media (--motionOK) {
  .hero-animation {
    animation: slideIn 1s ease;
  }
}

@media (--ipad) {
  .sidebar {
    display: none;
  }
}

Calling this syntactic sugar undersells it. Change a breakpoint in one place and the new value travels through the entire cascade. It follows the same thinking as Style Container Queries: move the logic out of hardcoded values and into named definitions.

How to use it now

Shipping this today takes a build step. MDN documents @custom-media, but browser support is still at the Nightly flag stage, and neither Safari nor Chrome has committed to Firefox’s timeline.

Write the syntax now and run it through postcss-custom-media. It compiles down to standard media queries for older browsers, so your source stays current without breaking anyone. When native support lands across the board, you drop the plugin from the build config and ship the CSS as written.

If the CSS side of a project is eating your dev hours, I take on that work. I have been building on WordPress since the 4.x days.

Naming capabilities instead of devices

The payoff is maintainability. Naming a capability, --motionOK or --large-screen, holds up better than sorting rules into “desktop” and “mobile” buckets that never described real devices well. CSS custom-media is the bit of syntax that makes that naming possible in plain CSS.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.