Molten Leading in CSS

Avatar of Chris Coyier
Chris Coyier on

Dave and I started the latest ShopTalk Show with an audio clip from Tim Brown responding to some of our previous chatter regarding vertical rhythm (and such). Transcription here. It sparked another interesting conversation about these things.

A small part of that was about Tim’s coined phrase “molten leading”, which is essentially line-height that depends on line length.

It’s actually a “triadic” relationship, as Tim puts it:

What interests me most here is a fundamental triadic relationship in typesetting — that of a text’s font size, line height, and line length. Adjusting any one of these elements without also adjusting the others is a recipe for uncomfortable reading, which is one reason designers have such a difficult time with fluid web layout.

There is no simple obvious way to connect an element’s width and its line-height in CSS (although you can with JavaScript). I’d call this yet-another use-case for container queries! You can adjust line-height with media queries (as Andy Clarke suggested). Basic example:

main {
  line-height: 1.4;
}
@media (max-width: 600px) {
  main {
    line-height: 1.3; 
  }
}

But, the browser window width isn’t necessarily indicative of the current element width.

Also, any kind of fixed breakpoint solution isn’t the perfect solution here anyway. A more fluid connection between these three properties would be better. Something that gets us a little closer here (since Tim-and-friends original explorations in 2012) is calc() and combining it with viewport units.

We’ve talked about viewport units around here before. By setting font-size with vw, we can make type that sizes based on the browser window width.

Here’s an example where we have some base values that we just sprinkle with viewport units:

body {
  font-size: calc(1em + 1vw);
  line-height: calc(1.2em + 1vw);
}

See the Pen Molten Leading by Chris Coyier (@chriscoyier) on CodePen.

That’s pretty simplistic. Tim originally suggested a more complex formula:

((current width − min-width) / (max-width − min-width)) × (line-height − min-line-height) + min-line-height = line-height

Turns out Mike Riethmuller has played with this already. Which plays out like this, for example:

body {
  font-size: 1em;
  line-height: 1.4em;
}

@media screen and (min-width: 20em) {
  body {
    font-size: calc(1em + (1.3125 - 1) * ((100vw - 20em) / (80 - 20)));
    line-height: calc(1.4em + (1.8 - 1.4) * ((100vw - 20em) / (80 - 20)));
  }
}

@media (min-width: 80em) {
  body {
    font-size: 1.3125em;
    line-height: 1.8em;
  }
}

Mike even Sass’d that up:

$min_width: 400;
$max_width: 800;

$min_font: 12;
$max_font: 24; 

:root { font-size: #{$min_font}px; }

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

See the Pen Precision responsive typography by Mike (@MadeByMike) on CodePen.

So yeah: it’s a thing you can do.