How to Set Maximum Number of Rows in a Flexbox Container and Hide Extra Element

How to set maximum number of rows in a flexbox container and hide extra element?

Use CSS grid for this:

.container {
display: grid;
grid-template-columns:repeat(auto-fit,100px); /* the width is define here */
grid-template-rows:auto auto; /* 2 rows */
grid-auto-rows:0px; /* next rows equal to 0 */
overflow:hidden; /* hide the overflow */
width: 50%;
max-width: 800px;
margin: 0 auto;
outline: 1px dashed blue;
padding: 5px;
}

div.item {
box-shadow: 0 0 0 1px inset black; /* use a shadow instead of border to not increase the height */
}
<div class="container">
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</div>
<div class="item">a</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 make flex box with limit 2 elements per row?

.container {
display: flex;
flex-wrap: wrap;
}

.inner {
flex-basis: 50%;
flex-grow: 1;
}

.inner:nth-of-type(1) {
background: red;
}

.inner:nth-of-type(2) {
background: gold;
}

.inner:nth-of-type(3) {
background: green;
}

.inner:nth-of-type(4) {
background: blue;
}
<div class="container">
<div class="inner">one</div>
<div class="inner">two</div>
<div class="inner">three</div>
<div class="inner">four</div>
</div>

Does anyone know how I can set a limit to the rows that flexbox can wrap?

I'm not sure this is achievable with flexbox. I'd highly recommend doing this in grid for much better layout control.

Explanation

flexbox is for one dimensional layouts, while grid is for two dimensional layouts.
Yes, flex-wrap will make multiple rows, but you can't control the layout as you want to. The problem with flex-wrap in this scenario is that when applied, it won't cause any overflow, as flex-wrap is used to wrap the items to prevent overflow.

The solution

Since you specified the size with width: 250px I'm going to assume you always want 2 rows.
By applying grid-auto-flow: column, the layout will continuously make a new column for each item.

With grid-template-rows: 1fr 1fr, there will always be 2 rows in the layout.

With grid-auto-columns: 20%, each item will be a column taking up 20% of the width of 250px, which is 50px (which is, from what I understand, your preferred size as you specificed flex-basis: 20%).

By applying overflow-x: auto, there will be a horizontal scrollbar from the content overflowing from the 250px container.

.wrap-here {
display: grid;
gap: 5px;
grid-auto-flow: column;
grid-template-rows: 1fr 1fr;
grid-auto-columns: 20%;
width: 250px;
overflow-x: auto;
}

.item {
border: 1px solid black;
padding: 10px;
margin-bottom: 5px;
}
<div class="wrap-here">
<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 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>

Limit the number of column in a row with flexbox

Like the comments already mentioned you would need to remove the max-width from your images and change up your width a little bit to account for your margins.

If you still want to limit your boxes to 180px i would recomment to instead limit the parent element to 3 * (box-width + margins) = 600px like this:

#acccommodation-city {
flex-grow: 2;
background-color: #F2F2F2;
border: 1px solid #F2F2F2;
border-radius: 10px;
padding: 16px 0px px 16px;
margin-right: 16px;
margin-left: 16px;
}

#accommodation-nav {
display: flex;
flex-flow: row wrap;
max-width:600px;
}

#accommodation-nav>div {
flex-basis: calc(33% - 20px);
}

.accommodation-item {
background-color: white;
border-radius: 10px;
box-shadow: 10px 5px 5px #E0DDDD;
margin-right: 10px;
margin-left: 10px;
margin-bottom: 10px;
width: min-content;
cursor: pointer;
}

.accommodation-item:hover,
.popular-item:hover {
background-color: #DEEBFF;
}

.accommodation-picture {
border: 3px solid white;
border-radius: 10px 10px 0px 0px;
box-sizing: border-box;
width: 180px;
height: 100px;
object-fit: cover;
}
<link rel="stylesheet" href="https://fonts.googleapis.com/           
css?family=Raleway">
<script src="https://kit.fontawesome.com/
1f544e41e8.js" crossorigin="anonymous"></script>

