Css margin-top vs margin-bottom

Viewed 11946

If you have a sequence of block elements and you wanted to place margin in between them.

Which do you prefer, margin-top or margin-bottom or both? Why?

8 Answers

Depends on context. But, generally margin-top is better because you can use :first-child to remove it. Like so:

div.block {
    margin-top: 10px;
}

div.block:first-child {
    margin-top: 0;
}

This way, the margins are only in between the blocks.

Only works for more modern browsers, obviously.

I always use margin-bottom, which means there is no unnecessary space before the first element.

The most voted answer in here is a bit outdated, in the sense that it says that the advantage of going margin-top is that you can then use :first-child (but as of 2018, you could use margin-bottom in combination with :last-child with equal support).

However, the reason to prefer margin-top with :first-child (instad of margin-bottom with :last-child) is explained in detail in this article CSS: margin top vs bottom.

Basically, it says that if you have a block between other similar blocks and you want to have this block's margins (top and bottom) different than the rest, you would get into more trouble because there is no easy way to select proceeding elements, but with the adjacent sibling selector (+) it is possible to achieve this without the need of helping classes:

enter image description here

Using the margin-top with :first-child structure, the CSS required to give proper spacing to the Ad is:

article {
    margin-top: 2em;
}

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

//space at the top of the Ad
.ad {
    margin-top: 1em;
}

//and to reduce space below the ad
.ad + article {
    margin-top: 1em;
}

@This Mat - I disagree with your approach. I would assign spacing on elements in a semantic fashion, and use contextual selectors to define behavior for that collection of elements.

.content p { /* obviously choose a more elegant name */
   margin-bottom: 10px;
}

Naming classes after their behavior instead of their content is kind of a slippery slope, and muddies up the semantic nature of your HTML. For example, what if in one area of your page, all elements with class .top10 suddenly needed 20 pixels instead? Instead of changing a single rule, you would have to create a new class name, and change it on all the elements you wanted to affect.

To answer the original question, it depends entirely on how you want elements to stack. Do you want extra space at the top or the bottom?

I don't quite understand why some of you guys are saying that margin-bottom is more logic than margin-top.

Just to makes sure you all people know: Page is rendered from top to bottom.

Let consider a simple problem

<div class="box">
   <div class="item first"></div>
   <div class="item second"></div>
   <div class="item third"></div>
</div>

The elements inside the box should have their distance between them.

A very generic solutions

.item:nth-child(n+2) {
    margin-top: 16px;
}

or you could use

.item + .item {
    margin-top: 16px;
}

As you can see there is only 1 rule needed. It will work only when more than 1 elements is present, which is kinda thing you expect if for example for some reason "first" & "second" does not exist you don't want to have the extra space from the top cause the space from the top is handled by "box" element padding.

And if for some reason one or more of the elements should have different spacing that the others you just do this:

.item + .item {
    margin-top: 16px;
}

.item + .item.second {
    margin-top: 32px;
   // you could use margin-bottom here but there will be needed a different rule for handling if there is no 3rd element
}

.item.second + .item {
    margin-top: 32px;
}

I find 1 problem here, if you inject an element into the list that does not contain the class "item", but why would you do that?

Considering margin-bottom I tried to find some solutions but I don't see any solution where you are not in need to write multiple rules.

.item {
    margin-bottom: 16px;
}

.item:last-child {
   margin-bottom: 0px;
}

Don't get me wrong, margin bottom is needed in some cases, but I find it rarely that it should be used.

In my experience margin-bottom is always like a needle in the foot.

I find in general that elements should have as less relations as possible between them and between the page & that they should be reusable as much as possible.

Ofc making your life simpler is a thing you decide to do or not.

Having 1 rule to maintain, instead of multiple ones is a better thing, won't you agree?

Less css code = better performance -> faster download

Yeah I usually use margin-bottom as well and then assign a last class to the last one in the bunch. Assuming you want a different styling on this.

.discussion .detailed.topics { margin: 20px 0 }    
.discussion .detailed.topics .topic { margin-bottom: 30px }
.discussion .detailed.topics .topic.last { margin-bottom: 0 }

This is a strong approach when your using dynamically driven content

HTML (Razor View Engine)

<div class="detailed topics">   
   @if (Model.ActiveTopics != null && Model.ActiveTopics.Count > 0)
   {
      for (int i = 0; i < Model.ActiveTopics.Count(); i++)
      {
          var topic = Model.ActiveTopics[i];
          <div class="topic@(i == Model.ActiveTopics.Count - 1 ? " last" : "")">
                ...                                 
          </div>
      }
   }
</div>
Related