#256: When to use @container queries

[Robin]: Max Böck asks when should we use @container or @media queries?

While I think container queries will eventually replace most “low level” responsive logic, there are still a lot of good usecases for trusty media queries.

A combination of both techniques will probably be the best way forward. @media can handle the big picture stuff, user preferences and global styles; @container will take care of all the micro-adjustments in the components themselves.

Once @container queries get support in browsers and it becomes a part of our daily work, I can see how this question might be confusing for folks getting started in web development. Heck, I can see it being confusing for me! And yet, although Max makes a lot of great points in that piece, I think the quickest explanation between the two could be this:

@media queries are for page layout and @container queries are for components.

That’s a little simplistic but when it comes to component design (like a navigation or a button) you likely want that component to be aware of its environment and the width or height of its parent. Let’s say you want to throw that dropdown component into the sidebar, or grab that button group and put it into a bigger space than it was initially designed for. Those are the moments when @container queries will absolutely shine.

Layouts are a bit different because we don’t often want to nest layouts. If you have a 12-column grid, it’s unlikely you’ll want to nest that grid within another grid component—instead, you’d want the elements to inherit the grid. And that’s precisely what subgrid is for:

See how nested elements above (like the gray rectangle) is aligned to the grid gap of the outer container? That’s good ol’ subgrid and that means we can mostly avoid nesting grid elements within grid elements.

Anyway, I reckon in almost all instances when we’re designing a component we’ll want to use @container. But, saying that, I really hope @media queries aren’t treated later like the <table> element is today, where a ton of people are somehow under the impression that they are bad practice just because they were the best option to lay things out at the time.

Even though @container is on the horizon and it will be fancy new tool under our belt, @media still has its place and is still useful and relevant in layout and design.

[Chris]: I’d revise my earlier statements that the vast majority of *-queries we write in the future will be container queries. Now I’d guess that, on a greenfield project, if you’re authoring that project from front-end components, it’ll be predominately (like maybe 90%) @container queries. If you’re refactoring an existing project, especially one that isn’t really component-based, it’ll maybe be 50% @container and 50% @media. Still just guessing here—it’s fun think about. These are such early days that I don’t think it’s even entirely certain it’ll ship in all the browsers, or even in the form we’re all experimenting with now.

Using the outline Property as a Collapsible Border

For some reason I’ve always avoided the outline property. But it has its uses! Take this example where Carter Li uses it as a collapsible border for tables. Just like this:

There have been many days and nights where I’ve been building a table and had to fight the borders of rows and columns because they didn’t work the way that I expected them to. In the past, you’d have to do some negative margin magic to make sure each cell lines up properly.

This post shows there’s a few gotchas that are interesting. For instance, an outline is always going to add a line around the entire shape, unlike border where you can say border-right only. Also, changing border-width is going to trigger layout in browsers, which makes sense. But it’s a good reminder that although there’s a long list of animatable CSS properties, there are only four things in CSS that can be animated safely without impacting performance: position, scale, rotation and opacity.

Making Tables With Sticky Header and Footers Got a Bit Easier

Speaking of tables, even though position: sticky is amazing, there’s been one thing that’s always been a bit tricky about it. If you want to make a table header stick to the top as you scroll, then it wouldn’t work in Chrome particularly well.

That’s all fixed now, thankfully:

Sounds like a big effort went into totally revamping tables in the rendering engine in Chromium, bringing tables up to speed. It’s not just the stickiness that was fixed, but all sorts of things. I’ll just focus on the sticky thing since that’s what I looked at.

So, if you want to make a table with sticky tables and rows like in this example below, you can totally do that:

Perfect Tooltips With CSS Clipping and Masking

I tend to forget that CSS clipping and masking can lead to really interesting ideas, so when I stumbled over this post by Louis Hoebregts this week where he walks us through the mask-image CSS property, I was pretty excited.

Here’s what Louis built:

Notice the bottom of that image where there’s a curved arrow pointing down? There’s a number of ways you can do that, but using mask-image isn’t what I normally reach for. Chris explained this CSS property a while back and here’s how it works.

First, you have an element with a background-image. Then you could pull in an SVG graphic to use as a mask over it:

