Margin vs Gap

Margins and gaps are very similar properties. They both add space between elements. But then why do we have two such similar properties? In this article, we will explore the differences between margins and gaps, and by the end, you will be in a position to decide when to use which property.

Margin

The purpose of margin is to add some space around an element. The margin is applied to the element itself that needs the spacing.

Consider the following example:

html

<div class="fruits">
  <div class="apple">Apple</div>
  <div class="banana">Banana</div>
  <div class="cherry">Cherry</div>
</div>

We can add margin to the .apple div to add some space around it.

css

.apple {
  margin: 1rem;
}

In the case of inline elements, the margin will only be applied horizontally. The browser will ignore the vertical margin though it will show it in the computed styles.

html

<div class="fruits">
  <span class="apple">Apple</span>
  <div class="banana">Banana</div>
  <div class="cherry">Cherry</div>
</div>

One unusual property of margin is that the margin between elements collapse. When it is applied to two adjacent elements, the greater margin will be used. It's like the margin of one element collides with the other elements margin.

css

.apple {
  margin: 1rem;
}

.banana {
  margin: 2rem;
}

Gaps

Gaps also add space between elements. But they are applied to the parent container. Also, the gap property is only applicable for multi-column, flex and grid containers.

css

.fruits {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

You can still apply margin to the child elements. But the gap will be applied in addition to the margin.

css

.fruits {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.apple {
  margin: 1rem;
}

One important property of gap is that if the container has pseudo elements, the gap will be applied to the pseudo elements as well. This is in most cases not desired.

css

.fruits::before, .fruits::after {
  content: "";
}

Ok so, which is better?

In general, margins are much more powerful than gaps. Let me explain why.

You can achieve behaviour of gaps using margins using sibling selector.

css

.fruits * + * {
  margin-top: 1rem;
}

This is same as using gap but with one benefit, It does not target the pseudo elements.

Another benefit of using margins is that you can select child elements as per your need. For example, if you want to add spacing only if the child element is not empty, You can do that using margins but it is not possible using gap.

html

<div class="fruits">
  <div class="apple">Apple</div>
  <div class="banana">Banana</div>
  <div></div>
  <div class="cherry">Cherry</div>
</div>

css

.fruits * + *:not(:empty) {
  margin-top: 1rem;
}

But in case of gaps, the spacing will still be applied to the empty elements 😓.

You can do all sorts of things using margins that you cannot do using gaps. You can target specific child elements and apply margins to them as per your need. But with gaps, the spacing is applied uniformly to all child elements. There is no way to target specific child elements and alter spacing to them.

Fun fact: Tailwind CSS's space-x and space-y classes are based on margins.

Conclusion

In conclusion, I would say margins are more powerful than gaps. You can do whatever gaps can do with more control and flexibility. The downside is that the syntax is a bit more complex as you will need to use sibling selectors and it looks weird as start. Gaps are more intuitive to use and understand.

So, which one to use?

Well, it depends on the use case. If you need the spacing to be applied uniformly to all child elements, use gaps. If you need more control and flexibility, use margins.

If you feel I missed out on something or you have any suggestions, feel free to reach out to me on Twitter @pawankumar2901.