Flex Items Create Space Between Them When They Wrap

Flex items create space between them when they wrap

When you create a flex container, an initial setting is align-content: stretch.

This causes multiple lines of flex items to distribute themselves evenly along the cross axis of the container. It's kind of like setting flex: 1 along the main axis: the flex items spread evenly across the line.

As a result, align-content: stretch may cause gaps when flex items wrap.

The simple solution is to override this setting with align-content: flex-start.

revised fiddle

html,body {  width: 100%;  height: 100%;}#container {  display: flex;  height: 100%;  background-color: blue;}.block {  flex: 1;}#left {  background-color: green;}#center {  display: flex;  flex: 1;  flex-wrap: wrap;  align-content: flex-start; /* NEW */}#right {  background-color: orange;}.flexContainer {  flex: 1;  width: 50%;  min-width: 100px;  max-width: 50%;  height: 150px;  background-color: red;  padding: 10px;}.flexDiv {  width: 100%;  height: 100%;  background-color: yellow;}
<div id="container">  <div id="left" class="block">Left</div>  <div id="center" class="block">    <div class="flexContainer">      <div class="flexDiv"></div>    </div>    <div class="flexContainer">      <div class="flexDiv"></div>    </div>  </div>  <div id="right" class="block">Right</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 property gap 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>

Unwanted space between wrapping flex-items

The correct answer without adding extra markup, is align-content: flex-start; - default is stretch, that's why wrapping elements have extra space between them, when the flex-container's size exceeds the size of the elements in it.

Giving wrapped flexbox items vertical spacing

If you force wrapping by applying a width you can then use margins as you normally would without setting a height.

.flexContainer {  display: flex;  align-items: center;  flex-wrap: wrap;  justify-content: center;  background: pink;  width: 150px;}.flexContainer > * {  margin: 1em 0;}.flexContainer .flexLabel {  flex-basis: 150px;  flex-shrink: 0;}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<div class="container"> <div class="col-sm-12"> <h1>Flexbox Wrapping</h1>
<div class="flexContainer">
<div class="flexLabel">This is a flex label</div>
<a class="btn btn-primary">Button 1</a> <a class="btn btn-warning">Button 2</a> <a class="btn btn-success">Button 3</a> </div>
</div></div>

Flexbox space between behavior combined with wrap

It's pretty annoying, but you can't use flexbox for that.

The better way is to go with CSS grid instead, and apply

/* for space-around style */
.fixed-grid--around{
grid-template-columns: repeat(auto-fill, minmax(150px,1fr));
justify-items: center;
}
/* for space-between style*/
.fixed-grid--between{
grid-template-columns: repeat(auto-fit, 150px);
justify-content: space-between;
}
/* both should run fixed width elements equal to the declared in the container */
.grid-element{
width: 150px;
}

By setting the grid columns minimum width to their elements width and the max column width to 1 fr we can get them to evenly distribute the space around them. For space-between style, autofit and space-between does the trick.

So it adds columns to fill the container, evenly distributes the space between them until another column can be added, and wraps as needed. Just what we always hoped for flexbox to do.

A pen I made before exploring the issue:

https://codepen.io/facundocorradini/pen/XVMLEq

If you're gonna use this, make sure to add some fallback for browsers that don't support grid. might be floats, inline-blocks, flex, or whatever. CSS Grid is really good at overriding the fallbacks, so it's fairly easy to apply.

Adding space between flexbox items

There a few things you have to consider.

First of all; with justify-content you define how remaining space is handled. By using space-between your items will be aligned so that the space between them is equal, by setting it to center the remaining space will be around all items, with all items stuck together.

In your case though, there is no remaining space, because your items actually stretch the div. So that doesn't help you.

Next; you've set the width of an item to 50%. Which is fine, your item's will be 50% of the viewport. That's because your grid will implicitly be 100% of the viewport. But because your image overflows the box, you can set margins if you want, and they will put the items further apart, but you need big-ass margins to actually see them. Bigger then the overflowing of your image.

So, to fix this, you make the images responsive by making them as width as the item;

