Fashionable CSS retains giving us plenty of new, simpler methods to resolve outdated issues, however usually the brand new options we’re getting don’t solely clear up outdated issues, they open up new potentialities as effectively.
Container queries are a type of issues that open up new potentialities, however as a result of they appear loads just like the outdated means of doing issues with media queries, our first intuition is to make use of them in the identical means, or at the very least a really comparable means.
After we try this, although, we aren’t making the most of how “sensible” container queries are when in comparison with media queries!
Due to how essential media queries have been for ushering within the period of responsive net design I don’t need to say something imply about them… however media queries are dumb. Not dumb when it comes to the idea, however dumb in that they don’t know very a lot. In actual fact, most individuals assume that they know greater than they do.
Let’s use this straightforward instance for example what I imply:
html {
font-size: 32px;
}
physique {
background: lightsalmon;
}
@media (min-width: 35rem) {
physique {
background: lightseagreen;
}
}
What would the viewport measurement be for the background coloration to alter? When you stated 1120px large — which is the product of multiplying 35 by 32 for individuals who didn’t trouble doing the mathematics — you aren’t alone in that guess, however you’d even be fallacious.
Keep in mind after I stated that media queries don’t know very a lot? There are solely two issues they do know:
the dimensions of the viewport, and
the browser’s font measurement.
And after I say the browser’s font measurement, I don’t imply the basis font measurement in your doc, which is why 1120px within the above instance was fallacious.
The font measurement they take a look at is the preliminary font measurement coming from the browser earlier than any values, together with the person agent kinds, are utilized. By default, that’s 16px, although customers can change that of their browser settings.
And sure, that is on function. The media question specification says:
Relative size items in media queries are primarily based on the preliminary worth, which signifies that items are by no means primarily based on outcomes of declarations.
This would possibly appear to be an odd determination, but when it didn’t work that means, what would occur if we did this:
html {
font-size: 16px;
}
@media (min-width: 30rem) {
html {
font-size: 32px;
}
}
If the media question appeared on the root font-size (like most assume it does), you’d run right into a loop when the viewport would get to 480px large, the place the font-size would go up in measurement, then again down again and again.
Container queries are loads smarter
Whereas media queries have this limitation, and for good motive, container queries don’t have to fret about this kind of drawback and that opens up plenty of attention-grabbing potentialities!
For instance, let’s say now we have a grid that must be stacked at smaller sizes, however three columns at bigger sizes. With media queries, we kind of should magic quantity our solution to the precise level the place this could occur. Utilizing a container question, we will decide the minimal measurement we wish a column to be, and it’ll at all times work as a result of we’re wanting on the container measurement.
Which means we don’t want a magic quantity for the breakpoint. If I would like three columns with a minimal measurement of 300px, I do know I can have three columns when the container is 900px large. If I did that with a media question, it wouldn’t work, as a result of when my viewport is 900px large, my container is, most of the time, smaller than that.
However even higher, we will use any unit we wish as effectively, as a result of container queries, not like media queries, can take a look at the font measurement of the container itself.
To me, ch is ideal for this kind of factor. Utilizing ch I can say “when I’ve sufficient room for every column to be a minimal of 30 characters large, I would like three columns.”
We are able to do the mathematics ourselves right here like this:
.grid-parent { container-type: inline-size; }
.grid {
show: grid;
hole: 1rem;
@container (width > 90ch) {
grid-template-columns: repeat(3, 1fr);
}
}
And this does work fairly effectively, as you may see on this instance.
As one other bonus, because of Miriam Suzanne, I lately realized that you may embrace calc() inside media and container queries, so as an alternative of doing the mathematics your self, you may embrace it like this: @container (width > calc(30ch * 3)) as you may see on this instance:
A extra sensible use case
One of many annoying issues about utilizing container queries is having to have an outlined container. A container can’t question itself, so we’d like an additional wrapper above the component we need to choose with a container question. You possibly can see within the examples above that I wanted a container on the surface of my grid for this to work.
Much more annoying is whenever you need grid or flex kids to alter their structure relying on how a lot area they’ve, solely to understand that this doesn’t actually work if the mother or father is the container. As an alternative of getting that grid or flex container be the outlined container, we find yourself having to wrap every grid or flex merchandise in a container like this:
<div class=”grid”>
<div class=”card-container”>
<div class=”card”>
</div>
<div class=”card-container”>
<div class=”card”>
</div>
<div class=”card-container”>
<div class=”card”>
</div>
</div>
.card-container { container-type: inline-size; }
It’s not that unhealthy within the grand scheme of issues, however it’s form of annoying.
Besides there are methods round this!
For instance, for those who’re utilizing repeat(auto-fit, …) you can use the primary grid because the container!
.grid-auto-fit {
show: grid;
hole: 1rem;
grid-template-columns: repeat(auto-fit, minmax(min(30ch, 100%)), 1fr);
container-type: inline-size;
}
Figuring out that the minimal measurement of a column is 30ch, we will leverage that information to restyle particular person grid objects relying on what number of columns now we have:
/* 2 columns + hole */
@container (width > calc(30ch * 2 + 1rem)) { … }
/* 3 columns + gaps */
@container (width > calc(30ch * 3 + 2rem)) { … }
I’ve used this on this instance to alter the kinds of the primary baby in my grid primarily based on whether or not now we have one, two, or three columns.
And whereas altering the background coloration of one thing is nice for demos, we will, after all, do rather more with this:
The draw back to this method
The one draw back I’ve discovered utilizing this method is that we will’t use customized properties for the breakpoints, which might actually enhance the DX of this.
That ought to ultimately change contemplating customized media queries are within the spec editor’s draft of the Media Queries Stage 5 specs, however its been in there for some time with no motion from any browsers, so it could be a very long time earlier than we will use them.
And whereas my opinion is that having customized properties for these would each make them extra readable and simpler to replace, it opens up sufficient potentialities that it’s nonetheless price it with out them.
What about flexbox?
With flexbox, the flex objects are what outline the structure, so it’s just a little unusual in that the sizes we apply on the objects are what are essential within the breakpoints.
It can nonetheless work, however there’s a large problem that may come up for those who do that with flexbox. Earlier than we take a look at the problem, here’s a fast instance of how we will get this working with flexbox:
.flex-container {
show: flex;
hole: 1rem;
flex-wrap: wrap;
container-type: inline-size;
}
.flex-container > * {
/* full-width at small sizes */
flex-basis: 100%;
flex-grow: 1;
/* when there may be room for 3 columns together with hole */
@container (width > calc(200px * 3 + 2rem)) {
flex-basis: calc(200px);
}
}
On this case, I used px to indicate it really works as effectively, however you may use any unit there, as I did with the grid examples.
This would possibly seem like one thing you should use a media question for as effectively — you should use the calc() in them too! — however this may solely work in a single if the mother or father has a width that matches the viewport width, which more often than not isn’t the case.
This breaks if the flex objects have padding
Lots of people don’t understand it, however the flexbox algorithm doesn’t take padding or borders under consideration, even for those who change your box-sizing. When you’ve got padding in your flex objects, you’ll principally should magic quantity your solution to getting it to work.
Right here’s an instance the place I added some padding however I haven’t modified anything, and also you’ll discover a type of awkward two-columns with one stretched on the underside layouts at one level:
Due to this, I do typically discover myself utilizing this kind of method extra usually with grid than flexbox, however there are undoubtedly conditions the place it could nonetheless work.
Like earlier than, as a result of we’re conscious of what number of columns now we have, we will leverage that to make extra dynamic and attention-grabbing layouts relying on the area accessible for a given component, or parts.
Opening up some attention-grabbing potentialities
I’ve solely began taking part in round with this kind of factor, and I’ve discovered that it’s opened up some new potentialities that we by no means had with media queries, and that makes me excited to see what else is feasible!
“Sensible” Layouts With Container Queries initially printed on CSS-Methods, which is a part of the DigitalOcean household. You need to get the publication.
Subscribe to MarketingSolution.
Receive web development discounts & web design tutorials.
Now! Lets GROW Together!