5 Items Per Row, Auto-Resize Items in Flexbox

5 items per row, auto-resize items in flexbox

You are right in giving a flex-basis: 20% but you have to adjust for the 4px margin on each flex item for it to wrap properly.


Equal Width Flex items in the last row

Use flex: 0 1 calc(20% - 8px) - this means the item won't grow beyond 20% of width (adjusting for margin) and can shrink based on the container width. See demo below:

.container {
background: gray;
width: 600px;
height: 200px; /* height given for illustration */
display: flex;
flex-flow: row wrap;
position: relative;
}

.item {
background: blue;
margin: 4px;
flex: 0 1 calc(20% - 8px); /* <-- adjusting for margin */
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>

Flexbox: 4 items per row

You've got flex-wrap: wrap on the container. That's good, because it overrides the default value, which is nowrap (source). This is the reason items don't wrap to form a grid in some cases.

In this case, the main problem is flex-grow: 1 on the flex items.

The flex-grow property doesn't actually size flex items. Its task is to distribute free space in the container (source). So no matter how small the screen size, each item will receive a proportional part of the free space on the line.

More specifically, there are eight flex items in your container. With flex-grow: 1, each one receives 1/8 of the free space on the line. Since there's no content in your items, they can shrink to zero width and will never wrap.

The solution is to define a width on the items. Try this:

.parent {  display: flex;  flex-wrap: wrap;}
.child { flex: 1 0 21%; /* explanation below */ margin: 5px; height: 100px; background-color: blue;}
<div class="parent">  <div class="child"></div>  <div class="child"></div>  <div class="child"></div>  <div class="child"></div>  <div class="child"></div>  <div class="child"></div>  <div class="child"></div>  <div class="child"></div></div>

How to change the number of flex items per row with image links?

Added the following css to your code:

.images-container img {
width: 100%;
}

.images-container>a {
flex: calc(100% / 3);
}

You can adjust the number of images per row by changing the flex property in .images-container>a.

Here is the working snippet with newly added css.

* {  box-sizing: border-box;}
.container { display: flex; flex-direction: column; margin: 0 auto; padding: 10px;}
input[type="search"] { height: 40px; width: 80%; margin: 30px auto; border: 1px red solid;}
.images-container { display: flex; justify-content: space-evenly; flex-wrap: wrap; border: 1px red solid;}
a { flex: 25%; border: 1px red solid;}
.images-container img { width: 100%;}
.images-container>a { flex: calc(100% / 3);}
<div class=container>
<div class="images-container"> <a href="https://picsum.photos/id/1/150/150" data-lightbox="image-1"><img src="https://picsum.photos/id/1/150/150" alt="Image 1"></a> <a href="https://picsum.photos/id/2/150/150" data-lightbox="image-2"><img src="https://picsum.photos/id/2/150/150" alt="Image 2"></a> <a href="https://picsum.photos/id/3/150/150" data-lightbox="image-3"><img src="https://picsum.photos/id/3/150/150" alt="Image 3"></a> <a href="https://picsum.photos/id/4/150/150" data-lightbox="image-4"><img src="https://picsum.photos/id/4/150/150" alt="Image 4"></a> <a href="https://picsum.photos/id/5/150/150" data-lightbox="image-5"><img src="https://picsum.photos/id/5/150/150" alt="Image 5"></a> <a href="https://picsum.photos/id/6/150/150" data-lightbox="image-6"><img src="https://picsum.photos/id/6/150/150" alt="Image 6"></a> <a href="https://picsum.photos/id/7/150/150" data-lightbox="image-7"><img src="https://picsum.photos/id/7/150/150" alt="Image 7"></a> <a href="https://picsum.photos/id/8/150/150" data-lightbox="image-8"><img src="https://picsum.photos/id/8/150/150" alt="Image 8"></a> <a href="https://picsum.photos/id/9/150/150" data-lightbox="image-9"><img src="https://picsum.photos/id/9/150/150" alt="Image 9"></a> <a href="https://picsum.photos/id/10/150/150" data-lightbox="image-10"><img src="https://picsum.photos/id/10/150/150" alt="Image 10"></a> <a href="https://picsum.photos/id/11/150/150" data-lightbox="image-11"><img src="https://picsum.photos/id/12/150/150" alt="Image 11"></a> <a href="https://picsum.photos/id/12/150/150" data-lightbox="image-12"><img src="https://picsum.photos/id/12/150/150" alt="Image 12"></a> </div>
</div>

How to display 3 items per row in flexbox?

Flex container:

  • You probably want to use display: flex not inline-flex.
  • Add flex-wrap: wrap to allow wrapping onto multiple lines.
  • Remove width: 33% if you wish it to take entire space avaiable.

For 3 items per row, add on the flex items:

  • flex-basis: 33.333333%
  • You can also use the flex's shorthand like the following: flex: 0 0 33.333333% => which also means flex-basis: 33.333333%.

.serv ul {  display: flex;  flex-wrap: wrap;  padding-left: 0;}
.serv ul li { list-style: none; flex: 0 0 33.333333%;}
<div class="serv">  <ul>    <li>1</li>    <li>2</li>    <li>3</li>    <li>4</li>    <li>5</li>    <li>6</li>  </ul></div>

Control item count in a row with flexbox

You only need to consider one rule like below:

 /*7 = 4 (1st row) + 3 (2nd row) and 5 = 1st element in 2nd row (4 + 1)*/
.grid-wrapper .grid-item:nth-child(7n + 5) {
width: calc(100%/3);
flex-grow:0;
}

The trick is to make one element bigger to trigger the wrap then rely on flex-grow to fill the space.

Full code

* {  box-sizing: border-box;}
.grid-wrapper { display: flex; flex-wrap: wrap; justify-content: center;}
.grid-wrapper .grid-item { width: 25%; text-align: center; padding: 5px; flex-grow: 1;}
.grid-wrapper .grid-item:nth-child(7n + 5) { width: calc(100%/3); flex-grow:0;}
p { background: #ddd; padding: 15px;}
<div class="grid-wrapper">  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div>  <div class="grid-item">    <p>Grid Item</p>  </div><div class="grid-item">    <p>Grid Item</p>  </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>

Arrange 2 items per row using flexbox

You can give flex: 50% to children divs without touching .item