.item img { display: block; height: auto; width: 100%; }

But that poses another problem; flexbox tries to size it's flex items to fit it all into the flex container. So you'll see that it automatically resizes your items so they will all fit in. To fix this, you have to explicitly force the width of your items;

.item { flex: 0 0 50%; }

Which is a shorthand for;

.item { flex-grow: 0; flex-shrink: 0; flex-basis: 50%; }

So basically you say; make my item 50% of it's container, and don't use your awesome algorithm to try to make it bigger or smaller.

Now you've got what you want, and you can use margin-right: 20px for example to create a 20px space between your items.

Full snippet;

.grid { display: flex; width: 100%; }
.item { flex: 0 0 50%; margin-right: 20px; }.item img { display: block; height: auto; width: 100%; }
.article-scroll-mobile { box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); flex-wrap: nowrap; text-align: center; overflow-x: auto; -webkit-overflow-scrolling: touch; /*For iOS smooth scroll effect*/}
<div class="grid article-scroll-mobile">  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div>  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div>  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div>  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div>  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div>  <div class="item">    <img src="https://www.w3schools.com/howto/img_fjords.jpg">  </div></div>

Creating a space between flex items in nested flexbox

Set Width of nav-links or use column-gap

        .navbar-container {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
.nav-links {
width: 300px;
// column-gap: 30px;
display: flex;
justify-content: space-between;
}
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>

</head>

<body>

<div class="navbar-container">
<a href="index.html">
<div class="logo">
<img src="./media/logo.svg" alt=" logo" height="80px" width="80">
</div>
</a>
<ul class="nav-links">
<li class="nav-link">
<a href="#">Install</a>
</li>
<li class="nav-link">
<a href="#">Learn</a>
</li>
<li class="nav-link">
<a href="#">item</a>
</li>
<li class="nav-link">
<a href="#">item</a>
</li>

<li class="nav-link">
<a href="#">item</a>
</li>

</ul>
</div>
</body>

</html>

How to display wrapping flex items as space-between with last row aligned left?

After trying the suggestions here (thanks!) and searching the web long and wide, I've reached the conclusion that this is simply not possible with flexbox. Any by that I mean that others have reached this conclusion while I stubbornly tried to make it work anyway, until finally giving up and accepting the wisdom of wiser people.

There are a couple of links I came across that might explain it better, or different aspects of the requirements, so I'm posting them here for... posterity.

How to keep wrapped flex-items the same width as the elements on the previous row?

http://fourkitchens.com/blog/article/responsive-multi-column-lists-flexbox

Remove space (gaps) between multiple lines of flex items when they wrap

An initial setting of a flex container is align-content: stretch.

This means that multiple lines of flex items will be distributed evenly along the cross axis.

To override this behavior, apply align-content: flex-start to the container.


When you're working in a single-line flex container (i.e., flex-wrap: nowrap), the properties to use to distribute space along the cross axis are align-items and align-self.

When you're working in a multi-line flex container (i.e., flex-wrap: wrap) – like in the question – the property to use to distribute flex lines (rows / columns) along the cross axis is align-content.

From the spec:

8.3. Cross-axis Alignment: the align-items and align-self properties

align-items sets the default alignment for all of the flex container’s items, including anonymous flex items. align-self allows this default alignment to be overridden for individual flex items.

8.4. Packing Flex Lines: the align-content
property

The align-content property aligns a flex container’s lines within the
flex container when there is extra space in the cross-axis, similar to
how justify-content aligns individual items within the main-axis.
Note, this property has no effect on a single-line flex container.

The align-content property takes six values:

  • flex-start
  • flex-end
  • center
  • space-between
  • space-around
  • stretch

Here's the definition for stretch:

stretch

Lines stretch to take up the remaining space. If the leftover free-space is negative, this value is identical to flex-start. Otherwise, the free-space is split equally between all of the lines, increasing their cross size.

In other words, align-content: stretch on the cross axis is similar to flex: 1 on the main axis.



Related Topics



Leave a reply



Submit