Custom media queries: native CSS or a build step

Bold hook "Named Breakpoints" beside an isometric ruler machine feeding lines to three gray screens on a blue gradient.

You put the tablet layout behind @media (--tablet), it looks right in the browser you test in, and on a browser that has not shipped @custom-media the sidebar never shows up. The unknown query never matches, so the styles inside the block don’t apply, and the layout falls back to whatever sits outside it. The browser reports nothing. That is the failure mode worth understanding before this rule goes anywhere near a production theme.

Custom media queries exist to fix a real annoyance: (prefers-reduced-motion: reduce) or a three-part breakpoint typed out over and over in one stylesheet. CSS-Tricks has a full almanac entry on @custom-media that covers the syntax, the scoping and the boolean toggles, and it is a good read. My question is narrower, and it decides whether a client site gets this at all: do you ship the native browser rule, or do you expand it in a build step?

What custom media queries buy you

You define an alias once, then use it like any other media query. The names are dashed idents and case-sensitive, aliases can reference each other, and a loop makes every alias in the loop undefined. Setting one to true or false gives you a cheap feature flag while a layout is still in flux.

@custom-media --tablet (min-width: 768px);
@custom-media --reduced-motion (prefers-reduced-motion: reduce);

@media (--reduced-motion) {
  .wc-block-components-notice-banner {
    animation: none;
  }
}

@media (--tablet) {
  .woocommerce-tabs {
    grid-template-columns: 1fr 320px;
  }
}

The value is the rename path. When the design moves from 768px to 800px, one line changes and every usage follows. It sits with native centering in the group of CSS features that delete old workarounds instead of adding new ones.

Native @custom-media or a PostCSS build step

Native means the browser resolves the alias while it parses your stylesheet. Nothing to install, and devtools show exactly what you wrote. The cost is availability: MDN still marks the rule experimental with limited availability, and the obvious guard, @supports (at-rule(@custom-media)), only works in Chrome 148 and up right now, which defeats the point of the check. The redefinition and scoping rules are also still under discussion in the CSS working group (issue 13041).

PostCSS Custom Media, from the csstools family, takes the same source syntax and expands every usage at build time into plain @media (min-width: 768px) blocks. The output runs everywhere, including browsers that will never learn the at-rule. The trade is that the alias only exists in files that pass through your build, and each usage repeats the expanded query, so the file grows a little. After minification it rarely matters.

The third option is the old one: a Sass map with a media() mixin. Same idea, SCSS only. Block themes ship plain CSS more and more, and dragging Sass back just for breakpoint variables isn’t worth the toolchain.

WordPress splits your CSS into pieces

WordPress makes this messier, because a front end rarely loads one stylesheet. Your compiled theme bundle prints next to the global styles that theme.json generates inline, WooCommerce inline CSS, whatever each plugin enqueues, and the Additional CSS box in the site editor. Per the Media Queries Level 5 spec, a @custom-media rule is global within its stylesheet, so an alias defined in your bundle does not resolve inside the Additional CSS box or inside a plugin’s stylesheet. If someone copies your @media (--tablet) pattern into that box, the block does not apply, in any browser.

The rule I follow: aliases and every usage of them stay inside one compiled artifact. A child theme or a small plugin that needs the same breakpoints gets its own definition. (I have not tested how this behaves on admin screens, where WordPress can concatenate CSS through load-styles.php, but I keep aliases out of admin styling anyway.)

matchMedia() never sees your aliases

Aliases are CSS-only. matchMedia("(--tablet)") does not work, even in a browser that supports the rule. That matters because themes pair breakpoints with script behavior all the time: a nav that becomes a drawer under the same width, a sticky add-to-cart bar that only sticks on small screens. That script still needs the literal query string. On WordPress sites I define the canonical string once in PHP and hand it over with wp_add_inline_script(), so the CSS and the script cannot drift apart.

Which one I’d pick for which site

For a client store in production, the PostCSS route. Shipped CSS is plain media queries, browser support stops being a question, and the cost is one plugin in a pipeline the theme already has. I would still write native @custom-media for conditions where dropping the styles in an old browser is harmless, meaning prefers-reduced-motion and prefers-contrast overrides, because the fallback there is the default presentation rather than a broken layout. A layout breakpoint does not qualify.

For an internal tool where you control the browser mix, go native and skip the dependency. For a theme or plugin you distribute to other people, always the build step, because you don’t get to pick their visitors.

If your theme has the same breakpoints pasted across a dozen partials, this is the kind of cleanup I do often: set up the PostCSS pipeline, centralize the queries, then check the front end for drift. Happy to take a look if that’s useful.

On a client site this week I’d add postcss-custom-media to the theme build, define the tablet and reduced-motion aliases once at the top, and leave the native rule out until MDN drops the experimental flag. Then the missing sidebar stops being a browser lottery and becomes a one-line change.

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.

Leave a Comment