Single-direction margin declarations

This morning I awoke to find Smashing Magazine had retweeted a tweet I made two months ago about how you should always try and apply margins in one direction only. This, like most rules in web development, is a very general (and breakable) rule. It’s even a rule you can opt not to follow at all, but after receiving a slew of Tweets asking why, I thought I’d write up why it’s a rule I live by, and one I’d recommend to anyone…

I’m not sure how I arrived at this rule, but I’m really glad I did and I would likely never ever change it. The basic premise is that you should try and define all your margins in one direction. This means always use margin-bottom to push items down the page, and margin-left to push them across the page. I’m going to focus mainly on margin-bottom throughout this article as it’s the most obvious to explain, but this can be applied to both directions (top/bottom, right/left).

The benefits are, as I see them:

Defining vertical rhythm

This next bit on its own is enough to convince me, this one tip is one of the most valuable ones I have, personally.

Whenever I start a new project I typically want to know two things; my base font-size and my base line-height. Let’s say that I choose a base font-size of 16px and a base line-height of 24px. This gives me (in proper units) this:

html{
    font:1em/1.5 "Comic Sans MS", cursive;
}

That 1.5 is my Magic Number. This is massively important; knowing this number allows me to set up my entire project’s vertical rhythm in one go:

h1,h2,h3,h4,h5,h6,hgroup,
ul,ol,dd,
p,figure,
pre,table,fieldset,hr{
    margin-bottom:1.5rem;
}

Bosh. Done. Now any block level element (I may have missed some) I add anywhere in that page will have a line-height of 24px (if my base font-size is 16px) and will be spaced apart by 24px (again, if my base font-size is 16px).

I can extend that list of selectors as and when I need to and all will remain in order:

h1,h2,h3,h4,h5,h6,hgroup,
ul,ol,dd,
p,figure,
pre,table,fieldset,hr,
.header,.media,.island{
    margin-bottom:1.5rem;
}

For me that is reason enough to stick to just defining my margins in one direction, I can just drop any element anywhere and it will obey the same vertical rhythm as any others.

Confidence in portability

So if I know that all my margins are consistently in the same direction then I can be a lot more confident that if I add, move or remove an element my spacing won’t mess up. This isn’t just about something as pretentious as vertical rhythm, this is about spacing in general. If everything is the same then it doesn’t really matter what is where, it all behaves similarly.

If I had some odd situation where I have a margin-top on element A, a margin-top and margin-bottom on element B and a margin-bottom on element C how can I be sure that removing B won’t break anything? I can’t, because I mixed up my margins!

Less to think about

So if you can be sure things are a lot less likely to break there’s one less thing to worry (as much) about.

One counter argument I got on Twitter today was that I didn’t ‘get’ collapsing margins. This kind of response really annoys (and offends) me. A similar one I get is ‘You just don’t understand specificity!’ whenever I advise against the use of IDs. It’s a developer’s understanding of a subject that allows them to know when to avoid or circumvent something.

Collapsing margins aren’t rocket science but they are one more caveat, one more thing to remember. Look at all that in the spec, all of that to have to consider just as a result of adjoining margins on elements. Don’t mix margin-top and margin-bottom and you won’t even need to think about that.

As a developer gets better they try to be less clever. I know where using IDs can be a pain so I save myself the hassle by not using them, same with collapsing margins; no one gets points for taking the more complex route. I honestly believe that if anything with caveats or potential ‘gotchas’ can be avoided they should be*.

I find I have never had any collapsed margin oddities in any of my projects because I avoid introducing the possibility.

Exceptions

By applying the margin-bottom to all block-level elements that means that most things you put into a page will carry that spacing. Let’s say for example you have a heading in a promotional box that you don’t wish to have a margin-bottom, simply override the rule as you would with any sensibly architected CSS:

h1,h2,h3,h4,h5,h6,hgroup,
...{
    margin-bottom:1.5rem;
}
...
.promo-title{
    padding-bottom:1.5rem;
    border-bottom:1px solid #ccc;
    margin-bottom:0;
}

Using more specific selectors you can undo or alter your spacings with ease.

In working at Sky, there were times when we wanted a larger break between one section and another, let’s say double (3rem) between a carousel and the content below it. Simple:

.carousel{
    ...
    margin-bottom:3rem;
    ...
}

Interestingly, what I actually did was create an abstract class of .landmark which carried that margin-bottom:3rem; to denote any content that was deemed a large, thematic break in the page (signified by larger spacing).

Other times we had a boxed-off bit of content for which I used the Island Object. Some CSS like this…

.island{
    padding:1.5rem;
    -webkit-border-radius:4px;
       -moz-border-radius:4px;
            border-radius:4px;
}

