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:
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.
I was really interested in that opening section about molten leading from the podcast, and it’s cool to see it in action. But – ahm – seeing it in action, I am not totally sure that, like, it really is more “comfortable” a reading experience when the line-height changes at the smallest screen sizes. I get that type nerds — said with all due respect! — perceive the importance, but it also kind of hurt my eyes.
Hurts my eyes too. Seriously, who likes their fonts that small on their phone and that big on their desktops?
Nobody is mandating any of the minimums and maximums here. You should make those choices based on a good reading experience.
If we’re going with the “arrrgggg! my eyes!!” hyperbole, I’d say the most blood pours from my facebeans when line height and font size aren’t considered in conjunction with line length ;)
Chris, that’s true, just really bad defaults on that demo I guess.
Facebeans. Heh.
Looks like this won’t be supported in Firefox until v48:
https://bugzilla.mozilla.org/show_bug.cgi?id=594933
Chrome, IE11 and Edge all work fine.
But what if you could access the elements width inside of the CSS for it? With EQCSS this would be
eval("clientWidth")
anywhere inside of an@element
query, so you could definitely use this as one of the values within thecalc()
!I had to do something similar lately, shrinking longer text for print so it didn’t break onto two pages – and I’ve been thinking about how to adapt this to take the line-length into account, so this post is very timely :)
Thanks!
Here’s an explanation of the math for those wondering what sorcery this is:
Let’s break it down…
I think I’m more comfortable using element queries for this, https://github.com/marcj/css-element-queries
Getting the numbers right here seems crazy tricky.
Using a regular unit with the viewport unit in
calc()
also has the bonus of preserving browser zoomAw, it ate my emoji. It was exuberant, I assure you.