Responsive Vertical Rhythm with CSS Custom Properties and CSS Calc

Vertical Rhythm is an important concept in web design. It has the ability to bring a design together and make different elements feel consistent on the same page.

It was impossible to change Vertical Rhythm at different viewports previously, because we didn’t have the right tools. But now, with CSS Calc and CSS Custom Properties, we can change Vertical Rhythm at different viewports. This article explains how.

Calculating the rhythm unit

A rhythm unit is the base multiple you’d use for the Vertical Rhythm of your site. The value of a rhythm unit should be the line-height of your body text. Here’s why.

/* One rhythm unit would be 20px * 1.4 = 28px */   
  font-size 20px  
  line-height 1.4 
   margin 28px 

Calculating the rhythm unit becomes easier if you use relative units (and you should). One rhythm unit will always be equal to the root font-size times the line-height of your body text.

/* 1 rhythm unit, calculated with rem */
  line-height 1.4 
   margin 1.4rem 

When you create whitespace, feel free to vary the number of rhythm units. You can even include non-integer values.

/* 2 rhythm units */  margin-top 2.8rem 
/* 0.75 rhythm units */  margin-top 1.05rem 

Why change Vertical Rhythm at different viewports?

We tend to place larger devices (like desktops) farther away than smaller devices (like phones). We need to increase font-size to compensate for the loss in readability due to the increased distance. If your user can’t read your site comfortably, they’ll likely leave, they’ll squint their eyes, or increase their browser’s front-size (if they’re savvy enough).

A little more on readability.

Readability is one of the most important elements to web typography. It’s affected by three values—the font-size, line-height (or leading), and line-length (or measure) of your text. When one element changes, others may need to change to preserve readability.

When you resize a browser from a mobile view to a desktop view, you’ll notice that both measure and font-size changes. As a result, leading should change too. This concept is so important that Tim Brown came up with the Molten leadingapproach. One example of molten leading in use is where you write your body line-height with viewport units.

/* This is a simple example. See the complete example in the link above */   font-size 1em + 1vw  line-height 1.2em + 1vw 

But the problem is, when you change the line-height of your body text, the Vertical Rhythm unit changes. There’s no way to incorporate Molten leading with Vertical Rhythm.

Now, even if you discarded molten leading and used the standard unitless line-heights, you’ll probably still go insane from the amount of duplication you need to create. Not worth the effort.

/* Change line height at different breakpoints */   line-height 1.4 

@media min-width 600px        line-height 1.5   
/* Calculate rhythm again at each breakpoint */   margin-top 1.4rem 

@media min-width 600px        line-height 1.5rem  

Changing the rhythm unit with CSS Custom Properties

CSS Custom properties (better known as CSS variables) can be used to create a rhythm unit that changes at different viewports.

To create a CSS variable, you create a custom property (hence it’s name) by prepending -- to a property.

:root   --color red 

To use a custom property you created, you write var(--your-custom-property).

   color --color 

The great thing about CSS Custom Properties is: they can be updated dynamically within different media queries.

:root   --color red 

@media min-width 30em   :root     --color blue      color --color 
GIF that shows a paragraph to text switching between red and blue colors
CSS Custom properties are updated dynamically, even within media queries!

That means you can create a --baseline property that correspond to one rhythm unit, then, use this --baseline property across your CSS to create responsive Vertical Rhythm.

:root   --baseline 1.4  line-height --baseline 

@media min-width 30em   :root     /* a value of 3 used here to exaggerate the changes so you can see it in the demo below */    --baseline 3  
GIF that shows that line-height can be changed via the baseline custom property.
Line height can be changed at different breakpoints via a custom property

To create rhythm values, you can need to use CSS Calc (because you can only calculate stuff in CSS with CSS Calc).

/* Two rhythm units */  margin-top --baseline * 2rem  /* 0.75 rhythm units */  margin-top --baseline * 0.75rem 
GIF that shows the margins of both <h2> and <p> change at the breakpoint
CSS Calc can be used together with CSS Custom Properties to calculate rhythm values

(Before we move on, here’s a quick signup form if you'd like to read similar articles from me every Wednesday).

Want to become a better Frontend Developer?

Don’t worry if you don’t know where to start. I’ll send you to the perfect place – a library of articles on CSS, JavaScript and Node that FEDs like yourself have found helpful. Each week, I’ll also send you an article to help you improve your FED skills crazy fast.

Powered by ConvertKit

Simplifying the calculation with a function

It can be a chore to write calc and var every time you create a rhythm value. You can simplify the calculation if create a function in a preprocessor like Sass.

// rvr stands for responsive vertical rhythm @function $multiple   @return --baseline  $multiple  1rem 

Then, you can use the vr function you’ve created like this. Much simpler! 💃.

/* Two rhythm units */ margin-top 2  /* 0.75 rhythm units */ margin-top 0.75 

How does support look like?

Support for both CSS Custom Properties and CSS Calc are awesome. They’re supported in all major browsers today.

Support chart for CSS Custom properties from
CSS Custom Properties are pretty well supported!
Support chart for CSS Calc from
CSS Calc is pretty well supported too!

Unfortunately, support for both CSS Calc and CSS Custom is lacking in Opera Mini (along with some lesser known browsers like QQ and Baidu); that’s a bummer.

Since Opera Mini doesn’t support CSS Calc and CSS Custom properties, we need to provide fallback properties each time we create a rhythm unit. This is slightly more work, but luckily, not a deal breaker.

:root   --baseline 1.4  /* Line-height fallback */  line-height 1.4  line-height --baseline  1rem 

@media min-width 30em   :root     --baseline 1.5   
  /* Line-height basic vertical rhythm fallback. */  margin-top 1.05rem  margin-top 0.75 

To make it simpler, you can also create a vr function that calculates Vertical rhythm based on the base line-height value. Here’s a simple version you can use (specifically for this example). If you’d like a more complete version, check out Typi, which is a library I’ve made to help make responsive typography simpler.

@function $multiple   @return 1.4  $multiple  1rem 

If you create the vr function, your rhythm fallback would be simpler:

   /* Line-height basic vertical rhythm fallback. */  margin-top 0.75  margin-top 0.75 

Note: I’ve yet to include responsive vertical rhythm in Typi yet. I hope to add it when I get some time on my hands.

Wrapping up

Vertical Rhythm is an important typography principle we should pay attention to, as designs and developers. Unfortunately, we couldn’t give it as much attention as we should because we lacked the tools to do so.

But now, we can create responsive vertical rhythm with the help of CSS Custom Properties and CSS Calc. If you create responsive vertical rhythm, make sure you provide fallback for browsers that don’t support either CSS Custom Properties and CSS Calc!

Bludit Themes

Bludit Themes