This content originally appeared on Go Make Things and was authored by Go Make Things
It’s still hard to give a shit about tech right now, and I want to give you an update on my community fridge project soon, but today, I actually am excited about a tech thing!
Today, let’s talk about container queries!
The Use Case
Responsive web design gave us media queries, which let you adjust the layout at certain breakpoints.
For example, you may have layout that starts off as a single column on small mobile devices in portrait orientation, flips to a two-column grid on mid-sized viewports, and then becomes three or four columns in bigger viewports.
.layout {
display: grid;
gap: 1em;
grid-template-columns: 1fr;
grid-template-rows: auto;
}
@media (min-width: 20em) {
.layout {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 40em) {
.layout {
grid-template-columns: repeat(3, 1fr);
}
}
@media (min-width: 60em) {
.layout {
grid-template-columns: repeat(3, 1fr);
}
}This kind of things works great for layouts.
But when you’re building a design system of components, it has some shortcomings.
The viewport size doesn’t matter
On a recent project, I was building out a dropzone component.
It progressively enhances an <input type="file"> element, letting you upload or drag-and-drop files. It also displays previews of selected files in a grid.
This component might span the whole width of a viewport. But it also might be used inside a narrow column, or in a <dialog> modal, or some other small portion of the page.
It wouldn’t make sense to base the file preview grid on the viewport size.
The component might be loaded into a very wide viewport, but inside a modal that’s only 15em (240px) wide. Displaying a four-column grid in such a tiny space wouldn’t make much sense.
What I really care about is the size of the parent container. And here’s where container queries come in.
Container queries FTW!
Container queries exist because Miriam Suzanne fought like hell to make it happen.
The oversimplified explanation is that they’re like media queries, but the use a parent container element as the basis for their calculations instead of the viewport.
Here’s how it works.
First, you have to give the parent container a container-name, which is used to identify it as “the thing to pay attention to when calculating sizes.”
kelp-dropzone {
container-name: dropzone;
}You also need to add a container-type. This tells the browser which stuff to pay attention to.
inline-sizewill trigger a response when the inline axis (the width in top-down languages) changes.sizewill trigger a response when the height or width change.scroll-statewill trigger a response to scroll changes (useful for doing things like snap targets).
For most of the kind of stuff I do, inline-size is the one I want.
kelp-dropzone {
container-name: dropzone;
container-type: inline-size;
}For the element who’s layout should change based on that parent container, I first define my base styles.
.dropzone-preview {
display: grid;
gap: 1em;
grid-template-columns: 1fr;
grid-template-rows: auto;
}Then, I use the @container <container-name> (<query>) {} at-rule to adjust styles based on the parent container.
Unlike media queries, container queries use greater-than/less-than (>/<) operators to do comparisons. MDN has great documentation on all of the options.
@container dropzone (width > 20em) {
.dropzone-preview {
grid-template-columns: repeat(2, 1fr);
}
}
@container dropzone (width > 40em) {
.dropzone-preview {
grid-template-columns: repeat(3, 1fr);
}
}
@container dropzone (width > 60em) {
.dropzone-preview {
grid-template-columns: repeat(3, 1fr);
}
}Now, the component will resize based on it’s parent container rather than the viewport!
Like this? A Lean Web Club membership is the best way to support my work and help me create more free content.
This content originally appeared on Go Make Things and was authored by Go Make Things
Go Make Things | Sciencx (2026-02-04T14:30:00+00:00) Container queries are rad AF!. Retrieved from https://www.scien.cx/2026/02/04/container-queries-are-rad-af/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.