Home > Software engineering >  How to have 5 flex elements in CSS, 3 on one row, and 2 on the next row, which are all the same flui
How to have 5 flex elements in CSS, 3 on one row, and 2 on the next row, which are all the same flui

Time:12-13

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:

enter image description here

Or this:

enter image description here

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:

enter image description here

And not looking for this ideally either:

enter image description here

(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.

  • Related