…would often lead to compounding margin-plus-padding issues, thus. The solution here was simply to remove the margin-bottom from the last element, like so.

Breaking the rule

Obviously there will come a time when this rule needs breaking; we can’t even try and kid ourselves—all web development rules get broken. However, before you do go against it, double and triple check that there isn’t a nicer solution. I really cannot remember the last time I broke this rule, but I’m sure I have and will need to in future. I just really, really try not to.

Final word

Everything I’ve written here is nigh on impossible to prove and isn’t quantifiable, but speaking anecdotally and from experience on some huge websites, the method I use works perfectly. More than perfectly. I genuinely cannot remember a time I have had problems with collapsing margins or spacing issues or anything arising from arbitrary margin declarations.

If you think this might be of use then I urge you to try it, it really has worked wonders on every site I’ve ever employed this on. Conversely, if I’ve missed a trick please do tell me!

If you don’t like the idea of it then that’s totally cool; I can’t prove anything and if you’re comfortable as you are then that’s great!

*From the guy who likes unquoted attributes in HTML… I know!

By Harry Roberts on Tuesday, June 12th, 2012 in Web Development. Tags: , , | 37 Comments »

+

37 Responses to ‘Single-direction margin declarations’


  1. James Young (@welcomebrand) said on 12 June, 2012 at 6:22 pm

    Good write up of the wider reasons Harry, although I’ve got to say I’m blown away it’s actually necessary to explain to some people!


  2. thecodezombie said on 12 June, 2012 at 6:28 pm

    I think I subconsciously picked this up from being so focussed on vertical rhythm over recent months. As you know, it largely surrounds “the down”, so having all margins in one direction (margin-bottom for me) just makes sense.

    As for left / right, I go with right…mainly because amongst the people I work with, catching the last element and removing the margin is more obvious. Consider a crude example, like a photo gallery of 9 images floated and stacked…3 to a row, 3 rows. Just more likely to catch the row end – 3, 6 & 9 – than the row start.

    To be honest, this might even be down to browser support…we still support IE7, so trying to use :nth-child causes a bit of a X-browser headache. We tend to count through items / recorda in PHP and apply an “end” class to remove the margin.

    So yeah, bottom and right for me.


  3. Martin Bavio said on 12 June, 2012 at 6:42 pm

    Wow, I’ve been doing the same for a couple of months, since I’ve adopted the concept of Vertical Rhythm. I’m glad I’m not the only one doing it!

    I have one question that doesn’t relate to the margin but I saw your code and you are using REM for spacing. I love the concept of REM and I would like to introduce it in my own projects, but I’m worried about browser support.

    Are you using REMs in production sites?

    Thank!


  4. Harry Roberts said on 12 June, 2012 at 6:52 pm

    @Martin Bavio: I use rem with a px fallback (on production sites) :)


  5. Martin Bavio said on 12 June, 2012 at 6:53 pm

    Great to know. I will be following your path! Thanks!


  6. Elyse said on 12 June, 2012 at 7:28 pm

    I have to say I was pretty skeptical when I saw this retweeted. Twitter really isn’t a good medium for this sort of thing. I did this exact same thing when I was building white label templates at my last job. They had to be flexible enough to cover a myriad of different features that you could turn on/off, as well as allow for styling on top of that, and browser compatible down to IE6. Bottom-only margins definitely saved a ton of browser bugs and time. So after reading, I’m realizing this is a totally valid theory, especially when applying to larger modules. Certainly doesn’t apply to everything though. Well written!

    Elyse


  7. CSSwizz said on 12 June, 2012 at 7:37 pm

    You talk some bollocks, 21 years old and you think you know the lot?

    I have underwear older than you, also they contain less crap than you do!


  8. Aurélien said on 12 June, 2012 at 7:44 pm

    what is rem ?


  9. jlemesur said on 12 June, 2012 at 7:49 pm

    Wow! CSSwizz. Why so angry? Are you upset because your old or have soiled underwear?


  10. Harry Roberts said on 12 June, 2012 at 7:49 pm

    @CSSwizz: Thank you for your constructive, anonymous feedback…

    @Aurélien: Mr Snook wrote probably the best article on rem http://snook.ca/archives/html_and_css/font-size-with-rem


  11. Dragos said on 12 June, 2012 at 7:54 pm

    Excellent article!
    I’ve been slicing for a long time and I came to the same conclusions over the time and these are the reasons why. While I have still a lot to learn I won’t give up this style for nothing. It’s the most efficient in the long term and once you are using it you won’t have to bother with many other problems that may occur with cross browser..

    Thanks for the article


  12. kimblim said on 12 June, 2012 at 7:56 pm

    I’ve been doing this for years – it’s just simpler!


  13. Dave Allen said on 12 June, 2012 at 8:02 pm

    Hi CSSwizz,

    Could you point us to examples of your work so we can learn from your experience and skills? Alway great to learn new things!

    I’m just a noobie here and it’s hard to keep up!

    Dave


  14. Scott said on 12 June, 2012 at 8:04 pm

    I’ve used this technique before, but regularly ran into problems when using nested block level elements, particularly when the outer element has a border/background.

    Here’s the kind of thing I mean – http://jsfiddle.net/2tHMR/1/ – because of the bottom margin there is large ugly space at the bottom of the element. Any neat solutions to that problem? I used :last-child in the example above but it doesn’t quite feel right (it’s not cross-browser compatible and might not be very efficient).


  15. graup said on 12 June, 2012 at 8:12 pm

    Good article, but the last paragraph is really the most important – everybody just do what is comfortable for them. After all, Harry just shares his point of view.

    I also apply this technique for most parts, but sometimes I do like the collapsing margins. If you understand them they can be useful, too.


  16. Keith said on 12 June, 2012 at 8:15 pm

    Great article, Harry. At my company, we’re trying to get our heads around standardizing CSS so that it’s more portable, DRY and can be passed to any front-end dev without complication. Your recommendations may lead us to a new methodology of design as well.

    I’m curious about how this might apply to elements which would otherwise require padding. For example, there may be a parent element which is designed so that all of its children must remain 20px from its inner boundaries – a that has a background color with child s. Would it be a better course of action to give the child elements outer (i.e. left and bottom) margins of the required amount, instead of giving the parent container 20px of padding? Or am I talking about an entirely separate issue?


  17. Harry Roberts said on 12 June, 2012 at 8:20 pm

    @Keith: The problem you are describing sounds like the problem I address with the jsFiddle here http://jsfiddle.net/csswizardry/5p8ts/ and here http://jsfiddle.net/csswizardry/5p8ts/1/ :)


  18. Keith said on 12 June, 2012 at 8:22 pm

    Ah! Brilliant! That makes so much sense. Thanks, Harry.


  19. Niels Matthijs said on 12 June, 2012 at 10:22 pm

    I’m probably one of the people that questioned this technique (and indirectly triggered this post).

    One important thing to say up front is that this technique is about vertical rhythm and doesn’t really work on horizontal spacing, unless you start mixing paddings and margins on different elements to create element spacing (or worse, use explicit widths), which isn’t a best practice in my book.

    I don’t really see the problem with collapsing margins though. Unless you’re abusing floats collapsing margins aren’t all that difficult and defining a vertical margin in two directions allows for more flexibility in spacing.

    For me, I’m going to stick with my preferred way of spacing:
    .parent > * {margin:1(r)em;} Equal spacing for everyone!


  20. Daniel Hug said on 13 June, 2012 at 5:27 am

    Great article Harry!

    But, why do you use margin-bottom, and not margin-top?

    Doesn’t margin-top make more sense?


  21. Peter F. said on 13 June, 2012 at 6:53 am

    Sorry for asking something a little off topic, I see you defined your vertical rythm using a 16px ( 1em ) font-size and a line-height of 1.5rem creating a 24px spacing, I use the same but I’m having trouble mantaining the pattern when I need font-sizes bigger for especial heading 60px or for sidenotes that maybe require 12px font-size, how can I mantain the rythm in these cases where the size of the font excedes the 24px and are not in multiples. Thanks.


  22. Harry Roberts said on 13 June, 2012 at 11:48 am

    @Peter F.: If your base line-height is 24px and your element’s font-size is 60px then set that elements line-height to a multiple of 24 that is larger than the font-size; in this case that would be 72px, or line-height:1.2;.


  23. codp said on 13 June, 2012 at 2:03 pm

    Harry, I have to ask, why are you using REM unit when there is considerable amount of older browsers that do not support REM unit?


  24. Paul d'Aoust said on 13 June, 2012 at 10:15 pm

    @Niels Matthijs: Floats (and abusing them) aren’t the only things that prevent well-behaved margin collapsing. Anything that creates a new flow context — floating, overflow: hidden, various clearfix techniques — will muck up your collapsing margins. Of course it all follows a set of rules, but it’s just a pain to try to remember those rules all the time. That, I think, is where this technique would come in handy.


  25. Peter F. said on 13 June, 2012 at 11:59 pm

    I see, so it really doesn’t matter the font-size as long as the line height is a multiple of the vertical rythm and is bigger than the font-size, is that correct? I just tested and it worked by the way, the rythm is maintained.

    Where I’m also having problems maintaning the rythm is on lists, I have a list on a home page where 24px “visually” looks way too cramped so I found myself increasing the line-height to the next multiple wich is 48px but now that way too much, and the “visually” ok number breaks the rythm, has this happened to you?
    Thank you for your time Harry.


  26. Phobia said on 14 June, 2012 at 4:18 pm

    Great write-up! To me this is the only way. It’s a surprise that its use is not more widespread. You still see things like normalize.css that does it the “painful way”.


  27. kikito said on 14 June, 2012 at 5:11 pm

    Hi harry,

    I liked the article, but I kindof see a flaw; Doesn’t the exception at the end pretty much nullify the advantages this method has over collapsed margins? You trade “not having to care about knowing the collapse rule” with “having to remember to remove the last margins on certain occasions”.

    Isn’t that “worse” than having to remember collapses?

    Oh, also, don’t pay attention to @CSSWiz. Success attracts douchebags.


  28. Sanik said on 21 June, 2012 at 11:56 am

    Great rule! I developed this myself a while ago but haven’t quite made it into a “RULE” :)


  29. SchoolDudeKeith said on 21 June, 2012 at 1:23 pm

    So clean, simple and smart. Had never seen this “rem” before.


  30. Paul Radzkov said on 21 June, 2012 at 2:50 pm

    Hi Harry,

    On my experiment with vertical rythm I’ve tried to use top-margins this way:

    p {margin-top:0;margin-bottom:0;}
    p + p {margin-top:18px;}

    h1 + h2,
    h2 + h3,

    h5 + h6,
    h1 + p,

    h6 + p {margin-top:18px;}

    …and other semantic combinations. Here is much more initial code but less breaking the rule situations. We don’t need to reset first- or last-child margins, and it works in IE7+.

    Unfortunatelly I didn’t use that in large projects yet, so I can’t say about efficiency.

    How did you find this approach?


  31. Ben Hayes said on 26 June, 2012 at 4:40 pm

    In your example above you set the line height without using any units. Doesn’t this prevent the line-height from inheriting down through all the elements on the page? Eric Meyer says in this article (http://meyerweb.com/eric/thoughts/2006/02/08/unitless-line-heights/) that setting line-height without units makes the line-height relate to the font size of each child element. But for a vertical rhythm surely that’s not what we want. So I would set the global line height with ems on the BODY…


  32. Leban Hyde said on 30 June, 2012 at 12:40 pm

    I’m a bit late to this party, but thought I would throw in my two cents…

    I am also using this technique by way of margin-bottom. We formalized it a t work, calling it “The Flow Down”. The idea is built on two ideas: 1.) The content naturally flows down the page 2.) Every element on the page, at some point, has a parent.

    You’ve already discussed most of this in this article, but for our team it is key to point out that the top space preceding a first-child element is deferred to the parent element containing/wrapping the first-child via padding(-top).

    You are correct that the margin-bottom of the last-child can be an issue, but I’ve learn to incorporate that into the overall aesthetic of the layout (I tend to embrace additional white space wherever I can).

    The vertical rhythm that is talked about here is really about establishing a baseline grid. Glad to see other web designers becoming aware of and utilizing this concept. Massimo Vignelli speaks about it in his book, the Vignelli Canon http://www.vignelli.com/canon.pdf

    Thanks for the affirmation of this concept. It always helps to have someone else’s research back my conclusions.

    Cheers!


  33. AOG said on 1 August, 2012 at 2:54 am

    Nice write-up, the only problem is, I think somebody has already mentioned, what about browsers that do not support :last-child? I often need to build content inside some box that has its own padding, and like you mentioned, it creates some margin-plus-padding issues. Any other solution to that problem?


  34. Scott Phelps said on 2 August, 2012 at 10:05 pm

    This is why using a CSS Preprocessor can be so amazing.

    Instead of having to remember that baseline, why not just make it a variable?

    Using LESS it would like this:

    @baselineHeight: 1.5em;

    Boom.

    Now every time you want to do something with this you add the variable instead.
    Using your example,

    html {
    font:1em/@baselineHeight “Comic Sans MS”, cursive;
    }

    Want to maintain that vertical rhythm, but need twice the baseline? You can even do math with the variable! Again, using your example:

    .carousel {

    margin-bottom:@baselineHeight*2;

    }

    It is now doubled.
    Amazing!


Leave a Reply

Respond to Single-direction margin declarations

Hi there, I am Harry Roberts. I am a 21 year old web developer from the UK. I Tweet and write about web standards, typography, best practices and everything in between. You should browse and search my archives and follow me on Twitter, 7,791 people do.

via Ad Packs