42

Is there a way to align items in several columns, where the number of columns depends on the widest item? Both the item height and the container width are fixed, but the item width is dynamic.

I am looking for a CSS-only way to achieve the following behavior:

(Assume that the parent container is 300px wide.)

  • If the widest item is wider than 150px, use a single column
  • If the widest item is between 100px and 150px, use two columns
  • If the widest item is less than 100px, use three columns
  • ...
  • If the widest item is less than container width / N, use N columns

One possible way to have this behavior could be by using display:inline-block and setting width property to the width of the widest element in the container using JavaScript.

See this JSFiddle for an example:

Example

However, I am thinking that there should also be a CSS-only way of doing this. Is it possible?

If not, perhaps there is an elegant CSS-only way of distributing / snapping the dynamically-sized items to the columns in a container with a fixed width?

David Mulder
  • 26,123
  • 9
  • 51
  • 114
M. Williams
  • 4,945
  • 2
  • 26
  • 27
  • http://www.w3schools.com/css/css3_multiple_columns.asp ??? OR http://www.w3schools.com/cssref/css3_pr_flex.asp –  Aug 17 '15 at 11:31
  • 1
    if you want css only solution then why tagged under javascript? can it also be included in solution? – Rohit Kumar Aug 17 '15 at 11:47
  • 8
    Basically NO. CSS can't detetct width and change parameters, it can only style *based* on parameters. You need Javascript. – Paulie_D Aug 17 '15 at 11:53
  • 8
    Any time you need to base CSS on an 'if' condition of unrelated, or descendant, elements the answer is going to be "no, you'll need JavaScript." – David Thomas Aug 17 '15 at 11:59
  • Looks like [element queries](http://hugogiraudel.com/2014/04/22/why-element-queries-matter/), which doesn't exist in CSS yet (there are also articles on SmahsingMag and Sitepoint, just google the 2 terms) – FelipeAls Aug 17 '15 at 12:33
  • Not exactly perfect (if there's too many items, there will be scrollbars), but it looks good: https://jsfiddle.net/xnu17xns/5/ – Stephan Bijzitter Aug 19 '15 at 11:55
  • Actually @Paulie_D I believe CSS CAN detect width by using the `calc()` function. You can use it to detect the width of the parent element and set it to a percentage of it along with other adjustments `width: calc(50% - 30px);` for example. It can't be used to the extent of answering this particular issue, but it can be used to detect the width :) – Lyall Aug 21 '15 at 19:07
  • 2
    No, CSS cannot *detect* width. It can set a width based on a parent. An element cannot detect it's own width. – Paulie_D Aug 21 '15 at 19:40
  • Sounds like a job for the [CSS Grid Layout](http://www.w3.org/TR/css-grid-1/). – Knu Aug 22 '15 at 18:49

7 Answers7

26

...I am looking for a CSS-only way to achieve the following behavior...If the widest item is wider than...

...I am thinking that there should also be a CSS-only way of doing this...

As indicated by @Paulie-D, CSS can't detect varying widths in your child divs and hence a pure CSS only solution is not existent.

This is because you are wanting to get the widths of all elements, then get the max of those, and then use that width to distribute elements into columns. This computation is beyond CSS. You will need Javascript to do that.

If not, perhaps there is an elegant CSS-only way of distributing / snapping the dynamically-sized items to the columns in a container with a fixed width?

I will explain that in two parts:


Part 1, the CSS:

When we say that we want content to be in columns, it means a top-to-down flow instead of just left-to-right wrapping flow. For this we require CSS Columns.

The trick would be to specify auto for column-count / column-width. This will automatically distribute the content into the number of columns required within the parent width.

I made a fundamental mistake in the above statement (hence another edit). As per the specs here the algorithm says:

(01) if ((column-width = auto) and (column-count = auto)) then
(02)      exit; /* not a multicol element */ 

This is where I was wrong earlier. When both column-count and column-width are set to auto then it is treated as not a multicol element. When one of these properties is set to non-auto value, then the other property is determined by this one.

From the above ref:

if column-count is set to auto, then the number of columns will be determined by other properties (e.g., column-width, if it has a non-auto value) and if column-width is set to auto, then the column width will be determined by other properties (e.g., column-count, if it has a non-auto value)

An example would be to set column-width to a fixed-width, say 120px (we will deal that in part 2 a little later):

.container { -webkit-columns: auto 120px; columns: auto 120px; }

This will cause the container to fit the content in as many columns as it can for a column width of 120px within its own width. If you increase the container width, it will get more columns. If you decrease the container width, it will get less columns eventually collapsing to a single column when there is not much space available.

See the complete example in snippet below:

Example 1:

* { box-sizing: border-box; padding: 0; margin: 0; }
p { margin-left: 16px; }
.container { width: 400px; border: 1px solid #f00; margin: 16px; }
.container.col { -webkit-columns: auto 120px; columns: auto 120px; }
.container > div { 
 -webkit-column-break-inside: avoid; column-break-inside: avoid; 
 display: block; padding: 8px; border: 1px solid #ccc;
}
#one { width: 200px; }
#two { width: 300px; }
<p>Small Container (1-column):</p>
<div id="one" class="container col">
 <div class="item-min">Maudie Mcmanus</div>
 <div class="item-min">Remedios</div>
 <div class="item-min">Chaya B</div>
 <div class="item-min">Duncan</div>
 <div class="item-min">Lashonda</div>
</div>
<p>Medium Container (2-column):</p>
<div id="two" class="container col">
 <div class="item-min">Maudie Mcmanus</div>
 <div class="item-min">Remedios</div>
 <div class="item-min">Chaya B</div>
 <div class="item-min">Duncan</div>
 <div class="item-min">Lashonda</div>
</div>
<p>Large Container (3-column):</p>
<div id="three" class="container col">
 <div class="item-min">Maudie Mcmanus</div>
 <div class="item-min">Remedios</div>
 <div class="item-min">Chaya B</div>
 <div class="item-min">Duncan</div>
 <div class="item-min">Lashonda</div>
</div>

Fiddle 1: http://jsfiddle.net/abhitalks/tgwp4b7a/2/show

In the above snippet, we are using column-count: auto on the container, and an arbitrary column-width: 120px (just for demo). It is all there is to it. There are three examples in the code above: (1) where container is of small width and content is distributed in one columns as they are constrained by the column-width; (2) where container is of medium width and content is distributed in two columns as there is now more space available; and (3) where container is of much larger width and can accommodate three columns.

As a side-effect, if the container's width is in percent, then the whole apparatus automatically becomes responsive as well. On larger screens showing more columns, and on smaller screens collapsing to one column.

However, this is dependent on the fixed-width that you give to the container's column-width and hence can also be called a magic-number solution. But, this is not what we want. We do not want to determine columns based on container's width, we want the columns to be determined by the content width. We'll see how to eliminate that dependency in the part 2 that follows.


Part 2, extending it with Javascript:

Now that we have established that elements can be distributed automatically by CSS in columns depending on the width available on parent, we can extend this to eliminate our dependence on fixed-width via Javascript.

Coming back to your question of:

...If the widest item is wider than...

In order to determine the widest item and apply that width to the rest of them, all that you require is just a well-known two-liner Javascript:

var maxWidth = Math.max.apply(null, $("div.item").map(function () {
    return $(this).width();
}).get());

We also set child divs to inline-block prevent wrapping to identify the real width. So, all you have to add to the CSS we wrote in part 1 is this:

.container > div {
    display: inline-block; 
    white-space: nowrap;   /* prevents wrapping and helps getting actual width */
}

Then we need to do two things: (1) set the column-width on container to this max-width that we calculated above; and (2) set this width to all of the child div to allow them to stack neatly. Also, we will not be needing column-count / column-width to be set in CSS, because we have to do that in Javascript anyway.

$("#container").css({ "column-width": maxWidth }).find('div').width(maxWidth);

See the complete example in snippet below:

Example 2:

//large
 var maxWidth = Math.max.apply(null, $("#one > div").map(function () { return $(this).outerWidth(); }).get());
 $("#one").css({ "-webkit-column-width": maxWidth, "column-width": maxWidth }).find('div').outerWidth(maxWidth);

 // medium
 var maxWidth2 = Math.max.apply(null, $("#two > div").map(function () { return $(this).outerWidth(); }).get());
 $("#two").css({ "-webkit-column-width": maxWidth2, "column-width": maxWidth2 }).find('div').outerWidth(maxWidth2);

 // small
 var maxWidth3 = Math.max.apply(null, $("#three > div").map(function () { return $(this).outerWidth(); }).get());
 $("#three").css({"-webkit-column-width": maxWidth3, "column-width": maxWidth3 }).find('div').outerWidth(maxWidth3);
* { box-sizing: border-box; padding: 0; margin: 0; }
 p { margin-left: 16px; }
 .container { width: 450px; border: 1px solid #f00; margin: 16px; }
 .container > div { 
  -webkit-column-break-inside: avoid; column-break-inside: avoid; 
  display: inline-block;  white-space: nowrap;
  padding: 8px; border: 1px solid #ccc;
 }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
 <p>Normal children (wrapping):</p>
 <div class="container">
  <div class="item">Maudie Mcmanus</div>
  <div class="item">Remedios Arrington</div>
  <div class="item">Chaya B</div>
  <div class="item">Duncan</div>
  <div class="item">Lashonda Tatum Walls</div>
 </div>
 <p>Large children (1-column):</p>
 <div id="one" class="container">
  <div class="item-min">Maudie Mcmanus Mcmanus Mcmanus</div>
  <div class="item-min">Remedios</div>
  <div class="item-min">Chaya B</div>
  <div class="item-min">Duncan</div>
  <div class="item-min">Lashonda</div>
 </div>
 <p>Medium children (2-column):</p>
 <div id="two" class="container">
  <div class="item-min">Maudie Mcmanus Mcmanus</div>
  <div class="item-min">Remedios</div>
  <div class="item-min">Chaya B</div>
  <div class="item-min">Duncan</div>
  <div class="item-min">Lashonda</div>
 </div>
 <p>Small children (3-column):</p>
 <div id="three" class="container">
  <div class="item-min">Maudie Mcmanus</div>
  <div class="item-min">Remedios</div>
  <div class="item-min">Chaya B</div>
  <div class="item-min">Duncan</div>
  <div class="item-min">Lashonda</div>
 </div>

Fiddle 2: http://jsfiddle.net/abhitalks/ojd57678/4/show

(Changed the above snippet and fiddle. Thanks to @Yandy_Viera, who pointed out the fact that jQuery .outerWdith should be used instead of .width (which ignores box-sizing: border-box, causing incorrect widths to be set.)

In the above snippet, we are now using three variations of examples: (1) where child divs are of larger width and are distributed in one column as they are constrained by the container's width; (2) where child divs are of smaller width and are distributed in two columns as there is now more space available; and (3) where child divs are of very small width and can be accommodated in three columns.


As you can see, CSS can help in distributing content into columns based on available width but cannot calculate and apply widest of the element widths to each of them. For this a two-liner Javascript would get you done what you initially wanted.

Note: When I first read your question I was under the impression that you already have a working Javascript solution with you, and I wasn't sure if you wanted one. However, on a second read I realized that you hadn't, and the Javascript angle was essential to understand. Hence, this edit to add a Javascript part.

Note 2: There was a flaw in the previous version of this answer, where I let in a fundamental mistake in auto values of the columns properties. This necessitated another edit.

Community
  • 1
  • 1
Abhitalks
  • 27,721
  • 5
  • 58
  • 81
  • hm, nice. Can you add, if width is small the columns will be the same height? – AleshaOleg Aug 17 '15 at 12:00
  • Hmmmm.. in a sense yes @Paulie_D. The width of the children need be fixed. Shall update the answer to indicate so. – Abhitalks Aug 17 '15 at 12:14
  • Where the OP says that he/she wants "*a top-to-down flow*"?, in fact in the OP's example is not that way, note that Remedios comes after Maudie but is on the right (**[Maudie Mcmanus] [Remedios Arrington]**) not as in your example that Remedios is in the line below. On the other hand, Why when the content of the items is changed that they are restructured, they lose the right border? – Yandy_Viera Aug 26 '15 at 13:47
  • @Yandy_Viera: Thank you for noticing that, much appreciated. (1) This is exactly why I added that in the answer. I was myself not too sure what the Op wanted, as my understanding of *columns* has always been top-down-across. And this is the way CSS columns have been spec'ed out out implemented. So, I thought it best to indicate my assumption to avoid the confusion and let Op decide. (2) I can't reproduce the problem of disappearing border. It looks fine from here. Nevertheless, now that you have pointed it out, I shall surely have a look at that. Thank you once again. – Abhitalks Aug 26 '15 at 16:07
  • @Abhitalks you are welcome, the problem of the border right you can see it in the image of your example and check out this jsfiddle forks from yours, I just remove some content of the items http://jsfiddle.net/Yandy_Viera/qvbbfdsL/1/ – Yandy_Viera Aug 26 '15 at 16:24
  • @Yandy_Viera: Thank you again :) It was a silly lapse on my part, I should have used `.outerWidth` instead of `.width` (which ignores the box model and was giving and setting incorrect widths). This cause the width to be less than the real width and this disappearing right border. Fixed. – Abhitalks Aug 26 '15 at 17:07
  • @Costantino: Thanks. A bit too late eh? I lost the bounty ;) – Abhitalks Aug 28 '15 at 05:08
  • @Abhitalks My fault, sorry — I was offline and the bounty was awarded automatically. Thank you very much for your detailed answer, it was very helpful. – M. Williams Aug 31 '15 at 20:43
  • @Abhitalks I have deleted my question. Oops, it was just a typo only. Thanks a lot – Zameer Ansari Dec 28 '15 at 08:13
11

As well all they said in comments, do not exist a CSS-only solution so I wanted to leave you a nice solution using js in which you do not even have to iterate looking for the widest item, everything comes from a set of CSS and math.

You can change the contents of the elements and you will see how the number of columns are adjusted, if the widest item is less than container width / N, it will use N columns automatically.

Check out this JSFiddle for demo

The idea is very simple, you set width: 'auto', display: 'inline-block' to container to allow it to fit its contents which is defined by the width of the widest element see it in the bellow img:

enter image description here

Now you can use the width of container to know the width of widest item and this avoid you to have to iterate seeking it. Right now you can use this width to setting to the rest of items but let's do it a little better we can make elements occupy the entire width of the container just with a litter calc:

var div = Math.floor(initialWidth / widestItemWidth);     /*this is to get as many items fit with the width of the widest element*/
var itemWidth = initialWidth / div;      /*for the width of the item occupy the entire container*/

So if the widest item is less than container width / N, it will use N columns automatically and they will fit the width of container, that is all you have to do, just set a css property, do a little calc and there you have what you wanted to achieve.

$(document).ready(function() {
    var $container = $('.container');
    var $item = $('.item');

    var initialWidth = $container.outerWidth();

   $container.css({     /*to allow it to fit its contents which is defined by the width of the widest element*/
        width: 'auto',
        display: 'inline-block'
    });   

    var widestItemWidth = $container.outerWidth();     /*Now this is the width of the widest item*/

    var div = Math.floor(initialWidth / widestItemWidth);     /*this is to get as many items fit with the width of the widest element*/
    var itemWidth = initialWidth / div;      /*for the width of the item occupy the entire container*/
  
  /*if you don't want the items occupy the entire width of the container just use 'widestItemWidth' as width of $item*/

    $item.css({
        width: itemWidth,
        float: 'left'
    });
    $container.css({     /*restoring the initial styles*/
        width: initialWidth,
        display: 'block'
    });
})
.container {
  width: 400px;
  overflow: hidden;
}
.container .item {
  padding: 8px;
  border: 1px solid rgb(216, 213, 213);
}
*{
  box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
    <div class="item">Maudie Mcmanus</div>
    <div class="item">Remedios Arrington</div>
    <div class="item">Chaya B</div>
    <div class="item">Duncan</div>
    <div class="item">Lashonda Tatum Walls</div>
</div>

If you want to add margin to your items you just have to take it into account when you do the math like this:

$(document).ready(function() {
    var $container = $('.container');
    var $item = $('.item');

    var initialWidth = $container.outerWidth();

    $container.css({
            width: 'auto',
            display: 'inline-block'
        });

    var currentWidth = $container.outerWidth();
    var itemMargin= parseInt($item.css('margin-right'));

    var div = Math.floor(initialWidth / currentWidth);
    var itemWidth = initialWidth / div - itemMargin;   /*subtracting the item's margin from the compute width*/

    $item.css({
        width: itemWidth,
        float: 'left'
    });
    $container.css({
        width: initialWidth,
        display: 'block'
    });
})
.container {
  width: 400px;
  overflow: hidden;
}
.container .item {
  padding: 8px;
  border: 1px solid rgb(216, 213, 213);
  margin-right: 3px;
}
*{
  box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
    <div class="item">Maudie Mcmanus</div>
    <div class="item">Remedios Arrington</div>
    <div class="item">Chaya B</div>
    <div class="item">Duncan</div>
    <div class="item">Lashonda Tatum Walls</div>
</div>

Here a JSFiddle example to play with

Yandy_Viera
  • 4,320
  • 4
  • 21
  • 42
4

The closest you can probably get with a pure CSS solution is to use CSS columns as suggested by others (or CSS Grid approach - See Edit). But, the key is to use relative units and be very aware of the location and of your column container in your layout and use media queries to control column count. This is definitely NOT a bulletproof solution. However, if you are creating the layout and control the placement and scope of the column container element then you can control the column count fairly reliably. If this is for a widget that is out of your control you will indeed need to implement a Javascript based solution.

Reference Links: Responsive CSS Columns, CSS Grid Layout

EDIT: After reading your question again and looking at your screenshot example, it looks as though you are actually looking for a common CSS grid grid solution where the elements flow horizontally and not vertically. I updated my answer to include a snippet demo of this where the blocks re-flow horizontally.

Snippet Demo with Columns based Media Queries and Container Widths (approximate minimum column width of 10em):

#main, #sideBar {
    box-sizing:border-box;
    display:block;
    padding:0;
    margin:0;
    width:100%;
}

.container {
    width: 100%;
    min-width:10em;
    -webkit-columns: 1;
    -moz-columns: 1;
      columns: 1;
}
.container .item {
    display: block;
    padding: 8px;
    border: 1px solid rgb(216, 213, 213);
    box-sizing:border-box;
    -webkit-column-break-inside: avoid; /* Chrome, Safari, Opera */
          page-break-inside: avoid; /* Firefox */
               break-inside: avoid; /* IE 10+ */
}
@media only screen and (min-width:20em) {
    .container {
    -webkit-columns: 2;
    -moz-columns: 2;
      columns: 2;
    }
}

@media only screen and (min-width:32em) {
    #main {
        float:left;
        width:65%;
    }

    #sideBar {
        float:left;
        width:30%;
        margin-left:5%;
    }
    #sideBar .container {
    -webkit-columns: 1;
    -moz-columns: 1;
      columns: 1;
    }

}

@media only screen and (min-width:48em) {
    
    #main .container {
    -webkit-columns: 3;
    -moz-columns: 3;
      columns: 3;
    }

    #sideBar .container {
    -webkit-columns: 1;
    -moz-columns: 1;
      columns: 1;
    }

}

