Service Business

Container Queries Everywhere: The CSS Feature That Killed the Breakpoint Mindset

4/4/2026 · John

Container queries shipped cross-browser in 2023, but it took two years for production design systems to actually adopt them. The shift is meaningful: components can now respond to their own container’s size, not just the viewport. A card looks the same in a sidebar, a grid, and a hero, because its layout adapts to the space it has, not to the device the user is on. Here’s the mental shift and how we ship it on FH client sites.

What container queries do

A container query lets a component change its layout based on the size of an ancestor element marked as a container. Unlike a media query (which responds to viewport size), a container query responds to a specific parent. A card placed in a 300px sidebar gets one layout; the same card placed in a 1200px grid gets a different layout — both without changing the component’s code.

/* Mark an element as a container */
.card-container {
container-type: inline-size;
}

/* Component responds to container width */
.card {
display: grid;
grid-template-columns: 1fr;
}

@container (min-width: 480px) {
.card {
grid-template-columns: 1fr 2fr;
}
}

@container (min-width: 720px) {
.card {
grid-template-columns: 1fr 3fr 2fr;
}
}

Why this changes design system architecture

Pre-container-queries, a component had to know which breakpoint context it was rendered in. A card in a sidebar needed a `.card--narrow` modifier; a card in a hero needed `.card--wide`. The component’s layout was coupled to the page it lived in. With container queries, the component is self-contained. It responds to its own context. You can drop it anywhere and it works.

How we use container queries on FH client sites

  • Project cards: one component definition; renders compactly in sidebars, expansively in galleries.
  • Service cards: same component in the home grid (2-column on tablet) and in the solutions page (3-column on desktop).
  • Testimonial blocks: stack vertically in narrow containers, side-by-side in wider ones.
  • Pricing comparison tables: adjust column count based on container width.
  • Blog post cards: scale typography and image size based on container.

Container query units

`cqi` (container query inline-size, ~width) and `cqb` (container query block-size, ~height) let you size things relative to the container. `font-size: 5cqi` means ‘5% of container width.’ Useful for fluid typography that scales smoothly with container, no breakpoint hops.

Browser support

Cross-browser stable since 2023. Safari, Chrome, Firefox, Edge all ship full support. For SMB sites in 2026, container queries are safe to use everywhere. No polyfill required.

When media queries still make sense

  • Layout shifts that depend on viewport orientation (portrait vs landscape).
  • Device-specific features (`hover: hover`, `pointer: fine` for input capability).
  • Theme switches (`prefers-color-scheme`).
  • Motion preferences (`prefers-reduced-motion`).
  • Print styles (`@media print`).

The mental shift

Designers used to think in pages: ‘at mobile, the page looks like X; at tablet, the page looks like Y; at desktop, the page looks like Z.’ With container queries, the unit of design is the component, not the page. ‘At narrow container, the card looks like X; at wide container, the card looks like Y.’ Pages compose from components that each handle their own responsiveness. The design system becomes more reusable and the layout work is dramatically less repetitive.

Container queries + Tailwind

Tailwind 4 ships first-class container query support. `@container` and `@md:` prefixes (`@md:flex-row`) work alongside `md:` (viewport-based). We use both: viewport queries for page-level layouts, container queries for component-level adjustments.

<div className="@container">
<div className="flex flex-col @md:flex-row gap-4">
<img className="w-full @md:w-1/3" />
<div className="flex-1">
<h3 className="text-lg @lg:text-xl">Title</h3>
<p className="text-sm @lg:text-base">Body</p>
</div>
</div>
</div>

Container types: inline-size vs size

`container-type: inline-size` is what you want 95% of the time. It tracks only the inline (horizontal) dimension and doesn’t prevent the container from expanding vertically. `container-type: size` tracks both dimensions but has a side effect: it forces the container to behave as if it has intrinsic size, which often breaks vertical flow. Stick to `inline-size`.

