Responsive Layouts, Fewer Media Queries

Over at CSS-Tricks you can read a min-bending article by Temani Afif

Since the introduction of media queries (literally decades ago), CSS has evolved to the points that there are a lot of tricks that can help us drastically reduce the usage of media queries we use. In some cases, I will show you how to replace multiple media queries with only one CSS declaration. These approaches can result in less code, be easier to maintain, and be more tied to the content at hand.

Common theme in all code shown is the use if max() and clamp(), resulting in code that’s hard to grasp:

grid-template-columns: repeat(auto-fit, minmax(clamp(100% / (var(--n) + 1) + 0.1%, (var(--w) - 100vw) * 1000, 100% / (var(--m) + 1) + 0.1%), 1fr));


Be sure to stick around for the More Tricks section of the post, as it also holds some nice things you can do:

  • Conditional background color
  • Toggling an element’s visibility (by conditionally limiting the height/width)
  • Changing the position of an element

While I do like the results, I’ll stick to using the more readable CSS Container Queries syntax once that becomes stable 😅

Responsive Layouts, Fewer Media Queries →

Media Queries in Times of Container Queries

Max Böck:

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?

As Max details we will still need both, but will see a shift from some Media Queries to Container Queries. Good read; I found myself nodding along for the entirety of the post.

Media Queries in Times of Container Queries →

Viewport Unit Based Typography vs. Safari


A common thing to do regarding font-sizing is to use Viewport Unit Based Typography, nowadays often combined with CSS min() or clamp():