@media only screen and (min-width:52em) {
    
    #sideBar .container {
    -webkit-columns: 2;
    -moz-columns: 2;
      columns: 2;
    }

}

@media only screen and (min-width:100em) {
    
    #main .container {
    -webkit-columns: 5;
    -moz-columns: 5;
      columns: 5;
    }

    #sideBar .container {
    -webkit-columns: 3;
    -moz-columns: 3;
      columns: 3;
    }

}
<div id="main"><h1>#main</h1>
    <div class="container">
        <div class="item">Maudie Mcmanus</div>
        <div class="item">Remedios Arrington</div>
        <div class="item">Chaya B</div>
        <div class="item">Duncan</div>
        <div class="item">Lashonda Tatum Walls</div>
    </div>
</div>
<div id="sideBar"><h1>#sideBar</h1>
    <div class="container">
        <div class="item">Maudie Mcmanus</div>
        <div class="item">Remedios Arrington</div>
        <div class="item">Chaya B</div>
        <div class="item">Duncan</div>
        <div class="item">Lashonda Tatum Walls</div>
    </div>
</div>

EDIT: Added this Snippet Demo using a CSS Grid approach that re-flows the blocks horizontally instead of vertically.

#main, #sideBar {
    box-sizing:border-box;
    display:block;
    padding:0;
    margin:0;
    width:100%;
    clear:left;
}

