Ultimate Guide to non-working CSS margins
Sometimes you’re styling some HTML elements with CSS and there seems to be a margin between the elements that you never defined. This article covers most cases why css margins are not working the way you expect them to be.
Whitespaces between inline-blocks
If you put two inline-block
elements next to each other in your HTML code, you need to make sure that there are no whitespaces between the closing and opening tags.
Otherwise, as the elements are inline
, they act like normal text elements where you would also expect to have a “margin” between your elements where a whitespace occurs.
The fix is to remove the spaces/newlines such that the opening and closing tags are immediately next to each other:
<span id="one"></span><span id="two"></span>
If you want to keep some formatting structure, you can use comments to remove the whitespaces:
<span id="one"></span><!--
--><span id="two"></span>
Inline Element Vertical Alignment
Whenever you have an inline
element which is followed by a block
element (or any element rendered in a new line), there will be a vertical space between these two.
This effect is most noticeable for inline-images, like <svg>
elements which are inline
by default.
This has to do with where in the current line the element is positioned.
If not specified otherwise, inline
elements are vertically aligned to the parent’s baseline
.
The fix is to vertically lower the element lower with for instance:
svg {
vertical-align: middle;
}
Collapsing Margins of Block Elements
The third way you can see margins between elements that you never defined has to do with something called Collapsing Margins:
Top and bottom margins of blocks are sometimes combined (collapsed) into a single margin whose size is the largest of the margins combined into it, a behavior known as margin collapsing.
The idea is that if you have several paragraphs and some other elements before or after them, and you want to have exactly 20px
of margin between them,
you can just define both margin-top: 20px;
and margin-bot: 20px;
.
This way, there will always be a space of 20px
between a paragraph and any element, even between adjacent paragraphs,
because the top
and bot
margin between them collapses into a single one of 20px
.
Unfortunately, this behavior is often more of an annoyance you have to work around instead of something useful.
Besides collapsing margins between two adjacent elements, there are two other cases how collapsing margins can occur, but the most common one is between a parent and its first child:
For example, you want to wrap a heading into a div
while leaving some space between the div's
upper border and the heading by defining a margin-top: 20px
on the heading.
However, instead of the h2
moving down, the whole div moves down by 20px
instead:
This happens because the div
has no border, and no padding defined, and the CSS specification states to
collapse the two top margins into a single one of the parent.
(The same happens with bottom margins.)
There are several ways to circumvent margin collapsing:
- Set a border or a (fake) padding on
div
:div { padding: 0.1px; }
- Use padding instead of margin to adjust the child:
h2 { padding-top: 20px; }
- Collapsing margins only happens with block elements, so you can define
div
to be aninline-block
to prevent it:div { display: inline-block; }
- Defining a different
overflow
value also disables it:div { overflow: auto; }
- Position your
div
absolute:div { position: absolute; }
These are the main issues why a space may appear somewhere you didn’t expect, but once you aware of how inline
elements are positioned and that collapsing margins exists,
they are usually easy to fix.