Reading List
Media Queries in Times of @container from Max Böck RSS feed.
Media Queries in Times of @container
With container queries now on the horizon - will we need media queries at all? Is there a future where we build responsive interfaces completely without them?
Ethan, who coined the term responsive web design over a decade ago, has recently said that media-query-less layouts are certainly within bounds:
Can we consider a flexible layout to be “responsive” if it doesn’t use any media queries, but only uses container queries? [...] I’d be inclined to answer: yes, absolutely.
Over at CSS-Tricks, Chris had similar thoughts. He issued a challenge to examine how and where media queries are used today, and if they will still be necessary going forward:
A common refrain, from me included, has been that if we had container queries we’d use them for the vast majority of what we use media queries for today. The challenge is: look through your CSS codebase now with fresh eyes knowing how the @container queries currently work. Does that refrain hold up?
Fair enough.
I took the bait and had a look at some of my projects - and yes, most of what I use @media
for today can probably be accomplished by @container
at some point. Nevertheless, I came up with a few scenarios where I think media queries will still be necessary.
For page layout
Permalink to “For page layout”While container queries can theoretically be used to control any element, they really shine when applied to reusable, independent components. The canonical example is a card component: a self-contained piece of UI you can put anywhere.
Page layouts, on the other hand, are better suited for media queries in my opinion. Page layouts are usually at the very top level of the DOM, not nested in another container. I’ve never encountered a case where the main page layout had to adapt to any other context than the viewport.
.layout {
display: grid;
}
@media (min-width: 60em) {
.layout {
grid-template-rows: 4rem 1fr auto;
grid-template-columns: 25% 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
}
For global tokens
Permalink to “For global tokens”Another good usecase for media queries is to set global design tokens, like spacing or font-sizes. With CSS custom properties it’s now much easier to have fine-grain control over global styles for different devices.
For example, you might want to have bigger text and more whitespace on a large TV than you want for a mobile screen. A larger screen means the user’s head will be physically farther away.
It only makes sense to use a media query there - since the reason for the change is the size of the device itself, not the width of any specific element.
:root {
/* Font Sizes */
--font-size-headline-l: 1.875rem;
--font-size-headline-m: 1.75rem;
--font-size-headline-s: 1.5rem;
--font-size-copy-l: 1.125rem;
--font-size-copy-s: 0.875rem;
/* Global Spacing */
--spacing-x: 1rem;
--spacing-y: 1rem;
}
@media (min-width: 48em) {
:root {
--font-size-headline-l: 2.5rem;
--font-size-headline-m: 2rem;
--font-size-headline-s: 1.75rem;
--font-size-copy-l: 1.25rem;
--font-size-copy-s: 1rem;
--spacing-x: 2rem;
--spacing-y: 2rem;
}
}
For user preference and actual “media” queries
Permalink to “For user preference and actual “media” queries”Screen dimensions are not the only things we can detect with media queries. The Media Queries Level 4 Spec (with Level 5 currently a working draft) lists many different queries related to user preference, like:
prefers-reduced-motion
prefers-contrast
prefers-reduced-transparency
prefers-color-scheme
inverted-colors
- and others
We can use these to better tailor an experience to the current user’s specific needs.
Other media queries allow for micro-optimizations based on a device’s input method (i.e. touch or mouse):
/* fine pointers (mouse) can hit smaller checkboxes */
@media (pointer: fine) {
input[type="checkbox"] {
width: 1rem;
height: 1rem;
border-width: 1px;
border-color: blue;
}
}
/* coarse pointers (touch) need larger hit areas */
@media (pointer: coarse) {
input[type="checkbox"] {
width: 2rem;
height: 2rem;
border-width: 2px;
}
}
Finally, there are actual “media type” queries like @media print
that won’t go anywhere. And there are experimental ideas being discussed for new media queries, like this one for “foldable” devices:
:root {
--sidebar-width: 5rem;
}
/* if there's a single, vertical fold in the device's screen,
expand the sidebar width to cover the entire left side. */
@media (spanning: single-fold-vertical) {
:root {
--sidebar-width: env(fold-left);
}
}
main {
display: grid;
grid-template-columns: var(--sidebar-width) 1fr;
}
BTW: You can read more about this in "The new responsive: Web design in a component-driven world" by Una Kravets.
For fixed-to-window stuff
Permalink to “For fixed-to-window stuff”Components that are taken out of the normal document flow don’t have to care about their containers. Some UI elements are fixed to the viewport itself, usually oriented along an edge of the screen.
Have a look at Twitter’s “Messages” tab at the bottom of the screen for example. Its relevant container is the window, so it makes sense to use a media query here and only apply position: fixed
at some breakpoint.
For heights
Permalink to “For heights”The current implementation of @container
only allows querying the width of an element (its “inline” axis), not its height.
👉 Update: Miriam tells me that it is possible to query the height of containers, provided they are defined as size
rather than inline-size
. The exact value name of this is still in flux at the time of writing.
Style adjustments in relation to width are probably the primary use case for most UI elements anyway, but there are still cases where screen height is an issue. Here’s an example from a “hero image” component:
.hero {
display:flex;
flex-direction: column;
height: 100vh;
}
/* if the screen is really tall, don't fill all of it */
@media (min-height: 60em) {
.hero {
height: 75vh;
}
}
Mix Container Queries and Media Queries
Permalink to “Mix Container Queries and 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.
A perfect team!