.container {
    width: 100%;
    min-width:10em;
}

.container .item {
    display: block;
    float:left;
    padding: .5em;
    border: 1px solid rgb(216, 213, 213);
    box-sizing:border-box;
    vertical-align: top;

}

@media only screen and (min-width:20em) {
    .container .item {
        margin: 0 1%;
        width:48%;
    }
}

@media only screen and (min-width:32em) {
    #main {
        float:left;
        width:65%;
    }

    #sideBar {
        float:left;
        clear:none;
        width:30%;
        margin-left:5%;
    }
    

    #sideBar .container .item {
        margin: 0;
        width:100%;
    }

}

@media only screen and (min-width:48em) {
    
    #main .container .item {
        width:31%;
    }

}

@media only screen and (min-width:52em) {
    
    #sideBar .container .item {
        margin: 0 1%;
        width:48%;
    }


}

@media only screen and (min-width:100em) {
    
    #main .container .item {
        width:18%;
    }

    #sideBar .container .item {
        width:31%;
    }

}
<div id="main"><h1>#main</h1>
    <div class="container">
        <div class="item">Maudie Mcmanus</div>
        <div class="item">Remedios Arrington</div>
        <div class="item">Chaya B</div>
        <div class="item">Duncan</div>
        <div class="item">Lashonda Tatum Walls</div>
    </div>
