Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make elements wrap in groups, not one by one

I have six inline, fixed-size elements and would like to wrap them so that each row has the same number of elements. So with a wide container, there would be 1 row with 6 columns / elements. As the container shrinks, it will go to 2x3, then 3x2, and finally 1x6.

My intuition is that I should be using flexbox, but I can't figure out how to stop it from wrapping one element at a time, giving me situations where there's 5 elements in the first row and 1 element in the second.

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

.box div {
  background-color: yellow;
  width: 50px;
  height: 50px;
  margin: 5px;
}
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
  <div>Six</div>
</div>

https://jsfiddle.net/59wgsk2s/1/

like image 324
Jay Weisskopf Avatar asked May 12 '18 19:05

Jay Weisskopf


People also ask

How do I ungroup elements in my design?

On the toolbar above the editor, click Group. To ungroup, click the group and click Ungroup from the editor toolbar. Shortcut: After selecting the elements, press CMD+G (Mac) or CTRL+G (Windows) on your keyboard to group them. You can’t group grids and charts. When added to your design, elements are in layers.

How to make the contents of HTML elements not to wrap?

You can make the contents of HTML <p>, <div>, and <span> elements not to wrap by using some CSS. You need the white-space property. As we know, this property helps us to handle the spaces within the element. So, if you want not to wrap the contents of the elements mentioned above, you need to use the “nowrap” value of the white-space property.

How do I wrap flex items onto new lines?

There is however the ability to wrap flex items onto new lines, creating new rows if flex-direction is row and new columns if flex-direction is column. In this guide I will explain how this works, what it is designed for and what situations really require CSS Grid Layout rather than flexbox. The initial value of the flex-wrap property is nowrap.

How do I wrap items in a container?

The container will need to have a height in order that the items will start wrapping and creating new columns, and items will stretch taller to fill each column completely. Wrapping works as you might expect when combined with flex-direction.


1 Answers

Because your items are fixed-size, getting them to wrap as pairs or a larger multiple is a bit tricky.

The simple way to get multiple items to wrap is by setting their length in percentages. Then, using media queries, the number of items per row can be controlled by adjusting the percentages.

In a layout with, let's say six items (like your layout), widths could be set to 16% for desktop views.

[ 16% ] [ 16% ] [ 16% ] [ 16% ] [ 16% ] [ 16% ] 

Then, for a laptop view, a media query can kick in, changing the widths to 33%:

[ 33% ] [ 33% ] [ 33% ]
[ 33% ] [ 33% ] [ 33% ]

Same idea for a tablet view:

[ 50% ] [ 50% ]
[ 50% ] [ 50% ]
[ 50% ] [ 50% ]

Same again for a mobile view:

[ 100% ]
[ 100% ]
[ 100% ]
[ 100% ]
[ 100% ]
[ 100% ]

Here's an illustration:

jsFiddle

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

.box div {
  flex: 1 0 15%;
  height: 50px;
  margin: 5px;
  background-color: yellow;
  border: 1px solid gray;
}

@media ( max-width: 800px) {
  .box div {
    flex-basis: 30%;
  }
}

@media ( max-width: 600px) {
  .box div {
    flex-basis: 40%;
  }
}

@media ( max-width: 400px) {
  .box div {
    flex-basis: 100%;
    margin: 0 0 5px 0;
  }
}

* {
  box-sizing: border-box;
}
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
  <div>Six</div>
</div>

Of course, the problem with the demo above, as it relates to your question, is that the items don't have fixed width. As percentages, they are flexible.

So let's try the reverse approach: Instead of adjusting the size of the items, let's adjust the size of the container. By shrinking the container (with media queries), we can control the wrapping behavior and keep the fixed-width size of each item:

jsFiddle

.box {
  display: flex;
  flex-wrap: wrap;
  width: 360px;
  background-color: lightgreen;
}

.box div {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: yellow;
  border: 1px solid gray;
}

@media ( max-width: 800px) {
  .box {
    width: 180px;
  }
}

@media ( max-width: 600px) {
  .box {
    width: 120px;
  }
}

@media ( max-width: 400px) {
  .box {
    width: 60px;
  }
}

* {
  box-sizing: border-box;
}
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
  <div>Six</div>
</div>

So if you can use either flexible lengths on the items, or shrink the width of the container, then your problem is solved. However, if neither are an option, then here's a clean and simple solution using CSS Grid Layout.

jsFiddle

.box {
  display: grid;
  grid-template-columns: repeat(6, 50px);
  grid-auto-rows: 50px;
  grid-gap: 5px;
}

@media ( max-width: 800px) {
  .box {
    grid-template-columns: repeat(3, 50px);
  }
}

@media ( max-width: 600px) {
  .box {
    grid-template-columns: 50px 50px;
  }
}

@media ( max-width: 400px) {
  .box {
    grid-template-columns: 50px;
  }
}

.box div {
  background-color: yellow;
  border: 1px solid gray;
}

* {
  box-sizing: border-box;
}
<div class="box">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
  <div>Six</div>
</div>
like image 54
Michael Benjamin Avatar answered Oct 03 '22 15:10

Michael Benjamin