Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flex-box ignores wrapped children's margin (margin collapse)

Tags:

css

flexbox

Given the following HTML:

<div class="outer">
  <div>
    <div class="inner">A</div>
  </div>
</div>
<div class="outer">
  <div class="inner">B</div>
</div>

and the following CSS (prefix free):

.outer {
  display: box;
  box-orient: vertical;

  height: 100px;
  width: 100px;

  background: red;
  margin: 10px;
}

.inner {
  height:     50px;
  margin-top: 10px;
  background: green;
}

A and B

Here is a CodePen.

A is wrapped in a <div> so it's margin gets ignored.

Q: How can I achieve B's behavior for A (margin) with the flex box model?

Note: The div wrappers can go multiple levels deep

Targeting: latest Chrome/Safari/iOS

Thank you very much for your help!

Edit: Thanks to @JoséCabo I came up with this:

.outer {
  display: flex;
  flex-direction: column;

  height: 100px;
  width: 100px;

  background: red;
  margin: 10px;
}

.inner {
  height:     50px;
  margin-top: 10px;
  background: green;
}

CodePen

Chrome: Chrome

Safari: Safari

Unfortunately it doesn't work in Safari as mentioned by @cimmanon, so I still need some help.

like image 210
Stephan Bönnemann-Walenta Avatar asked Feb 24 '13 22:02

Stephan Bönnemann-Walenta


People also ask

Does flexbox collapse margins?

Margin collapsing is a feature of a block formatting context. There is no margin collapsing in a flex formatting context. A flex container establishes a new flex formatting context for its contents. This is the same as establishing a block formatting context, except that flex layout is used instead of block layout.

Why is margin not collapsing?

Margins of elements do not collapse when the value of the overflow property of the elements is set to anything other than visible. Its value must be visible so that margin can collapse.

How do you remove margins from flex wrap?

So what you would do is use grid-gap for spacing between the items. Then use padding for the same spacing between the items and the container. The last row margin problem is eliminated.

How do I fix the collapse margin in CSS?

How to Avoid Margin Collapse. First, remember that margins should preferably be used to increase the distance between sibling elements, not to create spacing between a child and a parent. If you need to increase space within the Flow layout, reach first for padding if possible.


2 Answers

What you're looking at actually has nothing to do with Flexbox, but what's called margin collapse

.outer div {
  border: 1px solid;
}

The addition of the border has prevented the margin from collapsing. Rather than relying on margins, I would recommend placing a padding on the parent container:

.outer {
  padding-top: 10px;
}

Example:

.wrapper {
  background: #eef;
  border: 1px solid darkgray;
}

.container {
  display: flex;
  flex-wrap: wrap;
  margin: -1em;
}
  
.item {
  flex-grow: 1;
  margin: 1em;
  border: 1px solid black;
  padding: 1em;
  min-width: 6em;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <div class="wrapper">
  <div class='container'>
    <div class='item'>item</div>
    <div class='item'>item</div>
    <div class='item'>item</div>   
    <div class='item'>item</div>
    <div class='item'>item</div>
    <div class='item'>item</div>    
  </div>
  </div>
</body>
</html>

Now, to cover all of your prefixes, you need something like this:

.outer {
  display: -moz-box;
  display: -webkit-flexbox;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -moz-box-orient: vertical;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
  height: 100px;
  width: 100px;
  background: red;
  margin: 10px;
}
like image 51
cimmanon Avatar answered Sep 30 '22 19:09

cimmanon


Finally I came up with the right solution (for my specific problem).

.outer {
  display: flex;
  flex-direction: column;

  height: 100px;
  width: 100px;

  background: red;
  margin: 10px;
}

.inner {
  height: 50px;
  margin-top: 10px;
  background: green;
  display: inline-block;
  width: 100%;
}

CodePen

I'm using display: inline-block on .inner to disable margin collapsing and then compensate for the lost width with width: 100%.

All the credit goes to cimmanon for pointing me in the right "margin collapse" direction

like image 20
Stephan Bönnemann-Walenta Avatar answered Sep 30 '22 19:09

Stephan Bönnemann-Walenta