</div>
<div id="sideBar"><h1>#sideBar</h1>
    <div class="container">
        <div class="item">Maudie Mcmanus</div>
        <div class="item">Remedios Arrington</div>
        <div class="item">Chaya B</div>
        <div class="item">Duncan</div>
        <div class="item">Lashonda Tatum Walls</div>
    </div>
</div>
IMI
  • 2,461
  • 1
  • 14
  • 20
  • The @media thing only refers to the screen width, and it doesn't solve his problem, since his ".container" element is not the body of the page. – Ronen Cypis Aug 24 '15 at 13:27
  • @RonenCypis - I think you have misunderstood my answer. No part of my answer uses the `.container` class on the `body` element of the page. If you fully read the answer, and examine the snippet examples, you can see that the media queries are used to control column count for the `.container` element based on its parent element's width. Even though these answers are not "dynamic", they do provide possible solutions to the OP's issue of equal column widths and re-flow by using only CSS. – IMI Aug 24 '15 at 14:33
2

Well as many others pointed it out here there is no CSS only solution. Mainly because CSS was designed to be loaded before the dom content so the content display nicely. Our main problem here is that we do NOT know the width of the element in advance, we will only know it when the page has loaded. Almost all the solutions on the page have the same idea, use Javascript to loop trough the elements, find the widest one and set all other elements (with the same class) to the given width. To improve the process and to make it a one line solution (with jquery, can be done with Javascript as well, but for simplicity I used jQuery), I suggest the following "hack / trick":

