[ad_1]
Modern CSS is constantly giving us many new and easier ways to solve old problems, but often the new features we get not only solve old problems but also open up new possibilities.
Container queries are one of the things that open up new possibilities, but because they look a lot As with the old approach to media queries, our first instinct is to use them in the same, or at least a very similar, way.
However, if we do that, we are not taking advantage of the benefits that container queries offer over media queries!
Because it is so important Media inquiries were for ushering in the era of responsive web design. I don’t want to say anything mean about them… but media queries are stupid. Not stupid in the conceptual sense, but stupid in the sense that they don’t know very much. In fact, most people assume they know more than they actually do.
Let’s use this simple example to illustrate what I mean:
html {
font-size: 32px;
}
body {
background: lightsalmon;
}
@media (min-width: 35rem) {
body {
background: lightseagreen;
}
}
How big would the viewport have to be for the background color to change? If you say 1120px
wide – that’s the product of 35 and 32 for those who haven’t bothered to do the math – You are not alone in this assumptionbut you would also be wrong.
Remember when I said that media queries don’t know very much? There are only two things they know:
- the size of the viewport and
- the font size of the browser.
And when I say the font size of the browserI do not mean the font size of the master document, which is why 1120px
in the example above was wrong.
The font size you are viewing is the original font size set by the browser before any Values, including user agent styles, are applied. By default, the 16px
However, users can change this in their browser settings.
And yes, This is intentional. The Media query specification says:
Relative length units in media queries are based on the initial value. This means that units are never based on results of declarations.
This may seem like a strange decision, but if it doesn’t work that way, what would happen if we did the following:
html {
font-size: 16px;
}
@media (min-width: 30rem) {
html {
font-size: 32px;
}
}
If the media query looked at the root font-size
(as most people assume), you would get into a loop if the viewport 480px
wide, where the font-size
The size would keep increasing and then decreasing again.
Container queries are much smarter
While media queries have this limitation (and for good reason), container queries do not have this type of problem, which opens up many interesting possibilities.
For example, let’s say we have a grid that should be stacked at smaller sizes, but three columns at larger sizes. For media queries, we need to magic number our way to the exact point where we want this to happen. Using a container query we can determine the minimum size a column should be and it always works because we are looking at the container size.
This means that we don’t need a magic number for the breakpoint. If I have three columns with a minimum size of 300px
I know that I can have three columns if the container 900px
broad. If I did this with a media query, it wouldn’t work because if my viewport 900px
wide, my container is usually smaller.
But even better: we can use any unit we want.because container queries, unlike media queries, can take into account the font size of the container itself.
Me, ch
is perfect for this kind of thing. With ch
I can say, “If I have enough space for each column to be at least 30 characters wide, I want three columns.”
We can do the calculation ourselves as follows:
.grid-parent { container-type: inline-size; }
.grid {
display: grid;
gap: 1rem;
@container (width > 90ch) {
grid-template-columns: repeat(3, 1fr);
}
}
And it works pretty well, as you can see in this example.
As an additional bonus thanks Miriam SuzanneI recently learned that You can include calc()
Queries within media and containersInstead of doing the calculation yourself, you can include it like this: @container (width > calc(30ch * 3))
as you can see in this example:
A more practical use case
One of the most annoying things about using container queries is having to have a defined container. A container can’t query itself, so we need an additional wrapper over the element we want to select with a container query. You can see in the examples above that I needed a container outside of my grid for this to work.
Even more annoying is when you want Grid or Flex children to change their layout depending on the space available, only to find that this doesn’t really work when the parent is the container. Instead of using that Grid or Flex container as the defined container, we end up having to Pack each grid or flex element in a container like this:
.card-container { container-type: inline-size; }
It is not The All in all, not bad, but kind of annoying.
But there are ways to get around this!For example, if you repeat(auto-fit, ...)
You may Use the main grid as a container!
.grid-auto-fit {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(min(30ch, 100%)), 1fr);
container-type: inline-size;
}
If you know that the minimum size of a column 30ch
we can use this information to redesign individual grid elements depending on the number of columns present:
/* 2 columns + gap */
@container (width > calc(30ch * 2 + 1rem)) { ... }
/* 3 columns + gaps */
@container (width > calc(30ch * 3 + 2rem)) { ... }
I used this in this example to change the styles of the first child element in my grid depending on whether we have one, two, or three columns.
And while changing the background color is great for demos, we can of course do a lot more with it:
The downside of this approachThe only downside I found with this approach is that we can’t use custom properties for the breakpoints, which would really improve DX.
This should ultimately Changes that take custom media queries into account are in the draft specification editor of the Media Queries Level 5 Specificationsbut it has been sitting there for some time without any movement from any browser, so it may be a long time before we can use it.
And while I think custom properties would make it both more readable and easier to update, they open up enough possibilities to make it worthwhile even without them.
What about Flexbox?In Flexbox, the flex elements define the layout, so it’s a bit odd that the breakpoints care about the sizes we apply to the elements.
It may still work, but There is a big problem that can occur when you do this with FlexboxBefore we look at the problem, here is a quick example of how we can make this work with Flexbox:
.flex-container {
display: flex;
gap: 1rem;
flex-wrap: wrap;
container-type: inline-size;
}
.flex-container > * {
/* full-width at small sizes */
flex-basis: 100%;
flex-grow: 1;
/* when there is room for 3 columns including gap */
@container (width > calc(200px * 3 + 2rem)) {
flex-basis: calc(200px);
}
}
In this case I have px
to show that it works too, but you can use any unit you like there like I did with the grid examples.
This might look like something you can also use a media query for – you can calc()
in them too! – but that would only work if the parent element has a width that matches the width of the viewport, which is usually not the case.
This stops if the flex elements have paddingMany people are not aware of this, but the The flexbox algorithm does not take padding or margins into accounteven if you box-sizing
If you padding
With your flex elements, you basically have to find a magic number to make it work.
Here’s an example where I added some padding but didn’t change anything else. You’ll notice at one point one of those weird two-column layouts where one of them is stretched:
For this reason, I generally use this approach more often with Grid than Flexbox, but there are definitely situations where it can still work.
As before, knowing how many columns we have, we can use this to create more dynamic and interesting layouts depending on the space available for one or more specific elements.
Opening up some interesting possibilitiesI’ve only just started playing around with this kind of thing and I’ve found that it opens up some new possibilities that we never had with media queries and that makes me excited to see what else is possible!
[ad_2]
Source link
Posted in Technology