How To Use Compass Vertical Rhythms

Vertical Rhythms are part and parcel of good web design. Although they are important, they can be an incredibly chore to calculate.

Luckily, Compass has a great vertical rhythm module that helps clears this mess up.

Compass Vertical Rhythm

Compass requires the use of Sass, a css preprocessor. If you’re not sure whether you want to start using a preprocessor like Sass, check out one of my previously written articles.

The Compass Vertical Rhythm reference is great, but may possibly overwhelm if you’re new to it.

In this post, we’re going to talk about how to use this powerful addon.

Note: You need to have the alpha version of Compass installed to before this tutorial will work. You can install compass alpha with

$ sudo gem install compass --pre

Configuring Vertical Rhythms

The first step to using Compass vertical rhythms is to configure a few variables. You can ignore most of the variables listed on the compass reference page with the exception of these two.

// Compass Vertical Rhythm Settings
$base-font-size: 20px; // Sets the base font size
$base-line-height: 36px; // Sets the base line height 

The following two modules are useful, but completely optional

$round-to-nearest-half-line: true; // Allows compass to round to  multiples of 0.5x line height 
$rhythm-unit: "rem"; // Sets rhythm unit to rem. Remove to use default em unit. 

I personally like to allow compass to automatically round to the nearest half line instead, and this can be very helpful when large header titles have to get bumped to two lines.

Rem unit is one of my favourites, and I use them for my development. However, it is not supported by IE 8. Unless you’re willing to get a polyfill for the rem unit, you might want to stick with default ems.

Now that you’ve set the basic compass variables, you’re more to less good to go. I will go one step further and list down basic font sizes that will be used in the website.

// Note these are custom. You have to tell compass to use them yourself 
$h1-fz: 45px;
$h2-fz: 30px;
$h3-fz: 24px;
$h4-fz: 20px;
$h5-fz: 16px;
$h6-fz: 13px;

Using Compass Vertical Rhythm

Telling Compass to set the baseline is quite simple, with the use of only one line of code.

// Establishes baseline with Compass.
@include establish-baseline;

This sets the default font size and line height you have previously declared into the html selector. The output will be slightly different depending on whether you’re using the experimental version of compass.

/* Standard Compass Version. At the time of writing this is v0.12.2.  
Thanks to Maximilien for noticing this */ 
* html {
  font-size: 125%; }

