Container Style Queries: Advanced Use Cases Beyond Size
AI generated
{ }
@
CSS · Container Queries · Style Queries
Container Style Queries Beyond Size
Style components from a custom property on their container, not from a class on themselves

@container style() checks whether a custom property on the query container has a specific value and applies rules only when that condition holds, opening up theming, density switches and design token driven components that stay completely context free. Here is where style queries genuinely help, where they still fall short, and how to fall back safely.

16 min read @container style() · Custom Properties Progressive Enhancement · Design Tokens

1. What style queries are and how they differ from size-based container queries

Container queries first became known purely as a size check: @container (min-width: 400px) lets a component react to the available space of its nearest named ancestor, independent of viewport width. Style queries extend the same underlying mechanism with a completely different kind of condition: instead of asking about dimensions, @container style(...) checks whether a specific CSS custom property on the container has a specific value, and only applies rules when that condition is met.

The key difference from a classic class is the direction the information flows: a class gets set directly on the element that should change, while a style query checks the condition on an ancestor and lets the descendants react, without those descendants ever needing to carry a class of their own. That makes style queries especially valuable for design-system components whose inner structure should not need to know which theme or context it is currently being rendered in.

2. The style() syntax: querying custom properties as a condition

The basic syntax is @container style(--property: value) { ... } and checks the computed value of the given custom property on the nearest container defined as a query container through container-type. Unlike size queries, a style-query container currently does not need an explicit container-type: size in most implementations, because style queries work independently of any size calculation.

It matters that the condition compares the computed string value exactly, not numerically greater or smaller. A custom property with the value dark only satisfies a condition that asks for exactly dark, not a range or a substring. That makes style queries syntactically simpler than size queries, while also limiting how conditions can be phrased.


.card-container {
  --theme: light;
  container-name: card;
}

@container card style(--theme: dark) {
  .card {
    background-color: #18181b;
    color: #f4f4f5;
    border-color: #3f3f46;
  }
}

3. Use case: driving theme variants from a custom property on the parent

The most obvious use case for style queries is component level theming: a custom property like --theme is set once on the outer container, for example depending on which area of the page a card component is embedded in, and every card inside that container reacts automatically, without the card itself needing a theme class or any JavaScript logic passing the context down.

That is especially valuable in design systems with many reused components, because the component itself stays completely context free: the same .card rule works identically whether it lands in a light marketing area or a dark dashboard area of the application, as long as the respective parent area sets the matching custom property. That decouples the component definition from the place it actually gets used.


/* Marketing area sets a light theme on its section container */
.marketing-section { --theme: light; container-name: theme-scope; }

/* Dashboard area sets a dark theme on its section container */
.dashboard-section { --theme: dark; container-name: theme-scope; }