1) Do not define the width of your container, and set the display to table rather than block;

2) Do not set any width for the items inside the div

This will make the items have the same width and display in one column, so when we use jQuery to get the max width we do not need to loop trough the elements.

Now use jQuery to inject additional CSS rules into the document header for the container and for the items. We need to change the container display type back to block instead of table, set it's width to 400px (or whatever we need) and we need to make the items inline-blocks with a set width.

Since CSS is always applying the last property this will be quite easy:

$("<style> .container {display: block; width:400px;} .item-min {width:"+$(".item-min").width()+"px;display:inline-block;}</style>").appendTo("head");

I have updated your Fiddler example HERE

I have tested it in IE 12, Edge, Chorme and Firefox and it works in all the browsers.

EDIT 1

If you do not want to use jQuery to keep the page as light as possible you can use the following one liner Javascript as well:

document.head.innerHTML += "<style> .container {display: block; width:400px;} .item-min {width:"+(document.getElementsByClassName("container")[0].clientWidth-16-2)+"px;display:inline-block;}</style>";

Quick explanation: container clientWidth will include the padding and the border of the items, since the padding in the original example is 8px and the border is 1px we need to deduct it twice (one time left one time right) from the width of the container.

See updated Fiddle

EDIT 2

A complete HTML document:

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <style type='text/css'>
    .container {

    display:table;
    table-layout:fixed;
}