html {
  font-size: 20px;
  line-height: 1.8em; 

/* Experimental Compass Version. At the time of writing this is v1.0.0.alpha.18 */ 
html {
  font-size: 125%;
  line-height: 1.8em;

Remember the various heading font sizes we set earlier? You have to tell compass to use them with the adjustfont-size-to mixin. This mixin takes up to 3 arguments.

// Adjust font size to mixin. 
// Note that those in [] are optional arguments. 
adjust-font-size-to($to-size, [$lines], [$from-size])

$lines = number of line heights this font is suppose to take up. 
$from-size = current font size used to adjust to target font size. 

$lines will default to the nearest line height multiple that can accomodate the target font size. It will round to the nearest half line height if $round-to-nearest-half-line is set to true. This number need not be an integer.

For example, if the target font size is 45px, the base-line-height is 36px, the resultant line height will either be 54px or 72px (in em or rem unit), depending on what $round-to-nearest-half-lineis set to. By stating $lines explicitly, you are telling compass to use your declaration instead of calculating them.

If you’re using ems as the rhythm unit, you have to tell compass to use the $from-size variable if the current container has a different font size than the base declared up above.

If you are using rems, you don’t have to bother about $from-size at all.

Here’s how you can use the adjust-font-size-to mixin. You can use this anywhere you need to.

h1 {
  @include adjust-font-size-to($h1-fz);

h2 {
  @include adjust-font-size-to($h2-fz);

h3 {
  @include adjust-font-size-to($h3-fz);

h4 {
  @include adjust-font-size-to($h4-fz);

h5 {
  @include adjust-font-size-to($h5-fz);

h6 {
  @include adjust-font-size-to($h6-fz);

The rhythm() function

The rhythm() function is the single most useful function in Compass. It allows you to quickly calculate multiple line-heights worth of margins and paddings without doing the math. This number need not be an integer

.example-selector {
  margin: rhythm(1) 0; // This translates to 36px margin top and bottom since the declared base lineheight is 36px. 
  padding: rhythm(1) 0; Similarly, this adds 36px of padding instead

In Conclusion

That’s really all to it to using Compass for vertical rhythm. Its incredibly quick and easy. There are many other functions provided that I don’t use often, but you can find them all in the reference.

Try using vertical rhythms in your next project and let me know how you find it!


Enjoyed the article?

  • Minh Phạm

    Why “rem”? What is the benefit of using “rem”?

    • Zell Liew

      Rem stands for Root em, and its easier to calculate compared to em since the base size used for calculations is always with reference from the root defined in html {} with @incude establish-mixin.

      Em always calculates with its base as the parent container, so if there are any changes to the parent container size, the calculation has to change to make sure you get the correct size.

      Take a look at this post It explains rems very clearly.

  • Max

    Why is it that when I do : @include establish-baseline;

    it outputs :

    * html {
    font-size: 87.5%; }

    html {
    font-size: 14px;
    line-height: 1.71429em; }

    Instead of:

    html {
    font-size: 87.5%;
    line-height: 1.71429em; }


    • Zell Liew

      That is interesting, I’m wondering if its because I’m using the compass experimental version. I wasn’t able to reproduce that on my computer.

      When I did a double check with the compass reference, @include establish-baselinse outputs the code as you pasted because IE 6 had some problems rendering fonts set in percentages.

      I have a feeling It might switch to the one I posted if you set legacy support for ie 6 to be false, like so
      $legacy-support-for-ie6: false;

      However, this is not tested yet so I’m not sure. Let me know if this works for you?

  • Minh Phạm

    When i add margin with function rhythm(), It seems give us “rem” unit. Can we make it fallback with px unit? Or we should use “Polifiil” ??

    • Zell Liew

      It gives rem unit if you have set the rhythm unit to rem as mentioned above. If you leave that out however, you’ll get the em unit instead.

      I usually use polyfills for rem when I work with IE8. If you’re not comfortable with polyfills, then use the default em unit instead.

  • Nicolas Bouteille

    Looks like $rhythm-unit: “rem”; does not work yet on Compass 0.12.2 but $font-unit: 1rem; does work.

    Did you make a mistake here or did I miss something?

    Looks like $rhythm-unit: “rem”; is something coming in the next versions and that they will provide pixel fallback for IE8- no ?

    EDIT :

    I just tried to set $font-unit: 1rem; to use REMs on compass 0.12 but now the line-height set by adjust-font-size-to is in REM too so it is relative to the base font size.
    So I have my h1 3.375rem (54px) but line-height 1.3333rem of 16px so not big enough at all… Is it just Compass 0.12 simply not ready to use rems or me who does not do things properly ?

    EDIT : looks like $relative-font-sizing needs to be set to false to use REMs. I would have thought REMs would be considered relative too…

    • Zell Liew

      You’re right here. I missed out that you need to have the alpha version of Codekit installed to use the rem unit with vertical rhythms. You can install it with the –pre suffix and the article should work fine.

      Thanks for spotting!

  • Gonzalo2683

    How to use vertical rhythm and images?

    • Zell Liew

      Unfortunately, the vertical rhythms in compass only applies to text. What I usually do for images is that I ensure a margin of rhythm(1) below the image.

      Sometimes when its applicable, I regulate the height of the image with the height property as well.

      When its responsive and height of the image needs to change at every viewport, it gets a lot harder

  • Gunther

    Long story short – it is not possible to achieve an exact vertical rhythm with relative units. And if you want to respect the users (base) font settings, you certainly will have to use them.

    There are many reasons, why the plan is doomed to failure.
    One is that browsers actually use different methods of rounding. Another one is that the assumption of 16px as base font size is not always correct. As a matter of fact, when using relative units you do not have any idea of the actual (base) font size, as it depends on the respective browser and the user settings.

    And imho if you want to use ‘rem’ units (and I am quite sure you will), and you have a responsive layout, it makes a lot of sense to adjust your base font size for different viewport sizes (also in relative units like ‘em’). This should be done on the HTML element and_not_on the BODY element, which would counteract the sense of the ‘rem’ unit.

    To me “vertical rhythm” is as useful/ practical as “pixel-perfect design” in web design. It comes from the print design, and that is clearly where it belongs to. That does not mean that you should not layout all your headings, paragraphs, blockquotes etc. in a consistent and visually appealing manner. But don’t try to be “pixel-perfect” – any attempt will undoubtedly fail.

    And there are numerous other stumbling blocks which can cause you to trip and even fall when dealing with vertical rhythm.
    “Collapsing margins” is only one of them. And which way do you try to achieve your vertical rhythm? Padding-top and margin-bottom? And what if you want to put a border around the element (and want to have it vertically centered)?

    Also there are the relatively new “viewport units” like ‘vw’, ‘vh’ and so on. They come in handy, especially in responsive design, not only for “fluid” font sizes, but also for the width of (SVG) images, whose heights are set to ‘auto’. And again your fine “vertical rhythm” is gone, as you have no chance to ever know anything about the height of these elements (which would be essential for the alignment to a vertical rhythm).

    So please stop telling authors that they should/ could apply a “pixel-perfect vertical rhythm” to their sites, using relative units!

    The only way to do so, would be to only use absolute units like ‘px’ with a massive loss of accessibility.

    • Zell Liew

      Hey Gunther,

      Thanks for posting out all the problems with creating an exact vertical rhythm!

      Not much has been said about this problem at all, and I had went through the frustrations of everything you had said. So it really makes a ton of sense :)

      Vertical rhythms here uses relative units (I’m using rem here) and that it generally helps to create a pleasing rhythm.

      It isn’t my intention to tell authors to apply a “pixel-perfect vertical rhythm”. if you do spot that statement anywhere, please let me know where I said that, and I’ll remove it right away.

    • Pedr Browne

      Spent a lot of time working with vertical rhythm and I have to say I think you are spot-on. It is, like so many things in the world of CSS, something that sounds amazing but is actually ruined by browser discrepancies. The math at it’s core simply will not work the same across all browsers. Rounding errors compound and throw layouts off, necessitating endless tweaks. The sad truth is that vertical rhythm and relative units are incompatible.