<div id="acccommodation-city">
<h3 class="title">Accommodations in Marseille</h3>
<div id="accommodation-nav">
<div class="accommodation-item">
<img class="accommodation-picture" src="https://i.stack.imgur.com/tbRiY.jpg">
<h5>Auberge la Cannebière</h5>
<p>Night starting at <strong>25€</strong></p>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #dfdddd;" class="fa-solid fa-star fa-2xs"></i>
</div>
<div class="accommodation-item">
<img class="accommodation-picture" src="https://i.stack.imgur.com/nJ3Bf.jpg">
<h5>Hôtel du port</h5>
<p>Night starting at <strong>25€</strong></p>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
</div>
<div class="accommodation-item">
<img class="accommodation-picture" src="https://i.stack.imgur.com/FAKLO.jpg">
<h5>Les mouettes Hotel</h5>
<p>Night starting at <strong>76€</strong></p>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #dfdddd;" class="fa-solid fa-star fa-2xs"></i>
</div>
<div class="accommodation-item">
<img class="accommodation-picture" src="https://i.stack.imgur.com/Qo6xt.jpg">
<h5>Hôtel de la mer</h5>
<p>Night starting at <strong>46€</strong></p>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #dfdddd;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #dfdddd;" class="fa-solid fa-star fa-2xs"></i>
</div>
<div class="accommodation-item">
<img class="accommodation-picture" src="https://i.stack.imgur.com/L9riT.jpg">
<h5>Auberge Le Panier</h5>
<p>Night starting at <strong>23€</strong></p>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #dfdddd;" class="fa-solid fa-star fa-2xs"></i>
</div>
<div class="accommodation-item">
<img class="accommodation-picture" src="https://i.stack.imgur.com/eYuCX.jpg">
<h5>Hôtel chez Amina</h5>
<p>Night starting at <strong>96€</strong></p>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
<i style="color: #0065FC;" class="fa-solid fa-star fa-2xs"></i>
</div>
</div>
<h5 style="cursor: pointer;">Show more</h5>
</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>

Fill the remaining height or width in a flex container

Use the flex-grow property to make a flex item consume free space on the main axis.

This property will expand the item as much as possible, adjusting the length to dynamic environments, such as screen re-sizing or the addition / removal of other items.

A common example is flex-grow: 1 or, using the shorthand property, flex: 1.

Hence, instead of width: 96% on your div, use flex: 1.


You wrote:

So at the moment, it's set to 96% which looks OK until you really squash the screen - then the right hand div gets a bit starved of the space it needs.

The squashing of the fixed-width div is related to another flex property: flex-shrink

By default, flex items are set to flex-shrink: 1 which enables them to shrink in order to prevent overflow of the container.

To disable this feature use flex-shrink: 0.

For more details see The flex-shrink factor section in the answer here:

  • What are the differences between flex-basis and width?

Learn more about flex alignment along the main axis here:

  • In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?

Learn more about flex alignment along the cross axis here:

  • How does flex-wrap work with align-self, align-items and align-content?

Create a row of flexbox items with a max height defined by one child

Flexbox can't do that natively but it is possible.

You will need an inner element inside the second child which is positioned absolutely.

Here the extra content is/can be hidden with overflow:hidden...or revealed by adding overflow:auto.

.wrapper {  display: flex;  width: 80%;  margin: 1em auto;  border: 2px solid red;}.child {  flex: 1;  border: 2px solid green;}.child:nth-child(2) {  position: relative;  overflow: auto;  /*overflow: hidden; */ /* removed for demo purposes */}.inner {  position: absolute;  top: 0;  left: 0;  width: 100%;  height: 100%;}
<div class="wrapper">  <div class="child">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis tenetur, laboriosam! Ab facilis, officia id delectus eaque expedita quia, incidunt eligendi aut, minus temporibus tenetur.</div>  <div class="child">    <div class="inner">      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae molestiae, libero inventore nobis et veritatis, laborum vitae, vel eaque omnis ad adipisci quia velit blanditiis qui. Cum voluptas quisquam itaque possimus accusamus repellendus quia iure      asperiores. Unde, rerum nihil maiores nisi, iusto voluptate id cumque incidunt, perspiciatis facilis perferendis explicabo.    </div>  </div></div>

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>


Related Topics



Leave a reply



Submit