Vertical Rhythm - Tutorial
Keeping a nice, consistent vertical rhythm can have a significant, positive influence on how aesthetically pleasing your visual designs are. In this article I'll shortly explain what vertical rhythm is, and focus on tips on how to achieve it easily in CSS.
What is vertical rhythm?
Short answer: vertical rhythm means that the vertical flow of your design aligns with a set of horizontal lines, spread across at equal distances between each other:
an example from Typing golf
(The distance between those lines will be called *baseline height* throughout this article.)
Keeping the flow of the document/application in sync with a certain rhythm can have various benefits, as explained here:
- Why is Vertical Rhythm an Important Typography Practice? - is a very good article, give it a read!
- Improving Layout With Vertical Rhythm - has a few nice examples of vertical rhythm in action
Please give these articles a read and come back here once you're done for some practical CSS tips.
...
Ok, ready? Here we go.
The baseline height
The baseline is the main measure of rhythm - it's one of the most important choices to consider when designing for vertical rhythm. Think of it as a basic unit of length (height). It is the distance between the horizontal lines that all of the elements should align to.
*The above picture represents a baseline of 24px*
If there's an element that needs to be higher than 24px, either of those two things need to be true:
- the element's height is a multiple of the baseline height.
For example, if the baseline height of the design is 24px, the element's height is 48, 72, 96 (...) px:
> > the element height is an exact multiple of the baseline height
- the element's height is arbitrary, and padding, margins and/or line-height are used to align it to the closest multiple of the baseline height that is larger than it's element's height.
For example: if the baseline height is 24px, and the height of element you want to include in your design is 30px, the closest larger multiple of the baseline height is 48. That means that you have to use 18px of vertical spacing to make the element align with the rhythm. Remember to divide the top and bottom vertical spacing equally!
> > *the vertical margin of the element and it's height add up to a multiple of the baseline height*
Setting up your CSS for vertical rhythm
Now that you know what vertical rhythm is, how do you incorporate in your design? The truth is that it might be hard to add vertical rhythm to an already existing design - it's best to keep the concept in mind during the initial phases of the design process.
The rem trick
While beginning to design with vertical rhythm, you might be struck by two questions:
- what if the baseline I choose is too small or too large?
- what will happen to my design when viewed on a high-dpi screen?
Fortunately, there's a way to address both of these questions and it's best incorporated very early in your css-writing process. Ready? You have to ditch pixels in favor of rems in your entire style-sheet. Why? Here are some of the benefits:
- you can simply set your vertical rhythm measure (the baseline height) to 1rem. Now you don't have to calculate the mulitple of an arbitrary number - if an element's box height is a multiple of 1rem, it doesn't break the rhythm! More on that later.
- rems are adjustable - you can change how many pixels are in 1rem in your design. This means that you can dynamically change the measure of your rhythm even very late in the design process!
- rems are responsive - if handled properly, they will behave properly on screens with various pixel densities
- accessibility - some people have the default zoom level of websites set to over 100%, in order to help with things like vision impairment. rems behave nicely in such environments.
Disclaimer: the above benefits hold true as long as you don't use px anywhere in your style-sheet!
Keeping the rhythm with rems
When using rems for vertical rhythm, in practice it boils down pretty much to these "rules of thumb":
- keep all line-heights a multiple of 1rem
- ensure the vertical height of the box for each element (including padding and margins) adds up to a multiple of 1rem
There certainly is more nuance to the process, but if you apply precisely all the above rules to each element of your design, you should be fine 🙂
I'll keep this section up-to-date as I'll gather feedback on this article :)
Scaling rems
By default, on a regular screen, 1rem = 16px. But the meaning of 1rem can easily be changed to whatever measure you want! rem is defined as (via MDN):
represents the font-size of the root element (e.g. the font-size of the <html> element). When used on the font-size on this root element, it represents its initial value.
So, if it represents the font-size of the <html> element, and we can change the font-size of the <html> element, then we can change the size represented by the rem unit :)
Here's an example:
html { font-size: 24px; } p { line-height: 1rem; /* `1rem = 24px` everywhere in your style-sheet */ }
Using px is not a good idea here. We can get the same result, but more responsive, with:
html { font-size: 1.5em; /* 1em = (usually) 16px. 1.5em = 24px. If someone prefers their font-size to be larger (and configured their browser that way), their preference will be taken into account with this approach. */ } p { line-height: 1rem; /* `1rem = 24px` everywhere in your style-sheet */ }
Which baseline to choose?
Your baseline height should be 1rem. You can change the meaning of 1rem, as demonstrated above. I suggest you start with setting 1rem to 1.5em (which will result in 24px baseline on most screens), as it gives you certain benefits:
- 24px has many divisors, so for example you can use font-size: calc(2/3 * 1rem);, which will result in a pixel-perfect (16px) font size, without having to specify it in pixel units;
- it will give a nice breathing room for paragraphs with the familiar font-size of 16px when used as a baseline.
Caveats
- to keep the rhythm you need to set the line-height of p elements to 1rem. But, by default, p has a font-size of 1rem, as well - which gives a very crowded result:
You can set the font-size to calc(2/3 * 1rem) (which will resolve into 16px on a default configuration) to give the text some more breathing room. You can either set this for p element only, but I recommend to set this for *all* elements:
Debugging vertical rhythm in your layout
I highly recommend using Basehold.it - it gives you a configurable one-liner that you can copy to your html to overlay it with a baseline to help you see if your design is in sync with your vertical rhythm.
If you discover that at some point, the vertical flow of your design starts to desynchronize with the overlay, it's time to debug. My method is to open up the Developer Tools, click the <img src="/uploads/default/original/1X/8505c2fc005bae51e08cc6f3816c7aa8f002ac30.png" width="27" height="28"> button and hover the mouse cursor over suspicious areas.
*Is the element's height a multiple of the specified basline height? In this example we can see that the height is a nice, round multiple of 24 - so it all checks out!*
For more complicated examples, look for details in the "Box model" view in Web Inspector:
*Here we can see that even though the height of the element (30px) is not a multiple of 24, the overall height of the box that contains the element is 48, so the element doesn't break the rhythm.*
Summary
By using rems all across your style-sheet you can preserve vertical rhythm with ease.
*Thanks for reading! Was this article clear and useful? Do you see any ways to improve? Did I leave out any important aspects of the subject? Please let me know :)*
PS. I have written a simple Vertical Rhythm CSS Reset to kick-start the design process. PRs welcome ;)
F28703: image.png | |
Jul 20 2018, 13:46 |
F28707: image.png | |
Jul 20 2018, 13:46 |
F28711: image.png | |
Jul 20 2018, 13:46 |
F28713: image.png | |
Jul 20 2018, 13:46 |
F28701: 38938a91841b70084060fd2e6fc06f1b1fc430b9.png | |
Jul 20 2018, 13:46 |
F28715: image.png | |
Jul 20 2018, 13:46 |
F28709: image.png | |
Jul 20 2018, 13:46 |
F28705: image.png | |
Jul 20 2018, 13:46 |
- Last Author
- kuba-orlik
- Last Edited
- Mar 8 2019, 12:43
Event Timeline
Vertical Rhythm is undoubtedly something that we should care about, but I can't stand rem's advocates still living in rem === dynamic && pixel === fixed world.
World without CSS variables, SCSS and CSS in JS. Just... no
B1:
you can simply set your vertical rhythm measure (the baseline height) to 1rem. Now you don't have to calculate the mulitple of an arbitrary number - if an element's box height is a multiple of 1rem, it doesn't break the rhythm! More on that later.
B2:
rems are adjustable - you can change how many pixels are in 1rem in your design. This means that you can dynamically change the measure of your rhythm even very late in the design process!
You can achieve that also without rems.
If you’re using variables to provide consistent sizing it’s pretty easy to alter sizes throughout an entire design whether px, rem, or otherwise.
CSS variables / SCSS variables / JS variables (CSS in JS) will come in handy depends on the project setup.
The truth is, in well-written & modern front-end app there is / are file(s) where you define registries for fonts, font-families, z-indexes, spacings, line-heights etc.
You can define getters / mixins / WHATEVER upon that.
B3:
rems are responsive - if handled properly, they will behave properly on screens with various pixel densities
B4 :
accessibility - some people have the default zoom level of websites set to over 100%, in order to help with things like vision impairment. rems behave nicely in such environments.
I don't understand B3 or it doesn't make sense, I think it should be elaborated.
We shouldn't embody bad written CSS with unit usage.
Regarding B4 - this should be also elaborated.
I'm working on private app - entirely written in CSS grid + pixels. I can scale that up to 500%. It's perfectly readable and looks nice.
To make this comment more useful for future readers, benefits of pixels:
1. Faster development - designers usually work in pixels, so:
1.1. You can build upon provided sizes
1.2. You can also immediately see if provided size is new one or not -> you can challenge design consistency at a glance.
2. It’s easier to visualise a length in pixels than it is to visualise that same length in rem or em.
3. Pixels are representing something finite, reliable* - after some practice you may predict how particular elements will look like without visual check (also means faster development).
'* Ofc if you realize that CSS pixel !== device pixel
I'm going to end with a quote from article that I came across once (https://mindtheshift.wordpress.com/2015/04/02/r-i-p-rem-viva-css-reference-pixel/):
If you are still using “rem” or “em” for accessibility purpose, stop using them immediately!
They are completely counter intuitive and just introduce another level of abstraction that is no longer needed.
You’re never sure what the root element font-size is and you need to do math in order to get something you can relate to (pixel).
I've encountered many issues while teaching new devs about the CSS pixel vs device pixel difference. I've found that pixels are not something we can easily relate to in world full of retinas, and rems are just as unrelatable but at least don't pretend they are something they're not.
Plus, when working with pixels it's easier to break the rhythm by adding "a few pixels here and there". Not so easy with rems (1.16rem? - easy to notice in CR), which is a good thing.
Many designs I've worked with did not take vertical rhythm into consideration. The designs in most of the projects I've worked on were presented as concepts, not literal pixel-by-pixel directives, so clients didn't complain when we shaved a few pixels here and there. NB. some designs were created on a retina mac, and if pixel measurements were taken seriously, we'd be looking at a 40px body font-size...
I think that a front-end developer also takes part in designing the website. The dev has to fill in the holes left by the graphic designer - like, for example, all the details of how the website wraps between the provided 1920px and 320px -wide mock-ups ;)
I know that I didn't put the above arguments in the article. These are new thoughts, that I've conjured over time and also in direct result of your comment above - so thanks :D