When you write CSS, chances are good you constantly struggle with spacing. If you never had a situation where you needed to open up the inspector to find the origin of vertical spacing, this article is not for you.
To avoid this struggle, I found that one very simple rule works surprisingly well for me:
Use margin-top
only.
I’ve been following this rule now for more than three years and in many different projects, and it proves to be just helpful.
You need to decide which element gets vertical spacing?
Add margin-top
to the lower element.
You want to increase/decrease some vertical spacing?
Change the margin-top
of the lower element.
Here are some best practices and exceptions I came along:
The next/subsequent sibling combinator
Sometimes you want to define spacing below an element. For example a heading that needs some space between itself and the next element, whatever it is. In this case you can use the next-sibling combinator
.element + * {
margin-top: 1rem
}
/* Instead of: */
.element {
margin-bottom: 1rem
}
If you have multiple inline-block elements below each other by the help of line break elements you can use the subsequent-sibling combinator:
.inlineBlockElement
<br>
.inlineBlockElement
<br>
.inlineBlockElement
.inlineBlockElement ~ .inlineBlockElement {
margin-top: 1rem
}
/* Or if you don’t know the next elements class */
.inlineBlockElement ~ *:not(br) {
margin-top: 1rem
}
Horizontal spacing
This rule is meant for vertical spacing, but you can apply it to horizontal spacing as well: Use margin-left
when possible.
But be careful with inline-block elements that may break into the next row. In this case using margin-right
is better as the spacing on the right is not visible.
Exception: content added with :before
There is no rule without exceptions, here is one I stumbled upon.
Let’s say you have an icon above a paragraph of text and this icon is a :before pseudo element. As the content after :before
cannot be targeted using CSS you need to use margin-bottom
.
<div>
:before
This is some content you can not easily give margin-top.
</div>
Why not margin-bottom
?
Actually, this was my first approach but I switched to margin-top
for several reasons.
1. Less code navigation
Most of the time I append new elements when writing markup. When doing so my scope is this newly added element. And thus setting margin-top
for this element is easier than eg. navigating to the previous elements css to set its margin-bottom
.
2. The next/subsequent sibling combinator
As there is no previous-sibling selector in CSS3, you can not easily say "Hey, if there is something before me it should have margin-bottom"
3. It looks better and is shorter to write
Sure, this is not reason #1, but who wants to write "bottom" all the time?
.element {
margin: 1rem 0 0;
}
.element {
margin-top: 1rem;
}
/* VS */
.element {
margin: 0 0 1rem;
}
.element {
margin-bottom: 1rem;
}
No headaches
This rule should make your life easier, not harder. Avoiding margin-bottom
is simple most of the time, but if you encounter a situation where this is not the case, don’t take it too serious.
And of course, if there are other guidelines for a project they should always have a higher priority.
Thanks for reading, how do you cope with spacing? Do you have a similar rule? Let me know!
Top comments (5)
I use the exact opposite guideline for years in large (modular) projets, which is using
margin-bottom/right
and IMHO is way better,Your examples of CSS for
margin-top
shouldn't be used, as it can cause a lot of issues in maintenance among others (eg: performance/speed),Also your point #3 I really can't see the difference from you top VS bottom.
About the headaches, no headaches at all, just a matter on how to do things properly
I did use
margin-bottom
for some time and it has most of the advantages. Especially #1 (less code navigation) was what convinced me to switch.You mean
~ *:not(br)
right? You can also go with+ br + *
which is easier to understand.Of course, with
margin-bottom
you don’t need the+
cominator, but you will have a harder time if you have various preceding elements that need different spacing.What are the advantages of
margin-bottom
that conviced you? Let me know!I mostly use
gap
for spacing (flex or grid), but if needed, I tend to usemargin-block-end
, and then just remove it from:last-of-type
.For margin-left/right u need to remove it for the :first/last-child and use float, which is the old way. Much better is with flex
Yes, especially now that
gap
for Flexbox is finally supported in all major browsers. Sometimes I use inline-block for simple cases to save a container element. I don’t use float for this.