Container Queries in Web Components

Container Queries are one of the most anticipated new features in CSS. I recently got a chance to play with them a bit and take the new syntax for a spin.

I came up with this demo of a book store. Each of the books is draggable and can be moved to one of three sections, with varying available space. Depending on where it is placed, different styles will be applied to the book. The full source code is up on Codepen. Here’s how it looks:

This demo currently only works in Chrome Canary. Download the latest version, then enable Container Queries under chrome://flags to see them in action.

Here’s what’s going on

Each of these books is a custom element, or “web component”. They each contain a cover image, a title and an author. In markup they look like this:

<book-element color="#ba423d">
<img slot="cover" src="/books/1984.avif" alt="cover by shepard fairey" />
<span slot="title">1984</span>
<span slot="author">George Orwell</span>
</book-element>

This then gets applied to a template which defines the internal Shadow DOM of the component. The <slot> elements in there will get replaced by the actual content we’re passing in.

<template id="book-template">
<style></style>
<article class="book">
<div class="front">
<slot name="cover"></slot>
</div>
<div class="meta">
<h2 class="title"><slot name="title"></slot></h2>
<p class="author"><slot name="author"></slot></p>
</div>
</article>
</template>

Alright, nothing too fancy yet, just some basic structure.

The magic happens when we apply some internal styling to this. Everything inside that <style> tag will be scoped to the component - and since styles can not leak out of the shadow DOM and we can’t (easily) style its contents from the outside, we have real component encapsulation.

Container Queries are one of the last few missing puzzle pieces in component-driven design. They enable us to give components intrinsic styles, meaning they can adapt themselves to whatever surroundings they are placed in.

The new key property there is contain - it lets us define an element as a container to compare container queries against. A value of layout indicates that nothing outside the element may affect its internal layout and vice versa.

This allows the browser to optimize the number of calculations necessary to create the page layout. By adding inline-size to the rule, we also tell the browser to respond to changes in width of the container.

UPDATE: as of Chrome Canary 93.0.4522, the contain property also needs the style value for container queries to work properly. It indicates that any styling that could affect more than the element and its children doesn’t escape the container. The reasoning behind that is documented in this issue by the CSS working group.

<template id="book-template">
<style>
/* Use Web Component as the Layout Container */
:host {
display: block;
contain: layout inline-size style;
}
</style>
...
</template>

In the bookstore demo, I created three variants that depend on the width of the component’s :host (which translates to the <book-element> itself). I’ve omitted some of the styling for brevity here, but this part is where we define the multi-column or 3D book styles.

/* Small Variant: Simple Cover + Title */
@container (max-width: 199px) {
.book {
padding: 0;
}
}
/* Medium Variant: Multi-Column, with Author */
@container (min-width: 200px) and (max-width: 399px) {
.book {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
}
/* Large Variant: 3D Perspective */
@container (min-width: 400px) {
.book {
position: relative;
transform-style: preserve-3d;
transform: rotateY(-25deg);
}
}

By adding Dragula.js to enable drag-and-drop functionality, we can then move the individual components around. As soon as they’re moved to a different section in the DOM, its internal styles are re-calculated to match the new environment, and the corresponding CSS block is applied. Magic!

The Bento Box Idea

Now theoretically, we could have achieved a similar effect by using the cascade itself. We could for example apply the 3D styles to all .books inside .stage. But that would have some problems:

  • it wouldn’t be responsive - if .stage ever gets too narrow, it would break
  • it would create an unwanted dependency context between parent and child
  • it would break component encapsulation and mix layout with content styles

It’s generally a good idea in CSS to separate “layout” from “content” components and let each handle their own specific areas of responsibility. I like to think of Japanese bento boxes as a metaphor for this: a container divided into specific sections that can be filled with anything.

For example, the layout for our bookstore looks like this:

layout schema for the bookstore with three main content sections

It’s a grid divided into three sections, the middle one containing a nested flexible grid itself.

<div class="layout">
<div class="stage"></div>
<main class="content">
<ul class="itemlist"></ul>
</main>
<div class="cart"></div>
</div>
/* main layout sections */
.stage,
.content,
.cart
{
padding: var(--spacing);
}

/* nested sub-grid */
.itemlist {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: var(--spacing);
}

/* desktop layout */
@media (min-width: 1024px) {
.layout {
display:grid;
height: 100vh;
grid-template-columns: 480px 1fr 130px;
}
}

The parts of the layout are only concerned with the alignment and dimensions of boxes. They have no effect whatsoever on their children other than giving them a certain amount of space to fill. Just like a bento box, it doesn’t care what we put into it, so we could easily re-use the layout for a completely different product. It is content-agnostic.

That’s why Container Queries pair so well with Web Components. They both offer ways to encapsulate logic to build smart, independent building blocks. Once they’re defined, they can be used anywhere.

Container Queries bring us one step closer to “Intrinsic Layouts” and a future of truly independent, component-driven design. Exciting stuff ahead!

Further Reading

Webmentions

What’s this?
  1. Pablo Lara H
    Container Queries in Web Components by Max Böck @mxbck #containerqueries #css #ChromeCanary mxb.dev/blog/container…
  2. Max Böck
    please do! container queries are uncharted territory, so very interested in what you have to say about them ;)
  3. Max Böck
    also looking forward to your upcoming course 😉
  4. Sara Soueidan
    Thank youuuu Max 😃
  5. Juan
    many awesome posts on container queries lately. Add this one by Max to the list.
