1

Today I read an article about CSS Typography and how to set up a simple baseline grid. I thought it could be fun to try so I set everything up, but apparently it's not looking as expected.

Here is the fullscreen fiddle: http://jsfiddle.net/j5Tav/embedded/result/
And with code: http://jsfiddle.net/j5Tav/

To visualize the baseline I use Baseliner as a bookmarklet. It displays a baseline using JavaScript.

As you can see from my SCSS code, I set the baseline to 21px at a font size of 14px:

/* Reset */
* { margin: 0; padding: 0; }

/* Variables */
$bodyFontSize: 14px;
$baseline: 21px; /* 1.5 for 14px */

body {
    font-size: $bodyFontSize;
    line-height: $baseline;
}

article {
    margin: 0 auto;
    width: 65%;
}

h1,
h2,
p {
     margin-bottom: $baseline;
}

h1 {
    font-size: $bodyFontSize * 2;
    line-height: $baseline * 2;
}

h2 {
    font-size: $bodyFontSize * 1.8;
     line-height: $baseline * 1.8;
}

Still, when you use Baseliner on the full screen fiddle and enter 21 into the bookmarklet, the baseline is totally off. Why? Did I calculate anything wrong?

Sven
  • 12,997
  • 27
  • 90
  • 148
  • 1
    Sounds like you've run into rounding inconsistencies (14px * 1.8 = 19.6px). Is there a particular reason you've chosen to specify a unit on each of your line-heights? (see: http://meyerweb.com/eric/thoughts/2006/02/08/unitless-line-heights/ and https://developer.mozilla.org/en-US/docs/CSS/line-height) – cimmanon Jan 22 '13 at 16:46
  • @cimmanon No, there is no specific reason. Normally I do it like your links suggest - without unit. But having a variable like $baseline: 21; seemed ultra strange for me. Normally I use rem with a px fallback for text size, but somehow jsfiddle can't handle that. Do you have an idea how to avoid these kind of problems? I'm still having difficulties wrapping my head around the baseline concept - at the moment I am ending with rem-values for the height of a div. – Sven Jan 22 '13 at 17:16
  • It seems to like you're trying to use a single variable when it would be more appropriate to have 2: `$multiplier: 1.5` (for line-height) and `$baseline: $font-size * $line-height` (for padding and the like). – cimmanon Jan 22 '13 at 17:55

3 Answers3

3

Take a look at the "The Ugly" section of this article:

http://coding.smashingmagazine.com/2012/12/17/css-baseline-the-good-the-bad-and-the-ugly/

In short, applying the same line-height to all your elements will not ensure that the text within those elements will be aligned to the baseline grid that you have in mind. This is because, in CSS, text is set to the vertical center of the line-height value.

For example, if you have one paragraph with 6-pixel text and another paragraph with 24-pixel text and they both have the same line-height value (for example, 30 pixels), the text of those paragraphs will not be aligned to the same baseline.

To achieve a uniform baseline grid in CSS, you have to vertically offset each text element that has a different font-size. You can do this by adding padding to the bottom and top of each element in which the text does not happen to align to your chosen line height. A tool like Baseliner by John Keyes can be helpful in knowing where the 'true' baseline is:

http://keyes.ie/things/baseliner/

You want to make sure that the top and bottom padding add up to your line height value; for example, if you have to add 5 pixels of top padding of the h1 element so that it aligns with your desired baseline grid of 10 pixels, then you have to add 5 pixels to the bottom padding in order for the total height of the h1 element (including padding) to equal a multiple of 10 pixels (assuming that it's line-height has been set to a multiple a 10 pixels, e.g., 10 pixels, 20 pixels, etc.). You could also use margins for this purpose, but this could get messy due to collapsing margins. Furthermore, you want to avoid having a line-height smaller than a font-size, and you want to avoid combining two different font sizes in one element as this may also throw off the baseline grid. As the cited article notes, creating a true CSS baseline grid is rather messy, at least if you do it manually.

Gerry
  • 628
  • 6
  • 16
1

Setting up vertical rhythm manually is a pain.

You have tagged your question with scss, so why not use its awesomeness? Have a look at Compass's Vertical Rhythm!

Andrey Mikhaylov - lolmaus
  • 23,107
  • 6
  • 84
  • 133
  • 1
    Compass seems abandoned as of now - no updates for last 1.5 yrs. Also the algorithm does not really set correct baseline distances for differently sized fonts. Here is a better algorithm: https://gist.github.com/razwan/10662500 – Dmitri Zaitsev May 05 '16 at 08:28
0

I think most baselining/vertical rhythm methods out there are hard to use because you need to know your font's metrics. I have come up with a slightly easier method to employ. It uses HTML + CSS + Utility font. You don't need to know your font metrics and can even mix + match fonts.

Here's an example with your init setup

/* Reset */

* {
  margin: 0;
  padding: 0;
}

:root {
  --baseline: 21px;
}


/* 1. Include a baselined font */

@font-face {
  font-family: "Baseline Em";
  src: url("https://rawgit.com/shalanah/baseline/98e925b/BaselineEm/baselineem-webfont.woff2") format("woff2"), url("https://rawgit.com/shalanah/baseline/98e925b/BaselineEm/baselineem-webfont.woff") format("woff"), url("https://rawgit.com/shalanah/baseline/98e925b/BaselineEm/baselineem-webfont.ttf") format("truetype");
  font-weight: normal;
  font-style: normal;
}

/* Show grid lines */

body {
  padding: calc(var(--baseline) * 2px) 100px 100px;
  /* mult of grid */
  background-repeat: repeat-y;
  background-size: 100% var(--baseline);
  background-image: linear-gradient( to bottom, #0ff 0, rgba(255, 255, 255, 0)1px);
}

article {
  margin: 0 auto;
  width: 65%;
  margin-bottom: var(--baseline);
}

/* 2. Setting block elements up */
h1,
h2,
p {
  font-family: "Baseline Em"; /* Baselined font only needed at block level */
  line-height: 1em;
}

/* 3. Making sure only block leading is considered */
span {
  line-height: 0;
}

/* 4. Set leadings + margins */
h1 {
  font-size: calc(var(--baseline) * 2); /* Your leading: Mult of baseline */
  margin-bottom: var(--baseline); /* Mult of baseline */
}
h2 {
  font-size: calc(var(--baseline) * 2);
  margin-bottom: var(--baseline);
}
p {
  font-size: calc(var(--baseline) * 1);
  margin-bottom: var(--baseline);
}

/* 5. Set fonts + font-size */
h1 span {
  font-family: Arial; /* Whatever you want */
  font-size: calc(var(--baseline) * 2); /* Your font-size: Whatever you want */
}
h2 span {
  font-family: "Comic Sans MS", cursive, sans-serif;
  font-size: calc(var(--baseline) * 1.8);
}
p span {
  font-family: Verdana;
  font-size: 14px;
}
<article>
  <h1><span>Heading 1</span></h1>
  <h2><span>Heading 2</span></h2>
  <p><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec pulvinar eleifend nisi. Aliquam ultrices laoreet ligula vel elementum. Etiam eu faucibus nisi, vel suscipit nisl.</span></p>
</article>
<article>
  <h1><span>Heading 1</span></h1>
  <h2><span>Heading 2</span></h2>
  <p><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec pulvinar eleifend nisi. Aliquam ultrices laoreet ligula vel elementum. Etiam eu faucibus nisi, vel suscipit nisl.</span></p>
</article>
Shalanah
  • 135
  • 2
  • 7