The Raven Technique: One Step Closer to Container Queries

Building further upon The Holy Albatross technique, comes The Raven Technique by Mathias Hülsbusch:

I want to get closer to actual container queries! So, what does CSS have offer that I could tap into? I have a mathematical background, so functions like calc(), min(), max() and clamp() are things I like and understand.

Next step: build a container-query-like solution with them.

Leveraging clamp() he builds new CSS Custom Properties (aka CSS Variables) which in their turn are used as Conditions for CSS calculations.

☝️ Did you know Chromium will be experimenting with native Container Queries, and we might eventually have them built into the browser?

You can play with the results in the pen below, by adjusting the width of .try_out_dimensions although I’d recommend to read the explanatory post first 😉

The Raven Technique: One Step Closer to Container Queries →

Container Queries are coming to Chromium!

Update 2020-02-12: Thanks to the hard work by Miriam Suzanne and others this proposal is now officially part of the CSS Specification Process (ref) and set to be part of css-contain-3 … it’s happening, people! 🎉

Just announced on the Chromium mailing list is an “Intent to Prototype” Container Queries, which is quite exciting news I must say!

🤔 Container Queries?

Container Queries allow authors to style elements according to the size of a container. This is similar to a @media query, except that it evaluates against a container instead of the viewport.

The experimental implementation will follow Miriam Suzanne’s proposal, which looks like this:

/* (1) Create an implicit "container root" */
aside {
  contain: size;

.media-object {
  display: grid;
  gap: 1em;

/* (2) Container Query targeting the nearest 
   "container root" ancestor. The rules nested
   inside will only be applied if the "container
   root" has a max-width of 45em */
@container (max-width: 45em) {
  .media-object {
    grid-template: 'img content' auto / auto 1fr;

Applying contain: size; (1) onto an element will make it an implicit “container root” or “containment context”. Elements contained inside it can then have container queries applied onto them, by use of a new at-rule @container (<container-media-query>) (2). The target selector and CSS rules to apply in that case are — similar to what we do with “regular” media queries — nested within the @container at-rule.

In the example above extra rules will be applied to .media-object whenever its nearest “container root” ancestor — such as <main> or <aside> — has a max-width of 45em.

🧑‍🔬 This proposal is experimental and has not been approved by the CSSWG yet. The expressed “intent to prototype” is meant as an experiment to see whether this idea would be worth pursuing or not. In the end, it could be that the final syntax can differ from the one listed here, if the proposal is workable in the first place.


A previous version of this proposal by L. David Baron required a context selector to be set, but that has been dropped here. The @container rule from Miriam’s version will work in any containment context (read: the nearest parent element that has contain: size set). The syntax might still change, but that’s irrelevant to the prototype which is to be implemented:

This is not at all finalized, but the underlying problems we need to solve in Blink are (mostly) the same regardless of how the feature is accessed, so we’ll for now use this proposal as the temporary syntax.


Intent to Prototype: Container Queries →
Chrome Tracking Bug →

🔥 Like what you see? Want to stay in the loop? Here's how:

Container Queries with the <watched-box> Custom Element

Heydon Pickering has created <watched-box>:

I wanted a simple, declarative container queries solution, and here it is:

  • ❤ Custom Element + ResizeObserver
  • 🥣 Use and mix together any CSS length units
  • 🖼 Orientation supported
  • 🧚‍♀️ ≅1.5KB minified

Once imported you can use it as follows:

<watched-box widthBreaks="70ch, 900px" heightBreaks="50vh, 60em">
  <!-- HTML and text stuff here -->

<watched-box> will then automatically add the proper classes:

  • Less than or equal to the supplied width: w-lte-[the width]
  • Greater than the supplied width: w-gt-[the width]
  • Less than or equal to the supplied height: h-lte-[the height]
  • Greater than the supplied height: h-gt-[the height]