CSS: margin top vs bottom (a layout trick you should know)

CSS: margin top vs bottom

CSS can be surprisingly difficult.

Learning little tricks can sometimes make all the difference to the quality and efficiency of your stylesheets.

And that's where todays question comes in.

"When vertically spacing block elements on a webpage should you separate items with top margin or bottom margin?"

This question is encountered by all front-end web developers at some point in their career.

And the answer is not obvious, even to many seasoned professionals.

It seems trivial but understanding the difference between top and bottom margin in this situation can be a game-changer.

The correct solution holds the key to smaller stylesheets, flexible layouts, and more modular CSS. It's worth getting right.

So let's start with the answer:

Always use top margin.

The reason is related to the 'C' in CSS.

In this article I'll show you why top margin is better and I'll reveal a deeper CSS principle behind the solution.

I'm sure you'll find it valuable.

But before you can add this principle to your bag of CSS tricks I need to explain how it works.

We'll do this by examining two layouts.

The first layout is simple, the second contains an additional element that complicates the design in a particular way.

These demos will illustrate the pros and cons of the top and bottom margin methods and it will become clear why top is always best.

Let's get started.

A basic vertical block layout

Vertical blocks layout 4 blocks2em space

This is our first test layout. It's a simple design of four vertical blocks with 2em spacing between each block.

Here's the HTML markup we'll be using:

<main>
    <article></article>
    <article></article>
    <article></article>
    <article></article>
</main>

Let's see how each method achieves this design.

Bottom margin vertical spacing

We only need two simple rules to make our layout work using bottom margins.

The first rule is margin bottom on each article element:

article {
    margin-bottom: 2em;
}

And the second rule removes bottom margin from the last article, just to keep things tidy. We can do this with the last-child selector.

article:last-child {
    margin-bottom: 0;
}

So far so good.

Top margin vertical spacing

Our top margin solution is exactly the same, only opposite:

article {
    margin-top: 2em;
}
article:first-child {
    margin-top: 0;
}

Both methods get the job done but what happens when we introduce a complication to the layout?

This is where things start getting interesting.

Introducing an element between blocks

Vertical blocks layout with an ad 4 blocks1em spaceAd

Let's place an ad between two blocks to make some advertising dollars. The designers have asked for less space above and below the ad.

Our updated HTML markup is as follows:

<main>
    <article></article>
    <article></article>
    <div class="ad"></div>
    <article></article>
    <article></article>
</main>

Do both methods still work?

Bottom margin spacing

Let's start by adding the smaller bottom margin to our ad:

.ad {
    margin-bottom: 1em;
}

This takes care of the space below the ad, but what about the space above?

To make a smaller space above the ad, we must somehow override the bottom margin on the proceeding article.

But that's impossible!

There's no way to select proceeding elements in CSS without adding some kind of hook like a class. But adding a class requires either server-side logic or javascript, and both of these options are messy.

FAIL!

Can top margin do any better?

Top margin spacing

Similar to before, let's add the smaller top margin to the ad like this:

.ad {
    margin-top: 1em;
}

Now what about bottom spacing?

To reduce space below the ad we must override the top margin on the article immediately following the ad.

This is something we can do!

We can use the adjacent sibling selector to target the first article after the ad, here's how you can do that:

.ad + article {
    margin-top: 1em;
}

You can think of the plus (+) as meaning 'followed immediately by'.

Easy!

Because the space between elements is defined as part of the element after the space we can change this CSS rule depending on the proceeding element.

In other words: we can override styles that follow particular elements.

This is the power of Cascading Style Sheets (CSS).

It's the cascade that makes top margin work while bottom margin fails.

Towards a more general purpose CSS rule

Cascading styles are at the heart of this solution.

The process works by styling an element based on it's context, and because CSS only cascades in a forward direction, only proceeding elements are parts of any element's context.

But element order is not a visual thing.

One element only proceeds another based on it's HTML source order, it does not matter if it's rendering position is actually 'above' or 'below'.

This is where our general purpose CSS principle comes to light.

If a style can be applied to one of many elements, always use the last possible element in the HTML source to allow overriding by context. Click to Tweet

Following this rule leads to many CSS benefits.

It encourages us to think about layouts in a more modular way and how these modules work with one another.

Our stylesheets become smaller and more manageable because we can more effectively work on one piece at a time.

And our website layouts to become more flexible and expressive because they are constructed by intelligent building blocks.

Here's an alternative way to think about this that may be a bit more intuitive:

Set default styles for webpage modules then override rules depending on proceeding context. Click to Tweet

Now we understand this more general purpose CSS rule we can apply it in new ways.

Of course we're not limited to margins and vertical blocks.

We can work horizontally, vertically, and hierarchically.

And we can override any style rules we please.

Conclusion

Sometimes the simplest things in CSS can reveal deeper lessons.

By delaying style rules to the last possible element I've shown how CSS can be written more efficiently and used in a modular way.

I hope this little trick serves you well.

Happy coding. =)

Published: 30 Apr 2018