:root {
  font-size: min(calc(1em + 1vw), 4em);

However, as Sara Soueidan details, Safari doesn’t co-operate here:

In Safari on macOS, the fluid text wasn’t really fluid—resizing the viewport did nothing to the font size, even though the latter is supposed to respond to the change in viewport width.

It’s a bug, slated to be fixed in the next version of Safari (Safari TP already has the fix). In the meantime there’s an easy workaround we can use.

More details + demo on Sara’s blog.

Working around the viewport-based fluid typography bug in Safari →

Re-reading that Viewport Unit Based Typography post from 2016 I now see that it also mentions that Safari doesn’t play nice with it. Let this underline the importance of filing bugs: because Sara filed a bug the Safari team came to know about the bug and fixed it (very fast too).

The new responsive: Web design in a component-driven world

In this session from Google I/O 2021, Una Kravets talks about “the new responsive”, short for being responsive to the user, container, and form-factor (text-version available via link below):

The web community is entering into a new era of responsive design and shifting our perspectives on what it means. With user preference queries, container queries, and other form-factor queries on the horizon, we’ll soon have the tools to create responsive designs far beyond what querying the global viewport allows.

To me, this post is the perfect successor to A List Apart’s A Dao of Web Design and Responsive Web Design. The timing is only off by one year …

The new responsive: Web design in a component-driven world →

Responsive Images the Simple Way

The logic behind displaying an image responsively is complicated. It involves determining how large the image will be displayed, as well as understanding whether the user is on a high-resolution display, among other things. Thankfully, the browser is better equipped than we are to handle this logic. All we need to do is give it some hints. We’ll use the srcset attribute to provide a list of image assets to choose from, and the sizes attribute to tell the browser how large the image will display at various breakpoints.

Yes, the syntax is still the same as in 2014, but it’s good to be remembered of it … I always find myself looking things up again when it comes to Responsive Images 😬

Responsive Images the Simple Way →

Responsive UIs in React Native

On the web it is – by now – obvious that you make your website responsive (*). Using a listener listening to the change event of the Dimensions API, it’s also possible to implement this kind of behaviour in React Native.

import {Component} from "react";
import {Dimensions} from "react-native";

export default class LogDimensionChanges extends Component {
    state = Dimensions.get("window");
    handler = dims => this.setState(dims);

    componentWillMount() {
        Dimensions.addEventListener("change", this.handler);

    componentWillUnmount() {
      // Important to stop updating state after unmount
      Dimensions.removeEventListener("change", this.handler);

    render() {
        const {width, height} = this.state.window;
        const mode = height > width ? "portrait" : "landscape";
        console.log(`New dimensions ${width}x${height} (${mode})`);
        return null;

This logic is applied into the react-native-responsive-ui package, which provides you with a <MediaQuery /> component, ResponsiveStyleSheet class, etc.:

import React, {Component} from "react";
import {View} from "react-native";
import {MediaQuery} from "react-native-responsive-ui";

export default class Login extends Component {
    render(): React$Element<*> {
        return <View>
            <MediaQuery minHeight={450} orientation="portrait">
                <Logo />

Responsive UIs in React Native →

(*) I know, this site still uses a non-responsive WordPress theme … shame on me

Responsive Components: a Solution to the Container Queries Problem

Extensive writeup by Philip Walton on how he tackles the Container Queries problem.

Instead of narrowly focusing on the specific CSS feature proposal we call “container queries”, I want to focus on the broader concept of building components that respond to their environment. And if you accept this larger framing, there are actually new web APIs that already let you achieve this.

That’s right, we don’t need to wait for container queries to start building responsive components. We can start building them now!

His result takes about the same approach as Elementary takes, but then using the more modern ResizeObserver.

Must say I’m leaning more towards Elementary though, as:

  • Elementary targets the responsive elements themselves, and not their parent element.
  • Elementary defines the breakpoints in the CSS itself and not the HTML (something Philip points out too).
  • Philip’s solutions relies on ResizeObserver which is only available in Chrome right now.

Responsive Components: a Solution to the Container Queries Problem →

Responsive Typography

Mike Riethmuller:

It is possible to have precise control over responsive typography. Using calc() and viewport units you can create fluid type that scales perfectly between specific pixel values, within a specific viewport range.

The formula used is this one:

@media (min-width: #{$min_width}px) and (max-width: #{$max_width}px) {
    font-size: calc(#{$min_font}px + (#{$max_font} - #{$min_font}) * ( (100vw - #{$min_width}px) / ( #{$max_width} - #{$min_width})));

As 100vw resembles 100% of the viewport width, the font-size will adjust along with it (between the given min_width and max_width).

💡 Looking for a more simple version of this? This viewport based typography method has got you covered.

It’s possible to also adjust the line-height, using the same formula. The full code then becomes:

$min_width: 25;
$max_width: 50;

$min_font: 1;
$min_lineheight: 1.35;
$max_font: 1.2;
$max_lineheight: 1.8;

:root {
  font-size: #{$min_font}em;
  line-height: #{$min_lineheight}em;

@media (min-width: #{$min_width}em) and (max-width: #{$max_width}em) {
  :root { 
    font-size: calc(#{$min_font}em + (#{$max_font} - #{$min_font}) * ( (100vw - #{$min_width}em) / ( #{$max_width} - #{$min_width})));
    line-height: calc(#{$min_lineheight}em + (#{$max_lineheight} - #{$min_lineheight}) * ( (100vw - #{$min_width}em) / ( #{$max_width} - #{$min_width})));

@media (min-width: #{$max_width}em) {
  :root { 
    font-size: #{$max_font}em;
    line-height: #{$max_lineheight}em;

If you’re looking for the Stylus variant (which is my preferred CSS Preprocessor), here’s one I’ve knocked up:

$min_width = 10;
$max_width = 100;

$min_font = 1;
$min_lineheight = 1.35;
$max_font = 1.2;
$max_lineheight = 1.8;

  font-size unit($min_font, "em")
  line-height unit($min_lineheight, "em")

  @media (min-width: unit($min_width, "em")) and (max-width: unit($max_width, "em"))
    font-size "calc(%s + (%s - %s) * ((100vw - %s) / (%s - %s)))" % (unit($min_font, "em") $max_font $min_font unit($min_width, "em") $max_width $min_width)
    line-height "calc(%s + (%s - %s) * ((100vw - %s) / (%s - %s)))" % (unit($min_lineheight, "em") $max_lineheight $min_lineheight unit($min_width, "em") $max_width $min_width)

  @media (min-width: unit($max_width, "em"))
    font-size unit($max_font, "em")
    line-height unit($max_lineheight, "em")

Precise control over responsive typography →
Molten Leading in CSS →

Coding mobile-first emails


Typically, emails are coded starting with an old school, table based desktop version, with mobile styles applied through a max-width media query to reflow the tables. In email clients that don’t support this, this approach can result in inconsistent rendering and difficult to read emails.

We’re going to flip the formula and start with the mobile version first instead, then work our way back to the desktop version.

Great resource!

Coding mobile-first emails →