Experimental: Check browser support before using this in production.

The CSS @custom-media at-rule allows creating aliases for media queries. This is particularly valuable if you have long or complex media queries that you use multiple times across your codebase. The feature is similar in nature to a media query version of CSS custom properties (CSS variables).

Syntax

The syntax for defining an alias is:

@custom-media (<dashed-ident>) [<media-query-list> | true | false];

For example:

@custom-media --modern-touch (pointer: coarse) and (min-width: 1024px);

…where the dashed ident is --modern-touch.

The syntax for using an alias is the same as using any media query, but instead of providing media types or media features, you provide the <dashed-ident> of your defined @custom-media:

@media (<dashed-ident>) {
  /* ... */
}

Arguments and Descriptors

  • <dashed-ident>: A user-defined identifier that must start with two dashes (--), similar to functions or custom properties. Just like custom properties, the name is case-sensitive. For example, --mobile-breakpoint and --Mobile-Breakpoint would refer to different custom media definitions.
  • <media-query-list>: A list of media queries, separated by operators.
  • true/false: Always-match / never-match toggles.

The following sections cover how these work in different contexts: scoping, boolean constants, complex logic, range syntax, and nested aliases.

Scope and Placement

Unlike custom properties, which are scoped to the element they are defined on and their children, @custom-media rules are global. They are evaluated in the global scope of the stylesheet and will always apply to the entire document. If multiple @custom-media rules are defined with the same name, the one in scope at the time of evaluation is the one that is used.

When a @media rule uses a custom alias (the dashed ident), it looks at the current definition of that alias at that point in the stylesheet. If the alias is redefined later, it does not “update” the media queries that were already processed. For example, in this case margin-block: 1rem will only be applied to body if it is fullscreen and not browser, despite the later declaration using the same name:

@custom-media --screen-display (display-mode: fullscreen);

@media (--screen-display) {
  body {
    margin-block: 1rem;
  }
}

@custom-media --screen-display (display-mode: browser);

Note: This scoping behavior is still being discussed and is subject to change in the future.

Boolean Constants

A @custom-media rule can be explicitly set to true or false. This is useful for toggling entire blocks of CSS during development or for feature flagging.

Operators and Complex Logic

@custom-media utilizes the exact same logical operators (and, ,, or, not, only) and grouping rules as @media, so you can build complex, parentheses-grouped logic just as you normally would. For a full breakdown of how to use operators, negate features, or hide stylesheets from older browsers, reference the Logic and Operators section of the @media almanac. It is also worth referencing the section on nesting and complex decision-making when building complex queries.

To construct a query using the and logical operator:

@custom-media --modern-touch (pointer: coarse) and (min-width: 1024px);

Range Syntax

@custom-media supports the ranged media query syntax, which uses operators such as greater than (>), less than (<), and equals (=) to evaluate conditions:

/* Old way */
@custom-media --tablet (min-width: 768px) and (max-width: 1024px);

/* New, cleaner way */
@custom-media --tablet (768px <= width <= 1024px);

Nested Aliases

@custom-media aliases can reference each other, allowing you to build layered, semantic conditions:

@custom-media --narrow-window (width < 30rem);
@custom-media --small-and-hover (--narrow-window) and (hover: hover);

@media (--small-and-hover) {
  /* Styles for mobile-sized screens with hover capabilities */
}

If a loop is detected, all involved custom media queries are treated as undefined. For instance, if --query-a references --query-b, then --query-b cannot reference --query-a. Similarly, a custom media query cannot refer to itself.

Be aware of over-nesting, as it can make debugging difficult when trying to identify which layer of a query is having the relevant impact in your browser’s developer tools.

Example: Defining Common Breakpoints

Instead of remembering if your “tablet” breakpoint is 768px or 800px, you can define it once at the top of your stylesheet:

@custom-media --tablet (min-width: 768px);

.sidebar {
  display: none;

  @media (--tablet) {
    display: block;
  }
}

Example: Defining Shorthands for Existing Properties

Standard boilerplate such as (prefers-reduced-motion: reduce) can be used many times across a codebase, and those bytes add up. You can use @custom-media to define simpler alternatives:

@custom-media --prefers-reduced-motion (prefers-reduced-motion: reduce);

@media (--prefers-reduced-motion) {
  /* ... */
}

@custom-media --js-enabled (scripting: enabled);
@custom-media --js-disabled (scripting: none);

@media (--js-disabled) {
  .no-js-banner {
    display: block;
  }
}

There are a great number of Open Props @custom-media Recipes you may consider using.

JavaScript Support

@custom-media aliases are not exposed to the JavaScript matchMedia() method, meaning this code will not work, even if you have the alias defined somewhere on your page:

matchMedia("(--tablet)")

Specification

The @custom-media at-rule is defined in the Media Queries Level 5 specification.

Browser Support

Unsupported browsers largely ignore @custom-media, so fallback declarations and progressive enhancement strategies can be advantageous. You can use @supports to check if @custom-media is supported in the user’s browser:

@supports (at-rule(@custom-media)) {
  /* ... */
}

At the time of writing, however, @supports at-rule evaluation does not have full browser support (Chrome 148+ only), so you will need to verify support for your specific use case. You can follow the discussion on this in CSS Drafts Issue #2463.

Another approach is to use a tool such as PostCSS Custom Media, which expands the rules at build time to achieve wider browser support.