Say I have 5 "flex" elements with flex-wrap
turned on and flex-direction: row
. I would like it to turn out like either of these two options:
Or this:
How can I make it so the items on the bottom row (which don't have enough to fill the space) are the same size as the row(s) above, which would have 3 in each preceding row? I don't want this basically:
And not looking for this ideally either:
(Assume my diagrams everything was perfectly aligned, sorry for the quick sketch)
I have tried stuff like this:
.container {
width: 100%;
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.box {
display: flex;
justify-content: center;
align-items: center;
height: 100px;
min-width: 30%; /* hack so it doesn't shrink too much */
background-color: purple;
color: white;
flex: 1;
}
<div >
<div >hello 1</div>
<div >hello 2</div>
<div >hello 3</div>
<div >hello 4</div>
<div >hello 5</div>
</div>
Notice how my example is like the second to last image, which I want to avoid. I want all items to be the same width, yet only allow 3 per row max.
Note, the elements will be of dynamic height, they will all be the same height potentially, but not given an explicit height. I only gave it an explicit height for demonstration purposes. My real app has content in these boxes like on a landing page.
If flexbox can't do this, that would be good to know. Then I would like to know how to do it another (modern) way somehow.
Also, the number of elements is dynamic too, 3 per row (or really, n per row, for different circumstances and a more general answer).
CodePudding user response:
We can use css grids to help us achieve what you are looking for
Here is a code snippet that describes scenario one that you have posted in the question
we create a template for a grid and give each area of our grid an identifier. We then assign each of our box
to a location on the grid
.box{
width: 100px;
height: 100px;
background-color: aquamarine;
}
#grid{
display: grid;
grid-template-rows: 200px 200px;
grid-template-columns: 200px 200px 200px;
grid-template-areas: "one two three"
"four five empty";
}
#one{
grid-area: one;
}
#two{
grid-area: two;
}
#three{
grid-area: three;
}
#four{
grid-area: four;
}
#five{
grid-area: five;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>HTML 5 Boilerplate</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="grid">
<div id="one">
Text
</div>
<div id="two">
Text
</div>
<div id="three">
Text
</div>
<div id="four">
Text
</div>
<div id="five">
Text
</div>
</div>
</body>
</html>
CodePudding user response:
You can use a width
(i.e. not min or max-width) set with a percentage value, forbid them to shrink (flex-shrink: 0
) and use margin
on the boxes to get the gaps:
.container {
width: 100%;
display: flex;
flex-wrap: wrap;
}
.box {
display: flex;
justify-content: center;
align-items: center;
height: 100px;
width: 30%;
flex-shrink: 0;
background-color: purple;
color: white;
margin: 1.66%;
}
<div >
<div >hello 1</div>
<div >hello 2</div>
<div >hello 3</div>
<div >hello 4</div>
<div >hello 5</div>
</div>
CodePudding user response:
Using CSS grid can give you a bit more control in a 2D layout.
This snippet is simply a grid with 3 columns and the gap of 16px as in the question.
.container {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 16px;
}
.box {
display: flex;
justify-content: center;
align-items: center;
height: 100px;
background-color: purple;
color: white;
flex: 1;
}
<div >
<div >hello 1</div>
<div >hello 2</div>
<div >hello 3</div>
<div >hello 4</div>
<div >hello 5</div>
</div>
You might want to put in a media query for a really narrow viewport if you want to keep 16px gap. In your question you have the narrowest a box can go as 30% so there's a breakpoint at 10% of the container being 32px.