Minding the gaps

Several people in the Drupal Gardens forums have asked how they can eliminate the vertical gaps between major sections of their themes.  Here's an illustration of these gaps.

To get rid of these gaps, look for top margin and top padding, usually on the elements with very distinct and descriptive ID's.  For example, the banner.

In the example above, the top padding of the #banner element is set to 27px.

And the navigation.

In the example above, the top margin of the #navigation element is set to 36px.

And the content, where both top margin and top padding are set.

In the example above, the top margin of the #content-inner element is set to 18px and the top padding is set to 18px, yielding a combined gap of 36px.

All of these values can be adjusted in the Theme Builder as noted in the three examples above.

Vertical Rhythm

These vertical gaps between major sections in our themes (those sections classed with the .stack class) are calculated to create a constant vertical rhythm.

Vertical rhythm is a critical component of a theme's balance.  Good vertical rhythm makes your content appear more readable and generally more pleasing. 

All Drupal Gardens themes are configured to a body text size of 13px and a line height of 18px. This means that every line of text consumes 18px of vertical height, illustrated below.

Zooming in on this example, note the content height (13px) and the half-leading above and below the content. In our case because the leading is an odd number of 5px (18 - 13 = 5), the browsers will distribute the half-leading as 2px above the content and 3px below. With an even leading value, the half-leading is distributed in equal amounts above and below the content.

Getting back to the gaps, in order to maintain a vertical rhythm, the spaces between content should also be some multiple of 18px, the same as the body content line height.  This isn't exactly a hard-fast rule, though. I actually prefer to break the 18px line height down into 3px units in order to have more flexibility.  All of the my vertical spaces are some multiple of three.

So in the Drupal Gardens themes, the ideal vertical gapping distance is 18px or 36px, but when these spaces are too short or tall, you may find 27px (or 24px or 21px or 30px, etc).

By basing all spacing units on multiples of three, vertical harmony emerges because the tops and bottoms of elements will tend to align more frequently.

Now that the why of the vertical spacing and units is clear, let's look at the how.  The simplest way to space elements on a page is to put margin/padding on the bottom of an element like this:

I dislike this method for two reasons:

  1. We are left with 18px of margin at the bottom of the set of the elements. If the wrapping container has padding, we end up with what appears to be extra, or worse variable, space at the bottom of the wrapping container. It becomes difficult to make this extra space consistently sized throughout a template. Here's an illustration.

And two:

  1. When an element pushes content down the page, it makes an assumption about the semantics of what's below it.  What do I mean by this?  Well, lets say we have a paragraph followed by another paragraph; this second paragraph is followed by an h2 element.

When margin/padding is set on the bottom of elements, the only way to vary the vertical space in a way that acknowledges the semantics of an element (in this case an h2 element that we would like to push a little farther down the page), we need to now add top margin to the h2. But adding just a little top margin to an h2 assumes that the bottom margin of the element it follows will always be the same.  Making little adjustments like this inevitably ends in uncontrollable vertical spacing and ever-more specific styles to control vertical spacing - in essence, a CSS mess.

To solve this, I put margin/padding at the top of elements to control the vertical spacing of elements on the page.  Yes, the top.  Why?  Well.

  1. Top margin/padding allows an element to push itself down the page. This means that the element can control its distance from the preceding element.
  2. In CSS, an element can know what precedes it, but it cannot know what follows it.
  3. We eliminate the bottom-gapping in containers.
    1. How do we prevent top-gapping you ask?  Check out my description of the adjacent sibling and preceding sibling combinators.
  4. And finally, the :first-child pseudo selector is supported by IE7, but the :last-child is not.  So we can target the first element of a set of siblings in the modern browsers, but not the last.

With top margin, we can vary the vertical spacing between elements with respect to their semantics (their meaning).

In the example above, the h2 element pushes itself 27px down from any element that precedes it.  In this way we get a constant amount of space above h2's.

We also eliminate the bottom gapping in a containing element.  

Note that the bottom of the container above is flush with the bottom of the last element.

Yes, we do create a problem of top gapping, but because IE7 and above support :first-child, we can remove the top margin/padding from a set of sibling elements inside a container.

.stack .box *:first-child {
  margin-top: 0;

Or you can use the adjacent sibling selector technique I've described before.

.stack .box * + * {
  margin-top: 18px;

Start your own site for free at Drupal Gardens.