Container queries in the wild

December 29, 2023

Chris Coyier made an interesting observation about container queries a couple of days ago.

If you’re learning about container queries (anywhere), the chances are high that you’re going to come across demos that use a “card” element. It’s probably going to have an image, a header, and a paragraph. The image will be on top when the card is pretty narrow, and on the side when the card is pretty wide.

That’s OK. There tends to be a top-use-case for CSS features.

Chris Coyier, Every Container Queries Demo is a Card

I had already been thinking about writing this post about some of the ways that I have been using container queries. My first implementation of container queries was the use case that Chris described. It was a card that was part of a grid layout of resources on the Real World Learning site we built for the Kauffman Foundation in 2022.

The card for the desktop was designed to have an icon on the left and a text block with the date, title, and category for the resource on the right. When the card was a smaller size, we wanted the layout to go to one column with the icon on top. (See an image below)

Showing two variations of a card, The first is a one column layout with an icon block on top of a text block. The second variation is a two column layout with the icon block on the left and text block on the right.

I used Flexbox for the layout. For the smaller container, flex-direction is set to column. Then when the container query is met, flex-direction changes to row.

As Chris mentioned in his post, most features have a top use case and for container queries, card layouts are probably the top use case. It is the solution I normally think of first.

But I also want to explore a couple of other ways that I have used container queries in my project work.

Using Container Units

I have been defining containers on parent elements to utilize container query length units. I like these units because I can set padding, element widths, and other things so that they grow or shrink proportionally to the container.

I used it in a hero layout in a project this summer. The column gap uses a container query length unit so that the gap is proportional to the layout. I also used the units to set the top and right margins on the image and to size the light blue square decoration in the top right. (see image below)

In another layout on the same project, I used container query length units to size text. I used a max() function to set a minimum font size and then used container query units for the maximum size so that it was proportional to the container.

It might not have been the best solution but it worked for what I wanted it to achieve. I was able to experiment using a different technique to have a more fluid text size that was in relationship to the container.

Two column layout with a grid of 4 images on the left and a text block with a heading, two paragraphs, and a call to action button on the right.

Code for the heading element:

h2 {  
  --container-width: 1518;  
  --min-font-size: 48px;
  --max-font-size: 64;
  color: var(--mid-blue);
  font-size: max(var(--min-font-size),var(--max-font-size)/var(--container-width)*100*1cqi);
  margin-bottom: 0.34375em;
}

Resizing and changing the layout of a component

The final example comes from a project for Toyota Policy Drivers that will launch in the new year. Each year, LGND has built a custom game program that has boosted engagement by challenging Toyota’s Policy Driver community to unlock higher levels of a game through grassroots advocacy participation.

One of the components of this year’s game hub is a progress/achievement bar. The progress bar contains the user’s avatar, and progress in the game, and tells the user how many points they have earned and how many are needed to earn a key to unlock a door to complete a level of the game.

The points row drops under the progress bar on smaller desktop and tablet screens.

As with most projects, I was given a mockup of the desktop layout and then it is up to me to make the design responsive across different screen sizes. The progress bar component layout needs to expand from one row to multiple rows and different configurations as the screen size gets smaller. The site has a navigation bar that is set on the left-hand side of the interface for larger screens and on the top of the screen for smaller ones.

The progress and points rows go underneath the avatar on smaller screens.

One of the things I like about container queries is that changes are made based on the container width, not the viewport width. Because the navigation bar changes location, using container size made much more sense in changing the layouts of the progress bar component. I also utilized container query units to margins and spacing so that the layout stays proportional.

You can view a demo of this layout on Codepen

Conclusion

I am still experimenting with container queries and using container query units to build better and more robust layouts that work across screen sizes. I am looking forward to continuing to push the boundaries of my knowledge and find new ways to utilize this exciting CSS feature.


This post is part of my attempt to post something every day for a month. I was inspired by Michelle Barker, who recently participated in National Blog Posting Month.

Comment on this post