Common pitfalls

  • Setting `container-type` and then wondering why the container collapses vertically. Use `inline-size`, not `size`.
  • Trying to use container queries to detect viewport size. Use media queries for that.
  • Nesting containers without naming them. `container-name: card` lets you target specific containers when nested.
  • Forgetting that container queries don’t work for the parent of the component (a component can’t query the container it’s inside without that parent being marked as a container).

Real impact on FH client builds

Reduced component duplication: same card component used in 5 different layout contexts instead of 5 modifier variants. Simpler design system: one source of truth per component. Faster development: build the component once, drop it anywhere. Cleaner CSS: less specificity nesting, fewer overrides. The shift is bigger than ‘a new feature’ — it’s a different way to structure responsive design.

The migration cost
Moving a design system from breakpoint-based to container-based isn’t a 1-day project. It’s a quarter-long architectural shift. The payoff compounds: every new feature ships faster because components are properly contained. The Tivey site was built container-first from day one; their dev velocity has been consistently faster than comparable breakpoint-based projects.

How this lands across FH client work

New FH client builds use container queries by default. Older builds get migrated component-by-component during natural redesigns. The team’s mental model has shifted; the design system has fewer modifiers; the layouts hold up across contexts. If your site’s responsive code is full of `xl:` and `lg:` modifiers and you’re still copy-pasting components for different layout contexts, book a consultation — the migration to container-first is a real architectural improvement.

Frequently asked questions

What do container queries actually do?

Let a component respond to the width of its container rather than the viewport. That means the same card can lay out correctly in a sidebar and in a full-width grid without knowing where it is, which viewport breakpoints could never express.

Why does this change design-system architecture?

Because components become genuinely self-contained. Previously a component's responsive behaviour depended on assumptions about the page it sat in, so reusing it elsewhere meant new breakpoint overrides. Now the component owns its own rules and travels intact.

Do media queries still have a place?

Yes, for things that are genuinely about the viewport or the device: page-level layout, navigation patterns, print styles, and preference queries such as reduced motion. The mistake is using them for component-level decisions, which is what they were always being stretched to do.

What are container query units?

Units relative to the container's size rather than the viewport's, so typography and spacing can scale with the space a component occupies. They are what makes a component that genuinely adapts possible, rather than one that switches between two fixed layouts.

What is the difference between inline-size and size containment?

Inline-size containment tracks width only and is what you want almost always. Full size containment requires the container's height to be independent of its content, which is rarely true in real layouts and produces collapsed elements when it is not.

Is browser support good enough?

Yes, across current browsers, and the degradation is graceful: without support the component falls back to its default layout rather than breaking. That makes adoption a decision about your audience's browser mix rather than a technical risk.

How do container queries work with a utility CSS framework?

Modern versions support them as first-class variants, so a component can carry container-relative utilities alongside ordinary ones. The mental shift is harder than the syntax: writing container-relative rules by default rather than reaching for screen breakpoints.

What are the common pitfalls?

Forgetting to declare the container, which makes the queries silently inert. Using size containment where inline-size was meant. And nesting containers so a component queries the wrong ancestor, which produces layout that is correct in isolation and wrong in place.

What is the mental shift?

From asking how wide is the screen to asking how much space do I have. That reframing is what makes components composable, and it is why teams that adopt this stop maintaining a growing list of breakpoint exceptions for each new placement.

Does this affect performance?

Marginally, and in both directions. Containment can help the browser limit layout work; a deeply nested set of containers can add some. Neither effect is large enough to drive the decision, which should be about maintainability.

What is the real impact on a build?

Fewer one-off overrides and fewer components that only work in one place. The visible saving is in the CSS that no longer needs writing every time a component is reused somewhere new, which compounds across a design system.

Where should I start?

With one component that already carries placement-specific overrides, usually a card. Convert it to container queries, delete the overrides, and put it in two different layouts. That single conversion demonstrates the argument better than any explanation.