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 />
            </MediaQuery>
        </View>;
    }
}

Responsive UIs in React Native →
react-native-responsive-ui

(*) 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, that only enforces a minimum font-size which isn’t limited by a given max_width? This way more simple 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:

// CONFIG
$min_width: 25;
$max_width: 50;

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

// DEFAULT (LOWER THAN MIN-WIDTH): USE MIN FONT-SIZE AND MIN LINEHEIGHT
:root {
  font-size: #{$min_font}em;
  line-height: #{$min_lineheight}em;
}

// BETWEEN MIN-WIDTH AND MAX-WIDTH: CALCULATE VALUES USING THE VARIANT 100VW
@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})));
  }
}

// GREATER THAN MAX-WIDTH: USE MAX FONT-SIZE AND MAX LINEHEIGHT
@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:

// CONFIG
$min_width = 10;
$max_width = 100;

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

// DEFAULT (LOWER THAN MIN-WIDTH) USE MIN FONT-SIZE AND MIN LINEHEIGHT
:root
  font-size unit($min_font, "em")
  line-height unit($min_lineheight, "em")


  // BETWEEN MIN-WIDTH AND MAX-WIDTH CALCULATE VALUES USING THE VARIANT 100VW
  @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)

  // GREATER THAN MAX-WIDTH USE MAX FONT-SIZE AND MAX LINEHEIGHT
  @media (min-width: unit($max_width, "em"))
    font-size unit($max_font, "em")
    line-height unit($max_lineheight, "em")

Did this help you out? Like what you see? Consider donating.

☕️ Buy me a Coffee ($3)

It certainly is no obligation but it would put a smile on my face. Thanks! 🙂

Precise control over responsive typography →
Molten Leading in CSS →

Coding mobile-first emails

1-tVdHVHlw8RJY7cOy4DNwLQ

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 →

Mediaqueryless Responsiveness

Slides of the – highly entertaining – talk @Vasilis gave at CSS Day 2016 in which he elaborated on a few techniques he experimented with in order to get responsive-like sites without using any media queries.

Some neat tricks include:

  • Calling it “active whitespace” instead of floats getting stacked up 😛
  • Setting a unit-ed value (such as 15em) instead of a plain number as a value for columns
  • Using an URL fragment (window.location.hash) along with an id along with the :target psuedo-class
  • Using vmin and vmax values (in combination with quantity selectors)

iOS9 MobileSafari Viewport Problem

CQe0DfnUwAAqdG7

The viewport is set incorrectly when the viewport meta tag is specified with initial-scale=1 or width=device-width, and the page contains an element (e.g. div tag) that is wider than the desired viewport’s boundary.

In the screenshot above (courtesy @RWD) you can see that the off-screen menu actually appears on-screen in iOS9. Apple changed how iOS9 responds to width=device-width as it, according to them, got abused too much.

To fix this, append shrink-to-fit=no to your viewport meta tag, as such:

<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">

Responsive Principles

Responsive web design has engendered a wider conversation about how we build products that accommodate an increasing breadth of connected devices. This talk will suggest a framework within which we can model this continuing discussion, and outline the principles needed for our work to better respond to a rapidly changing world.

A PDF with presenter notes is also available.

The Web’s Grain

Great piece by Frank Chimero. Starts with that nostalgic nineties feel and finds it way to photography, responsive design, and the fact that some websites try to blow you away with their design/technological advancements.

“Listen bub,” I say, “it is very impressive that you can teach a bear to ride a bicycle, and it is fascinating and novel. But perhaps it’s cruel? Because that’s not what bears are supposed to do. And look, pal, that bear will never actually be good at riding a bicycle.”

This is how I feel about so many of the fancy websites I see. “It is fascinating that you can do that, but it’s really not what a website is supposed to do.”

Reminds me of this quote (supposedly) from Jurassic Park:

Just because we can doesn’t mean we should.

Another interesting thing: On breakpoints he has to say this:

So, those media queries we write? It might be time to stop calling them breakpoints, and instead consider them points of reassembly.

Tomatoh, Potatoh … or is there more to it?

The Web’s Grain →