Using Container Queries in CSS

Hero image for Using Container Queries in CSS. Image by Teng Yuhong.
Hero image for 'Using Container Queries in CSS.' Image by Teng Yuhong.

Although support is currently limited at best, CSS container queries (also sometimes referred to as 'element queries'), allow us to apply styles to an element based on the size of its parent container. Essentially; it's like conventional media queries, but instead of being limited to updating your layout and styling based on viewport dimensions (and other global media attributes), you can isolate parts of the page and tailor its specific look and behaviour to the context of its container.

For example, consider the following HTML, which displays two boxes sidebyside:

<section className='container'>  <div className='box'>    <p>Box 1</p>  </div>  <div className='box'>    <p>Box 2</p>  </div></section>

Using traditional media queries, we could change the layout of these boxes based on the size of the viewport, using something like:

@media (min-width: 500px) {  .box {    width: 50%;  }}

However, this becomes problematic when elements are nested; where 50% might not equal half the width of the viewport. Container queries resolve this by allowing us to react to the width of the parent container instead.

To start with, we would first set up containment context on the .container element using containertype. In this instance, we use inlinesize so that we can measure based on the inlineaxis of the container, but containertype also accepts size and normal based on your use case. See the documentation here.

.container {  container-type: inline-size;}

With that context created, we can use @container to respond to changes in the .container dimensions. In this example, the .box elements will change from 100% to 50% width, and with smaller text when the parent container width exceeds 500px:

.box {  width: 100%;  font-size: 1.8rem;}@container (min-width: 500px) {  .box {    width: 50%;    font-size: 1.2rem;  }}

You can of course also use Sass nesting if you happen to be using Sass for your CSS generation:

.box {  width: 100%;  font-size: 1.8rem;  @container (min-width: 500px) {    width: 50%;    font-size: 1.2rem;  }}

Graceful Degradation

As with any new CSS feature where support isn't yet great, you will need to consider what happens when a visitor arrives at your site who's browser doesn't yet support container queries. The simplest is to use a @supports rule:

@supports (container-type: inline-size) {  // container query styles here}@supports not (container-type: inline-size) {  // fallback, non-container query styles here}

Google Chrome Labs also offers a polyfill you can bring into your project which uses ResizeObserver to support the @container syntax.

However, from my personal experience, I've found that this can lead to quite a noticeable slowdown and jankiness in the interface especially if you are already doing quite a lot of animation or reactivetype computations.

It may be that you find as I did that it's better to continue down traditional mediaquery routes for responsive development (at least for now) and enhance using @supports, than it is to bring a resourceintensive polyfill into the mix.


Categories:

  1. CSS
  2. Front‑End Development
  3. Responsive Development
  4. Sass