140

I have a flex container with two flex items. I want to set a margin-top on the second one, but only when it's wrapped and not at the first flex line.

If possible, I want to avoid using media queries.

I thought margin-bottom on the first element could be a solution. However, it adds space at the bottom when the elements are not wrapped, so same problem.

This is my code:

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
}
.item-big {
  background: blue;
  width: 300px;
}
.item-small {
  background: red;
  margin-top: 30px;
}
<div class="container">
  <div class="item-big">
    FIRST BIG ELEM
  </div>
  <div class="item-small">
    SECOND SMALL ELEM
  </div>
</div>
Oriol
  • 274,082
  • 63
  • 437
  • 513
Manuel Di Iorio
  • 3,631
  • 5
  • 29
  • 31
  • 2
    Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it **in the question itself. Please don't abuse the code blocks to get around this requirement**. – Paulie_D Jun 17 '15 at 11:12
  • The problem is that in this case I didn't need to explain with more code, so it's a problem of StackOverflow if a block code is required. – Manuel Di Iorio Jun 17 '15 at 12:06
  • 2
    The issue is the usefulness for **future** users of SO. If your JSfiddle link went away then your post is essentially useless. That's why SO asks for code....ideally in the code snippets available to you when you create the question. – Paulie_D Jun 17 '15 at 12:12
  • Ok, I understood, I'm editing the question to comply the rules ;) – Manuel Di Iorio Jun 17 '15 at 12:19

2 Answers2

261

You can add some margin-top to both flex items, and a negative margin-top of the same amount to the flex container.

This way, the negative margin of the flex container will neutralize the margin of the flex items at the first line, but not the margin of the items that wrapped to other lines.

.container {
  margin-top: -30px;
}
.item-big, .item-small {
  margin-top: 30px;
}

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
  margin-top: -30px;
}
.item-big, .item-small {
  margin-top: 30px;
  background: red;
}
.item-big {
  background: blue;
  width: 300px;
}
<div class="container">
   <div class="item-big">
      FIRST BIG ELEM
   </div>
   <div class="item-small">
      SECOND SMALL ELEM
   </div>
</div>

Nowadays there is overall support (MDN) for the css (row-)gap property in flex layout containers which this answer proposes. The way to go .

Youp Bernoulli
  • 5,303
  • 5
  • 39
  • 59
Oriol
  • 274,082
  • 63
  • 437
  • 513
21

If your browser supports the CSS gap property you can use it like this

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
  gap: 20px;
}

gap adds an extra space surrounding the flex-child items. If you want to add some extra space only at the top and bottom, use row-gap instead.

For browsers that not supports the gap property you can use the lobotomized owl selector which selects every element which has an adjacent item right before it, this means it won't select the first one.

.container > * + * {
  margin-top: 20px;
}

If you want to add this margin using * + * operator only if the elements are stacked on top of each other, you should wrap it in @media.

The third solution with :not() and :first-child CSS pseudo-class

.container:not(:first-child) {
  margin-top: 20px;
}
Volker E.
  • 5,911
  • 11
  • 47
  • 64
Mikolaj
  • 1,231
  • 1
  • 16
  • 34
  • Good feature, but still poorly supported in Safari (only latest versions will work). So if you want to support a-bit-older browsers then prefer to use mix of negative/positive margins to create gaps. – koloml Nov 10 '21 at 10:40
  • Also second solution for older browsers will not help: second column is counted as second element and top margin will be added. – koloml Nov 10 '21 at 10:42