.element {
  background-image: url(background.png);
  mask-image: url(star.svg);

So you’ll see something like this:

Just like the background CSS property, we need to tell mask-image to not repeat itself. But we also need to set the mask-size as well. And once we fix those things…

.element {
  background-image: url(background.png);
  mask-image: url(star.svg);
  mask-repeat: no-repeat;
  mask-size: 100%;

…this is the effect we end up with:

So what Louis does is mask his tooltip shape with that little arrow using mask-position to place it at the very bottom of the element. And if you ask me, that’s pretty darn smart.

This is also a good reminder that there’s a lot of things you can do with this technique. Sarah wrote this great piece a while ago about when to use masking and clipping when it comes to SVGs:

Think about masking as a way to apply complex, detailed, and shapes with varying opacity over another element. This can lead to really beautiful visual effects and performant alternatives to other techniques. For instance, animating gradients can be really CPU-intensive. But in the graphic below, we’re animating the mask instead of the gradient to the same visual effect, and it’s a lot less heavy.

Masking is a whole other newsletter, but I love this demo from Craig Roblewsky that helps explain how a mask can change the color of an underlying element:

Inline Styles as Classes

This is some evil stuff here, folks. Sam Thorogood opened the gates of hell to show us how we can write CSS like this:

Chris then blogged about how a classname like this works. You can write some HTML like the following to apply those styles:

<div class="display: flex;"> 
  <!-- content goes here -->

I apologize profusely that you had to see that but technically, display and flex above are two separate CSS classes but you could also write something like this and it would work too:

[class*="padding\: 1rem\;"] {
  padding: 1rem;

Again, I cannot begin to apologize enough for this despicable code you’re seeing and my lawyers have told me that I am not legally responsible for any damage I’ve caused in sharing this any further. They also told me to say that you could write a Sass function or something to create all these classes automatically. But! This would be the work of pure evil and I do not even remotely recommend this. It’s just sort of neat to know that you can do this.

Even if you shouldn’t.

Useful and Useless Code Comments

Jim Nielsen made some notes about what constitutes a “useful” code comment:

If somebody says a comment isn’t adding any value, I would ask: to whom?

Personally, I’ve never liked the advice that writing obvious comments is bad practice—probably because I write obvious comments all the time.

Jim reminds us that what we see as useful might not be what other folks consider useful. Perhaps a team doesn’t have many front-end experienced folks, so commenting helps explain non-trivial CSS things. I could certainly see that being helpful.

I guess my advice to myself when writing comments is this: what am I likely to forget in the future when it comes to this code? Will I forget that this CSS property or class interacts with this other one? Will I forget that I have to do this one weird hacky thing because of the code in another file? That’s the really valuable stuff to write a comment about and pairs well with Sarah’s thoughts on code comments.

axe DevTools

Is your website accessible? Deque’s axe DevTools Pro makes accessibility testing easy for dev teams.

Find and fix potentially critical issues while you code. No expertise required. Build more accessible experiences and get started for free today.


CSS is powerful for creating overlay effects but has a few drawbacks. The same code doesn’t work across devices, or the overlay effect is lost when a user downloads the image! How do we overcome this? Read on to understand how we solve this problem.

[Chris]: In-app command palettes are pretty sweet. Often they manifest in UI as a bar. Like the macOS spotlight thingy, which predominantly searches but also does other things.

And think of a tool like Alfred, also literally a bar, that does countless things.

Those are system wide though. Sometimes these bars are app-specific.

Command palettes aren’t always bars (essentially search inputs) though. Consider the command palette of VS Code. A keyboard command brings up an autocomplete-powered super menu of damn near anything VS Code can do. It’s bar-like—it’s just the bar isn’t there at all unless you ask for it.

Chrome DevTools has a similar palette.

I’m a fan. For one thing, it makes everything keyboard-accessible. For another, if your brain knows this tool can do something, you just forgot where they tucked the function, it’s no matter; you can find it here.

But the “all-powerful” command palette isn’t the only way these things show up. Philip Davis has a great article looking at some examples of command palettes that are more focused. Like Notion’s insertion palette.

That’s not everything that Notion can do, it’s a subset of things contextualized to the action of inserting a new block. Notion has a Quick Find command too, and lots of other keyboard shortcut giving it powerful, yet contextual commands.

The new-ish WordPress block editor has its own version, the block inserter which I’ll use to insert an image of it:

Philip has other interesting examples in there like Raycast, which is a command palette with command palettes inside.

Command palette’s becoming more mainstream is one of my favorite trends in modern applications. There are lots more good examples that I’ve enjoyed using. LinearAlfredFigXcodeVSCodeSketch Runner, and CtrlP.