/* The card component itself never needs a theme class */
@container theme-scope style(--theme: dark) {
  .card { background: #1f2937; color: #e5e7eb; }
}
@container theme-scope style(--theme: light) {
  .card { background: #ffffff; color: #111827; }
}

4. Use case: layout density (compact/comfortable) without extra classes

A second practical use case is controlling layout density, for example in tables or lists with a switchable compact versus comfortable mode. Instead of maintaining a separate CSS class for every density variant on every affected child element, a single custom property on the shared container is enough, and every row, cell and padding value reacts consistently to the same value.

This approach mainly reduces the number of places where density logic would otherwise have to be duplicated. Instead of tagging ten different child elements individually with .compact modifier classes, the density decision is made in exactly one place and propagated to every affected rule through style queries, which noticeably improves maintainability and consistency.


.data-table-wrapper {
  --density: comfortable;
  container-name: table-density;
}

@container table-density style(--density: compact) {
  td, th { padding-block: 0.25rem; font-size: 0.8125rem; }
  tr { line-height: 1.2; }
}

@container table-density style(--density: comfortable) {
  td, th { padding-block: 0.75rem; font-size: 0.875rem; }
  tr { line-height: 1.5; }
}

5. Boolean-like custom properties and how they differ from real CSS booleans

CSS has no dedicated boolean data type, which is why style queries for seemingly binary states usually work with string values like true/false or an explicit single value convention. The specification does allow a shorthand that treats a set, non-empty custom property as true, but support for that shorthand is still more inconsistent across browser engines than the core feature itself.

In practice it is therefore more robust to always use an explicit string value for boolean states and phrase the condition unambiguously, such as @container style(--collapsed: true), instead of relying on the mere existence of the property. That makes the code marginally more verbose but noticeably more predictable across different browser versions.

6. Combining style queries with size queries

Style queries and classic size queries are not mutually exclusive and can be combined in a single @container rule by joining the size condition and the style() condition with and. That allows rules like only when the container is at least 500px wide and the dark theme is active at the same time, which would be considerably more cumbersome to express with plain media queries or plain classes alone.

This combination is especially valuable for responsive design systems that need to react to both available space and thematic context, for example a component that shows a reduced layout in a narrow, dark context but an expanded layout with extra metadata in a wide, dark context. A single combined query covers that case without nested media queries or extra JavaScript logic.


@container sidebar (min-width: 500px) and style(--theme: dark) {
  .widget {
    grid-template-columns: 1fr 1fr;
    background: #111827;
  }
}

7. Inheritance, cascade, and why style queries need the custom property on the container itself

An important limitation concerns the cascade: style queries evaluate the computed value of a custom property on the container element itself, not on the querying descendant. That means a custom property that only reaches the container through inheritance from an even more distant ancestor is, in many implementations, recognized more reliably when it is set explicitly on the element defined as the query container, rather than relying purely on implicit inheritance chains.

In practice that means: anyone setting a custom property high up in the document tree and expecting every arbitrary query container defined further down to automatically see it should test that in every target browser. The more robust approach is to set the relevant custom property directly on the element that also acts as the named query container, instead of relying on multi-level inheritance.

8. The real browser support picture and a safe fallback pattern

Style queries are one of the newer additions to the container query specification, and browser support noticeably lags behind plain size-based container queries, which are now broadly available. Chromium based browsers have supported style() for custom property conditions the longest, while other engines still support it only experimentally or not at all, which makes practical use today a deliberate progressive enhancement decision.

The safe fallback pattern defines base styles outside any style query and lets @container style(...) make only additional, non-critical adjustments. A browser without support ignores the entire rule and shows the base styles, a supporting browser gets the refined variant, but no user ever sees a broken or incomplete layout.


/* Base styles work everywhere, with or without style() support */
.card {
  background: #ffffff;
  color: #111827;
  border: 1px solid #e5e7eb;
}

/* Progressive enhancement: only refines the theme where supported */
@supports (container-type: inline-size) {
  @container theme-scope style(--theme: dark) {
    .card {
      background: #18181b;
      color: #f4f4f5;
      border-color: #3f3f46;
    }
  }
}

9. When style queries are the right choice, and when classes still fit better

Style queries pay off especially where a component should stay context free and the context information already exists as a custom property or has to be set anyway, for example for design tokens. For simple, binary states that can easily be expressed with a single extra class on the affected element itself, a classic class often remains the more pragmatic and cross-browser reliable choice.

The decision between a style query and a class is ultimately a question of responsibility: style queries fit when the context comes from outside and the component itself should not need to know about it. Classes fit when the state is known directly on the affected element and no extra indirection through a container is needed. Both techniques are not mutually exclusive but complement each other depending on the architecture.

Criterion Style query (@container style()) Classic class Recommendation
Browser support Limited, mainly Chromium Universal Guard with @supports
Component context freedom High, no knowledge of context needed Low, class must be set Style query for design-system components
Combining with a size query Directly possible via and Not applicable Style query for combined conditions
Debugging effort Higher, value comes from the container Lower, visible directly on the element Class for simple, local state
Typical use Theme, density, design tokens Local UI state (open/active) Choose based on where the state originates

Mironsoft

Modern CSS, layout architecture and rendering performance

CSS that stays maintainable instead of breaking with every change?

We review existing stylesheets for specificity chaos and layout thrashing, then build a CSS architecture with cascade layers, custom properties and modern layout primitives that still makes sense after the tenth feature.

CSS Audit

Systematically uncovering specificity issues, cascade conflicts and unused selectors.

Architecture Refactoring

Introducing cascade layers, custom properties and design tokens cleanly.

Performance Tuning

Fixing layout thrashing, expensive selectors and rendering bottlenecks.

10. Summary

Container Style Queries: The Essentials at a Glance

Core idea

@container style(--property: value) checks custom property values on the query container instead of dimensions, letting descendants react while staying context free.

Strongest use case

Theming and layout density for reusable design-system components without theme classes on every child element.

Limitation

Boolean states should use explicit string values, and the custom property ideally belongs directly on the query container.

Browser reality

Support lags behind size queries, so always define base styles outside the style query and refine progressively.

11. FAQ: Container Style Queries: The Essentials at a Glance

1What is the difference between style queries and regular container queries?
Regular container queries check dimensions like the width or height of the container, style queries instead check the value of a CSS custom property on the container.
2What is the basic syntax of a style query?
@container name style(--property: value) { ... } checks whether the given custom property on the named container has exactly that value, and applies the rules only then.
3Do I need container-type: size for style queries?
Not strictly in most current implementations, because style queries work independently of any size calculation. A named container via container-name is often enough.
4Can I combine style queries with size queries?
Yes, with and both conditions can be joined in one rule, for example a minimum width together with a specific theme value.
5How do I represent boolean states in a style query?
Most robustly with an explicit string value like --collapsed: true instead of relying on the mere existence of the property, since the shorthand is supported inconsistently across browsers.
6Do style queries reliably evaluate inherited custom properties?
It works most reliably when the custom property is set directly on the element defined as the query container, rather than relying on multi-level inheritance from further up.
7How good is browser support for style queries currently?
Chromium based browsers support them the longest, other engines only experimentally in places. Usage should therefore be planned as progressive enhancement.
8How do I build a safe fallback for style queries?
Always define base styles outside the style query, so non-supporting browsers show a working baseline, and let the style query only make additional refinements.
9When is a class better than a style query?
When the state is known directly on the affected element and no indirection through a parent container is needed, a class stays simpler and more reliable.
10Are style queries suited for theming in design systems?
Yes, that is one of the strongest use cases, because a component can react to a theme set on the parent container without needing a theme class of its own.