Show All Webmentions (50)
  1. Vadim Makeev 🚜
    That’s a nice combo! Thank you for mixing CQ and WC together, the whole case feels stronger because of that. You also haven’t mentioned Sass or any other preprocessor, but there’s > * + * nested selector, which might be a bit confusing.
  2. Max Böck
    True, it's not necessary there. I'll remove it. 👍
  3. HN Front Page
    CSS Container Queries in Web Components L: mxb.dev/blog/container… C: news.ycombinator.com/item?id=271730…
  4. Hacker News
    CSS Container Queries in Web Components: mxb.dev/blog/container… Comments: news.ycombinator.com/item?id=271730…
  5. Winson Tang
    CSS Container Queries in Web Components mxb.dev/blog/container…
  6. yosh
    Yesssss, container queries! It's been a few years since I was working on CSS tooling and reusable components, but I remember wanting this so badly. Not being able to define layouts which adapt to their available space on-screen makes it so hard to reuse mxb.dev/blog/container…
  7. Tweet Snipper
    CSS Container Queries in Web Components mxb.dev/blog/container…
  8. HackerNewsTop10
    CSS Container Queries in Web Components Link: mxb.dev/blog/container… Comments: news.ycombinator.com/item?id=271730…
  9. Angsuman's Server
    CSS Container Queries in Web Components mxb.dev/blog/container…
  10. Hacker News
    CSS Container Queries in Web Components mxb.dev/blog/container…
  11. James Lau
    Container Queries concept demo by @mxbck. mxb.dev/blog/container…
  12. Hacker News 20
    CSS Container Queries in Web Components mxb.dev/blog/container… (news.ycombinator.com/item?id=271730…)
  13. Adactio Links
    Container Queries in Web Components | Max Böck mxb.dev/blog/container…
  14. WebコンポーネントのCSSコンテナクエリ mxb.dev/blog/container…
  15. Hacker News 50
    CSS Container Queries in Web Components mxb.dev/blog/container… (news.ycombinator.com/item?id=271730…)
  16. Jorge Cisneros
    CSS Container Queries in Web Components mxb.dev/blog/container…
  17. Ryan Bell
    Container queries bring us one step closer to native intrinsic layouts mxb.dev/blog/container… vimeo.com/380795929
  18. Zoltán Cserei
    container queries are going to be awesome mxb.dev/blog/container…
  19. Luis Orduz
    Could come in handy. mxb.dev/blog/container…
  20. Friday Front-End
    Container Queries in Web Components, by @mxbck mxb.dev/blog/container…
  21. 雑u Bot
    CSS Container Queries in Web Components mxb.dev/blog/container…
  22. FullStack Bulletin
    Container Queries in Web Components mxb.dev/blog/container…
  23. Silvestar Bistrović
    Max Böck explores Container Queries and shares the process of creating a book store demo. mxb.dev/blog/container… via @mxbck #ui #uidev #css #webdev #frontend
  24. ♟️Eduardo
    "Las Container Queries son una de las nuevas funciones más esperadas de #CSS. Recientemente tuve la oportunidad de jugar un poco con ellos para probar la nueva sintaxis." mxb.dev/blog/container…
  25. Scott Jehl
    This pattern of using :host to set up web component elements to support container query CSS is really nice. Great idea, @mxbck! mxb.dev/blog/container… (found via @css)
  26. Sara Soueidan
    #CSS Container Queries in Web Components mxb.dev/blog/container… — We're yet another step closer to a more modularized Web, and the possibilities are yet to be explored. ✨
  27. Phuoc Nguyen
    Container Queries in Web Components mxb.dev/blog/container… Thanks for sharing that useful post, @mxbck 👍 #webdev #FrontEnd #webcomponent
  28. Brian Perry
    Cool example of using container queries in a web component. Also hard to believe this combination of things is possible now (even if only in Chrome Canary) mxb.dev/blog/container…
  29. martinkosh
    Container Queries in Web Components mxb.dev/blog/container… #Programming #developer #web
  30. Sean O
    Ooo would be really neat if each cover had a container-responsive design to optimize readability at smaller sizes. Future of book design?
  31. Lucijan Blagonić
    Container Queries in Web Components mxb.dev/blog/container… — the demo is so slick and a great example for container queries! 👏 Well done @mxbck
  32. Sakito
    このCSS Container Queriesの例はいいユースケースの例だった。 Container Queries in Web Components mxb.dev/blog/container…
  33. Steve Perry
    Exciting times ahead with container queries. Looking forward to having a play with them and web components when I get chance. mxb.dev/blog/container…
  34. Frontend Daily 🚀
    Container Queries in Web Components: mxb.dev/blog/container… (Here's a Chrome-only demo showing container queries in action.)
  35. Imabit Inc
    #CSS #Automated | Container Queries in Web Components mxb.dev/blog/container…
  36. Front-End Front
    Container Queries in Web Components mxb.dev/blog/container…
  37. Chris Ashton
    Nice summary of CSS container queries, with real world example: mxb.dev/blog/container…
  38. Выражения от контейнера в веб-компонентах. Макс Бёк показывает, как можно будет удобно применять директиву @​container внутри изолированного Shadow DOM веб-компонентов. mxb.dev/blog/container…
  39. Daniel
    A collection of cool links, ideas, and news that I've seen in the past few days: the :not() CSS pseudo selector accepts a complete list of selectors. We can do something like :not(h1, h2, #main) as we have for the :is selector CSS inset is now fully supported. This means we can have shorthands as inset: 4px 8px; instead of top: 4px ; right: 8px; we can emulate the dark mode and reduced motion in Chrome Dev Tools. More details here. in PHP you can use debug_backtrace() to print the full stack trace as we have in javascript the console.trace seen in the CSS Tricks newsletter a great example for the Container Queries made by Max Böck. Impressive stuff. That's all folks! See you the next time! I hope you have enjoyed this article and if you would like to get more articles about React and frontend development you can always sign up for my email list. Newsletter subscribe:
  40. WebSupport.tech
    Container Queries in Web Components mxb.dev/blog/container…