My problem is that I want the flexbox with variable range width, and all works well, but not on the last row. I want the same dimension for all children even where the row is not full of children (the last row).
#products-list {
position:relative;
display: flex;
flex-flow: row wrap;
width:100%;
}
#products-list .product {
min-width:150px;
max-width:250px;
margin:10px 10px 20px 10px;
flex:1;
}
I created a dynamic situation in jsFiddle
My flex divs can shrink until 150px and grow up to 250px, but all must be with the same size (and obviously I want a CSS solution, with JS I know the way).
Unfortunately, in the current iteration of flexbox (Level 1), there is no clean way to solve the last-row alignment problem. It's a common problem.
It would be useful to have a flex property along the lines of:
last-row
last-column
only-child-in-a-row
alone-in-a-column
This problem does appear to be a high priority for Flexbox Level 2:
Although this behavior is difficult to achieve in flexbox, it's simple and easy in CSS Grid Layout :
In case Grid is not an option, here's a list of similar questions containing various flexbox hacks:
As a quick and dirty solution one can use:
.my-flex-child:last-child/*.product:last-child*/ {
flex-grow: 100;/*Or any number big enough*/
}
There is a great solution that works always. add a div with class product (The same class for other items that are under flex) and add a style for this div:height:0px; you need to add as many dives that are possible to be in one row.
<div class="product" style="height:0px">
as many that can be in one row. That's all. Works always.
I was having a similar challenge with menu rows. I wanted more spacing on the top of the second row of menu items.
The use of flex-box's row-gap worked well.
https://developer.mozilla.org/en-US/docs/Web/CSS/row-gap
.menu {
display: flex;
flex-wrap: wrap;
row-gap: 10px;
}
This added a margin-top type effect to menu items were wrapped to the second line.
You could try using grid instead of flexbox here:
#products-list {
display: grid;
grid-gap: 5px;
grid-template-columns: repeat(auto-fit, minmax(100px, 250px)); //grid automagic
justify-content: start; //start left
}
I used this workaround, even if it's not very elegant and it doesn't use the power of Flexbox.
It can be carried out on the following conditions:
If this is the case, you can use the following snippet:
$itemWidth: 400px;
$itemMargin: 10px;
html, body {
margin: 0;
padding: 0;
}
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0 auto;
border: solid 1px blue;
}
@for $i from 1 through 10 {
@media only screen and (min-width: $i * $itemWidth + 2 * $i * $itemMargin) {
.flex-container {
width: $i * $itemWidth + 2 * $i * $itemMargin;
}
}
}
.item {
flex: 0 0 $itemWidth;
height: 100px;
margin: $itemMargin;
background: red;
}
<div class="flex-container">
<div class="item"></div>
<div class="item" style="flex: 500 0 200px"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Here I have created an example on codepen which also implements margin.
The second and the third conditions can be avoided respectively using css variables (if you decided to provide support for it) and compiling the above scss snippet.
Well, it's true, we could do it also before flexbox, but display: flex
can be still essential for a responsive design.
A simple trick adds a flexible space to fill the rest of the last row:
#products-list{
display:flex;
flex-flow: row wrap;
justify-content:space-between;
}
#products-list::after {
content: "";
flex: auto;
flex-basis: 200px;/*your item width*/
flex-grow: 0;
}
But you shouldn't use margins on items then. Rather wrap them into containers with padding.
I was facing this same issue where I wanted to have a variable number of items in a resizable container. I wanted to use all of the horizontal space, but have all of the flex items at the same size.
I ultimately came up with a javascript approach that dynamically added padding spacers as the container was resized.
function padLastFormRow() {
let topList = [];
let nSpacersToAdd = 0;
$('#flexContainer').find('.formSpacer').remove();
$('#flexContainer').find('.formItem').each(function(i, formItem) {
topList.push($(formItem).position().top);
});
let allRowLengths = getFlexLineLengths(topList);
let firstRowLength = allRowLengths[0];
let lastRowLength = allRowLengths[((allRowLengths.length) - 1)];
if (lastRowLength < firstRowLength) {
nSpacersToAdd = firstRowLength - lastRowLength ;
}
for (var i = 1; i <= nSpacersToAdd; i ++) {
$('#flexContainer').append(formSpacerItem);
}
}
Please see my Fiddle: http://jsfiddle.net/Harold_Buchman/z5r3ogye/11/
If all your rows have the same number of items, you can use :nth-last-child
. For example, if all the rows have 3 items, you can do something like this:
.container{ display: flex; flex-wrap: wrap; background: yellow; } .item{ width: calc((100% - 2*10px)/3); height: 50px; background: blue; color: white; margin-right: 10px; margin-bottom: 10px; padding: 5px; box-sizing: border-box; } // last item of each row .item:nth-child(3n){ margin-right: 0; background: green; } // last 3 items .item:nth-last-child(-n+3){ margin-bottom: 0; font-size: 150%; }
<div class="container"> <div class="item" >1</div> <div class="item" >2</div> <div class="item" >3</div> <div class="item" >4</div> <div class="item" >5</div> <div class="item" >6</div> <div class="item" >7</div> </div>
If all your rows have the same number of items, you can use :nth-last-child
. For example, if all the rows have 3 items, you can do something like this to remove the margin of the last 3 items:
.container{ display: flex; flex-wrap: wrap; background: yellow; } .item{ width: calc((100% - 2*10px)/3); height: 50px; background: blue; color: white; margin-right: 10px; margin-bottom: 10px; padding: 5px; box-sizing: border-box; } /* last item of each row */ .item:nth-child(3n){ margin-right: 0; font-size: 150%; } /* last 3 items */ .item:nth-last-child(-n+3){ margin-bottom: 0; background: green; }
<div class="container"> <div class="item" >1</div> <div class="item" >2</div> <div class="item" >3</div> <div class="item" >4</div> <div class="item" >5</div> <div class="item" >6</div> <div class="item" >7</div> </div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.