.container .item-min {
    padding: 8px;
    border: 1px solid rgb(216, 213, 213);

}
  </style>


<script type='text/javascript'>
window.onload=function(){
document.head.innerHTML += "<style> .container {display: block; width:400px;} .item-min {width:"+(document.getElementsByClassName("container")[0].clientWidth-16-2)+"px;display:inline-block;}</style>";
}
</script>

</head>
<body>
      <div class="container">
        <div class="item-min">Maudie Mcmanus</div>
        <div class="item-min">Remedios Arrington</div>
        <div class="item-min">Chaya B</div>
        <div class="item-min">Duncan</div>
        <div class="item-min">Lashonda Tatum Walls</div>
    </div>


</body>

</html>
Emil Borconi
  • 3,326
  • 2
  • 24
  • 40
1

First of all- Check out the Fiddle Demo (play with the .container's width...)

This is not possible using CSS only, but here is an elegant solution using jquery, that detects the container's width, the widest item's width, and spread the items into the relevant number of columns (dynamically created).

HTML

<p>Without width:
    <div class="container">
        <div class="item">Maudie Mcmanus</div>
        <div class="item">Remedios Arrington</div>
        <div class="item">Chaya B</div>
        <div class="item">Duncan</div>
        <div class="item">Lashonda Tatum Walls</div>
    </div>
</p>

Javascript

$(function(){
    var $items = $('.item');

    // detect the widest column's width
    var widestItemWidth = 0;
    $items.each(function(){
        widestItemWidth = Math.max(widestItemWidth, $(this).width());
    });

    // calculate the number of columns
    var $container = $('.container');
    var containerWidth = $container.width();
    var numOfColumns = parseInt(containerWidth / widestItemWidth);

    // create the columns
    for(var i = 0; i < numOfColumns; i++){
        $container.prepend('<div class="column"></div>');
    }
    var $columns = $('.column');
    $columns.css('width', (100/numOfColumns)+'%');

    // spread the items between the columns
    $items.each(function(i){
        var columnIndex = i % numOfColumns;
        $(this).appendTo($columns.eq(columnIndex));
    });
});

CSS

.container {
    width: 400px;
}
.container .column {
    display: inline-block;
    box-sizing: border-box;
    vertical-align: text-top;
}
.container .item {
    display: inline-block;
    padding: 8px;
    border: 1px solid rgb(216, 213, 213);
}
Ronen Cypis
  • 21,182
  • 1
  • 20
  • 25
0

The easiest would seem to set width to 32% plus clear:none for all columns and a separate clear:both class per every third (last) column. Add media queries to address different screen sizes and set width accordingly, e.g. 24%, 48%, etc.

0

Try this example

@media only screen and (device-width : 300px) {#container {width:300px; display:block;}}
@media only screen and (device-width : 150px) {#container {width:150px; display:block; float:left}}
@media only screen and (device-width : 100px) {#container {width:150px; display:block; float:left}}
Qorbani
  • 5,825
  • 2
  • 39
  • 47
Stalin Rex
  • 31
  • 3