Margin collapsing in flexbox
Margin collapsing is a feature of a block formatting context.
There is no margin collapsing in a flex formatting context.
3. Flex Containers: the
flex
andinline-flex
display
valuesA 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. For example,
floats do not intrude into the flex container, and the flex
container’s margins do not collapse with the margins of its contents.
flexbox margin collapsing between children
Margins does not collapse when one use display: flex
. If you want to know more about collapse margins in general, here is a couple of articles to start with:
- https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
- https://css-tricks.com/what-you-should-know-about-collapsing-margins/
As a workaround, to make it behave similar to display: block
, you could do something like this, where you add a flex
class to container
's that has display: flex
, to target only h1
and p
.
And if you can't do that manually, a script could do that work for you.
.wrapper { width: 50%; margin: 0 auto;}.container { display: flex; /* display: block; */ flex-flow: column nowrap; background-color: green;}h1 { background-color: #777; margin-bottom: 20px;}p { background-color: #ccc; margin-top: 15px;}
/* custom classes to remove margin */.container.flex h1:first-child { margin-top: 0;}.container.flex p:last-child { margin: 0;}
<div class="wrapper"> <div class="container flex"> <h1>header h1</h1> <p>plain text</p> </div></div>
Collapsing margin on Flexbox children
It's a bit of a hack, but you can add a negative margin on the flex container to cancel out the items' margins along the edges, and then move its "background" styling to a parent wrapper-element.
Updated JSBin
Updated CSS (SASS):
.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
Why are margins not collapsing?
Flex items' margins won't collapse. When flex items wrap, they create their own row, and the individual margins on the flex items won't collapse between rows. Only normal, adjacent block elements stacked will margin collapse the way you're intending. This is a good reference - https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
You can create the same layout by removing the top margin from the li
's and making that a padding-top
on the ul
instead, then only the bottom margin will be applied between li
's when the flex row wraps.
ul { list-style-type: none; padding-left: 0px;}
a { text-decoration: none;}
main { background-color: #F1F4F5; padding: 30px 0px;}
.main-wrapper { max-width: 800px; margin: auto;}
.tags ul { display: flex; justify-content: center; align-items: center; flex-wrap: wrap; margin: 0; padding-top: 20px;}.tags li { margin: 0 10px 20px; display: block;}.tags a { display: block; justify-content: center; color: #3A4250; background-color: #e6e6e6; border-radius: 20px; padding: 7px 20px; transition: background-color 0.3s ease, color 0.3s ease;}.tags a:hover { color: #FFFFFF; background-color: #FC575E; transition: background-color 0.3s ease, color 0.3s ease;}
<main> <div class="main-wrapper"> <div class="tags"> <ul> <li> <a href="#">ELEMENT 1</a> </li> <li> <a href="#">ELEMENT 2</a> </li> <li> <a href="#">ELEMENT 3</a> </li> <li> <a href="#">ELEMENT 4</a> </li> <li> <a href="#">ELEMENT 5</a> </li> </ul> </div> </div></main>
Collapsing margin on Flexbox grid in Edge and Firefox
Margin using percent doesn't work cross browsers on flex items, so if your margin's is more related to the viewport, use viewport units (vh
or vw
), else you can combine px
with CSS calc()
(i.e. width: calc(33.333% - 20px)
) to match an equal gutter between the items.
Updated codepen
body { padding: 1.5%; background-color: #333;}
.container { //background-color: black; max-width: 964px; margin: 0 auto; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-box-flex-flow: row wrap; -moz-box-flex-flow: row wrap; -webkit-flex-flow: row wrap; -ms-flex-flow: row wrap; flex-flow: row wrap;}
.item { position: relative; width: 97%; color: #fff; background-color: #4286f4; padding: 0 20px 40px; margin: 1.5vh; box-sizing: border-box;}
@media only screen and (min-width:420px){ .item { width: 47%; }}
@media only screen and (min-width:768px){ .item { width: 30.333%; }}
a { position: absolute; bottom: 20px; left: 20px;}
<div class="container"> <div class="item item-1"> <h2>Item one</h2> <p>Pellentesque convallis turpis nec enim consequat, vitae pellentesque purus tempus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis blandit elit vel lacus gravida, nec imperdiet ligula ornare.</p> <a href="#">Read more</a> </div> <div class="item item-2"> <h2>Item two</h2> <p>Pellentesque convallis turpis nec enim consequat, vitae pellentesque purus tempus.</p> <a href="#">Read more</a> </div> <div class="item item-3"> <h2>Item three</h2> <p>Pellentesque convallis turpis nec enim consequat, vitae pellentesque purus tempus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae.</p> <a href="#">Read more</a> </div> <div class="item item-4"> <h2>Item four</h2> <p>Pellentesque convallis turpis nec enim consequat.</p> <a href="#">Read more</a> </div> <div class="item item-5"> <h2>Item five</h2> <p>Pellentesque convallis turpis nec enim consequat.</p> <a href="#">Read more</a> </div> <div class="item item-6"> <h2>Item six</h2> <p>Pellentesque convallis turpis nec enim consequat.</p> <a href="#">Read more</a> </div></div>
Better way to set distance between flexbox items
- Flexbox doesn't have collapsing margins.
- Flexbox doesn't have anything akin to
border-spacing
for tables (edit: CSS propertygap
fulfills this role in newer browsers, Can I use)
Therefore achieving what you are asking for is a bit more difficult.
In my experience, the "cleanest" way that doesn't use :first-child
/:last-child
and works without any modification on flex-wrap:wrap
is to set padding:5px
on the container and margin:5px
on the children. That will produce a 10px
gap between each child and between each child and their parent.
Demo
.upper {
margin: 30px;
display: flex;
flex-direction: row;
width: 300px;
height: 80px;
border: 1px red solid;
padding: 5px; /* this */
}
.upper > div {
flex: 1 1 auto;
border: 1px red solid;
text-align: center;
margin: 5px; /* and that, will result in a 10px gap */
}
.upper.mc /* multicol test */ {
flex-direction: column;
flex-wrap: wrap;
width: 200px;
height: 200px;
}
<div class="upper">
<div>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa<br/>aaa</div>
<div>aaa<br/>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa</div>
</div>
<div class="upper mc">
<div>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa<br/>aaa</div>
<div>aaa<br/>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa</div>
</div>
Related Topics
Why Doesn't This A:Visited CSS Style Work
Css Text-Decoration Property Cannot Be Overridden by Child Element
Text Blended Over Background Color
What Is the Best CSS Framework and Are They Worth the Effort
How to Automatically Crop and Center an Image
How to Change the Height of an Image in CSS :Before/:After Pseudo-Elements
What Is Difference Between Justify-Self, Justify-Items and Justify-Content in CSS Grid
How to Change the Bootstrap 4 Navbar Button Icon Color
Why Is @Font-Face Throwing a 404 Error on Woff Files
What Do "Flex" and "Justify-Content" Achieve That "Text-Align" Doesn'T
Does Element Width Include Padding
Match All Elements Having Class Name Starting With a Specific String
Set Flexbox Children to Have Different Heights to Use Up Available Space