5

I have a variable number of divs, which should be displayed on two lines, as follows

[1]  [3]  [5]  [7]

[2]  [4]  [6]  ...

I looked at the column-count property, however it's not exactly what I need, as it fixes the number of columns, whereas in my case it should be dynamic. (what I need would be a similar line-count property, which doesn't seeem to exist).

Is there a pure CSS solution, or should I make container divs for every groups of 2 vertical divs?

Thanks,

Edit : Here is a simplified code of my case. Actually, As I set the height property on my container div, shouldn't the article divs be stacked by at most 2 ? Now they're overflowing the container.

<html>
<head>
<link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
<div class="container">
<div class="article">A</div>
<div class="article">B</div>
<div class="article">C</div>
<div class="article">D</div>
<div class="article">E</div>
</div>
</body>
</html>

and the CSS

.article {
width:50px;
height:50px;
border:1px gray dashed;
margin:1px;
}

.container {
height:110px;
max-height:110px;
}

However with this code all the article divs are in one column.

Eino Gourdin
  • 4,169
  • 3
  • 39
  • 67

5 Answers5

4

You can use the columns css property on a container:

#columns-holder {
  -moz-columns: 100px;
  -webkit-columns: 100px;
  columns: 100px;
  -moz-column-gap: 15px;
  -webkit-column-gap: 15px;
  column-gap: 15px;
}
.box {
  width: 100px;
  height: 100px;
  margin-bottom: 15px;
  background: grey;
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
  break-inside: avoid;
}
<div id="columns-holder">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
  <div class="box">7</div>
  <div class="box">8</div>
  <div class="box">9</div>
  <div class="box">10</div>
</div>
Pete
  • 57,112
  • 28
  • 117
  • 166
  • Ah it's almost this ! However if I set a height for the "box" divs, I'll have the top half of div 2 on the first column, and the bottom half on the second one. Do you know how to prevent those blocks from being cut like this ? – Eino Gourdin Jun 26 '15 at 11:39
  • 1
    Yes it's almost perfect. But the problem with this way is that if I have only 2 divs for example, they'll still be cut in half and spread to take the whole width. I went with `flex-flow: column wrap;` from Nico O's answer. I guess `columns:` is best appropriated for text, and less for solid blocks? But thanks! – Eino Gourdin Jun 26 '15 at 12:27
  • Cool no worries, glad you found a solution – Pete Jun 26 '15 at 12:29
2

You can do this using flexbox and flex-direction: column; Doing so will allow you to have new columns once the bottom of parent element is reached.

Here is an example:

*
{
  box-sizing: border-box
}
.flex-parent
{
  display: flex;
  flex-flow: column wrap;
  /* this indicates, when a new "column" will be started */
  height: 200px;
  align-content: flex-start;
}
.flex-parent .col
{
  flex: 0 0 auto;
  width: 100px;
  height: 50px;
  background-color: silver;
  margin: 4px;
}
<div class="flex-parent">
  <div class="col">1</div>
  <div class="col">2</div>
  <div class="col">3</div>
  <div class="col">4</div>
  <div class="col">5</div>
  <div class="col">6</div>
  <div class="col">7</div>
  <div class="col">8</div>
  <div class="col">10</div>
  <div class="col">11</div>
  <div class="col">12</div>
</div>
Nico O
  • 13,762
  • 9
  • 54
  • 69
  • Thanks ! That does the trick ! Just one point left, with display:flex, the spacing between the "col" divs depends on the width of the page. But I would need the coumns to be like 20px apart. Is there a way to fix a max width for the columns (or a max margin for the boxes)? – Eino Gourdin Jun 26 '15 at 11:49
  • 1
    Sure, just apply `align-content: flex-start;` to the flex parent. See updated answer. You can change the `margin: 4px` to `margin: 10px;` to have items to be spaced by 20px in total. – Nico O Jun 26 '15 at 11:54
  • 1
    you are very welcome. [Here is some information about browser support](http://caniuse.com/#feat=flexbox) - when you need safari support, you will want to add a `-webkit-` prefix. – Nico O Jun 26 '15 at 12:00
1

When I have to do something like this i use float property with a code like this to be applied to each div you want to display:

.divclass{
    float: left;
    margin: 10px;
    width: 300px;
}

don't forget to clear float after the list of divs:

<br stytle="clear: both;">

With this structure I get to put as many divs as they can fit on the screen width and to put the others on a new line. Obviously the number of divs on each row will be dependent on the screen width or container div width. Can help you a bit more if you provide more code of yours.

Lelio Faieta
  • 6,457
  • 7
  • 40
  • 74
  • Thanks for the idea! Actually I need to stack them by columns of 2. So I tried to replace `float:left;`by `float:top;`, but even with the `clear:both`, and a maximum height for my parent div, the child divs continue to be stacked on a single column. Do you have any idea ? – Eino Gourdin Jun 26 '15 at 11:53
  • Keep the float left. Adjust container width and div width to get divs as you want. If you have a 600px container and divs are 300px you have them on two columns (if you don't count margins) – Lelio Faieta Jun 26 '15 at 12:44
1

For Column-count With a simple list mark up

<ul>
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>D</li>
<ul>

Use this CSS:

ul {
    -moz-column-count: 2;
    -moz-column-gap: 20px;
    -webkit-column-count: 2;
    -webkit-column-gap: 20px;
    column-count: 2;
    column-gap: 20px;
}

Another option is CSS3 as below: CSS3 solution would look like this:

HTML

<div id="wrap">
    <div class="list_item">A</div>
    <div class="list_item">B</div>
    <div class="list_item">C</div>
    <div class="list_item">D</div>
    <div class="list_item">E</div>
    <div class="list_item">F</div>
    <div class="list_item">G</div>
    <div class="list_item">H</div>
</div>

CSS:

.list_item {
    float: left;
    margin: 5px;
    padding: 5px;
    width: 200px;
    border: 1px solid gray;
}
#wrap {
    width:460px;
    column-count:2;
    column-gap:20px;
    -moz-column-count:2;
    -moz-column-gap:20px;
    -webkit-column-count:2;
    -webkit-column-gap:20px;
}

you can see more details at here

Community
  • 1
  • 1
developer
  • 1,565
  • 1
  • 9
  • 12
  • Thanks for the answer ! Actually column-count fixes 2 column, whereas I would need 2 lines, and as many columns as needed. So I would need something like a `line-count`. Do you know of a way I could do this ? – Eino Gourdin Jun 26 '15 at 11:41
0

Here is an example of a grid where the elements will be 4 elements on each row.

You can adjust the size of the .container element to what you want. If you don't want to support vw units.

Why widht:22%;?
The logical way would be to set width:25% right if we want 4 elements? 4x25=100.
Try to edit the code below to that :) As you see it will wrap to a new line. Setting it slightly less 23% or 22% I went with 22%.
Now you have some space for border margins and paddings. If you want them to fit perfectly next to one an other.
set the box-sizing: borderbox. and 0 margin 0 padding (and no white space) and a width of 25%. Should get you close to a perfect fit.

.container {
  width: 50vw;
  border: 5px solid pink;
}
.container .item {
  display: inline-block;
  border: 2px solid firebrick;
  width: 22%;
  height: 50px;
}
<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 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 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 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 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 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 class="item"></div>
</div>
Persijn
  • 14,624
  • 3
  • 43
  • 72
  • 1
    Hi, thanks for your answer ! However I need it the other way, that is once you filled a column (of 2 elements), you switch to a new line :) – Eino Gourdin Jun 26 '15 at 10:17