Demos

Container Queries in action

Overview

This demo site serves as a reference for how developers can use container queries, with a fallback for non-supporting browsers. It implements the techniques outlined in the article How to use container queries now.

The strategy is simple to implement, highly-performant, and embraces progressive enhancement, so if you want to use container queries on your site, this is a great option!

How to use the site

  • Browse through the demos listed in the left-hand navigation menu. For each of the demos, resize them to see how they respond. Note: the demos are best viewed on a large screen so you can resize them.
  • You can resize the demo by dragging the divider between this content area and the "Pinned demo" sidebar. You can also collapse both the right and left sidebars or resize the browser window.
  • Lastly, you can click the "pin demo in sidebar" button from any demo page to compare different demos side by side.

How it works

In browsers that support container queries natively, all styles are handled (as expected) by the @container rules defined in the CSS.

In browsers that don't support container queries, a <responsive-container> components is added that leverages ResizeObserver to add breakpoint-specific classes to itself whenever its size changes. Fallback styles are then defined in the CSS that match the exact behavior of the native @container. For more details, check out the blog post How to use container queries now or view the demo source on GitHub.

To better understand how the live representation of the <responsive-container> DOM structure. Resize the content area to see it change:

<responsive-container class="" >
  <!-- Component goes here... -->
</responsive-container>

The default breakpoint classes used on this site correspond to the following size definitions. (Note that breakpoint sizes are fully customizable, and not all components define styles for every breakpoint):

Breakpoint name Container size
XS (base styles, applied by default)
SM @container (min-width: 384px)
MD @container (min-width: 576px)
LG @container (min-width: 768px)
XL @container (min-width: 960px)

Testing the fallback

Most developers reading this are probably using a modern browser, and if so it means you're looking at the native container query version rather than the fallback version.

To see the different variations of this strategy in action, you can check out the following builds:

Version Description
index.html Contains both the native and fallback versions (uses feature detection to serve the appropriate one)
native-only.html Contains just the native version (non-supporting browsers will see the default styles)
fallback-only.html Contains just the fallback version (useful for testing that the fallback works properly)
no-fallback.html Contains no fallback (useful for seeing how the default styles look if the fallback fails for any reason)

Next steps

  • Want to go deeper?
    Read about the implementation and check out the source code.

  • Have an idea to improve the strategy?
    Open an issue on GitHub!

  • Disagree with everything I've ever said?
    Cool, write a blog post and tell the world why your idea is better!

Calendar

  • 9 a.m.
  • 10 a.m.
  • 11 a.m.
  • 12 p.m.
  • 1 p.m.
  • 2 p.m.
  • 3 p.m.
  • 4 p.m.
  • 5 p.m.
5
Mon
  • 9 – 11 a.m.
    Planning
  • 12 – 2 p.m.
    Team lunch
6
Tue
  • 12 – 1 p.m.
    Work out
  • 2 – 3 p.m.
    Doctor
  • 4 – 6 p.m.
    Soccer
7
Wed
  • 9 – 11 p.m.
    Customer call
  • 2 – 6 p.m.
    Team event
8
Thu
  • 12 – 1 p.m.
    Work out
9
Fri
  • 9 – 6 p.m.
    No meetings

The code

<!-- Container element -->
<responsive-container>
  <!-- Component element -->
  <div class="Calendar">...</div>
</responsive-container>

Card

Card title

A basic card component with an image, title, description, and call to action. By default, the image is on top and full-width, but inside larger containers the image is positioned on the left with the rest of the content beside it.

The code

<!-- Container element -->
<responsive-container>
  <!-- Component element -->
  <div class="Card">...</div>
</responsive-container>

Form

Must be at least 8 characters

Go deeper

<!-- Container element -->
<responsive-container>
  <!-- Component element -->
  <form class="Form">...</form>
</responsive-container>

Gallery

The code

<!-- Container element -->
<responsive-container>
  <!-- Component element -->
  <ul class="Gallery">
    <li></li>
    <li></li>
    <li></li>
    ...
  </ul>
</responsive-container>

Nested containers

The code

This demo shows the Card component nested inside the Gallery component, where each of the Gallery component items serve as the container element for each Card component. As the gallery's matching breakpoint changes, its layout will update and in turn cause a change in size to the card's container element.

<!-- Outer container element (named) -->
<responsive-container name="Gallery">
  <!-- Outer component element -->
  <div class="Gallery">
    <!-- Inner container element -->
    <responsive-container>
      <!-- Inner component element -->
      <div class="Card">...</div>
    </responsive-container>
    <!-- Inner container element -->
    <responsive-container>
      <!-- Inner component element -->
      <div class="Card">...</div>
    </responsive-container>
    ...
  </div>
</responsive-container>

Custom breakpoints

Multi-column layout

Most of the demos on this site use the same, global set of breakpoints, but in some cases a component needs to define its own breakpoints due to its particular design needs.

For example, this component defines custom breakpoints so it can know when to switch from a 1-column layout to a 2-column layout (and from 2 to 3). The default breakpoints don't quite work here, so custom breakpoints are needed.

The custom breakpoints are defined on this specific component by setting JSON in the data-breakpoints attribute of the container element. Check out the source links below for more details.

The code

<!-- Container element -->
<responsive-container breakpoints='{"C2":400,"C3":800,"C4":1200}'>
  <!-- Component element -->
  <div class="MultiColBox">...</div>
</responsive-container>
Pinned demo