For what it's worth: It's now 2017 and the grid layout module does this out of the box
* {
margin:0;
padding:0;
}
.container {
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
grid-gap: 10px;
justify-content: center;
align-content: flex-start;
margin: 0 auto;
text-align: center;
margin-top: 10px;
}
.block {
background-color: #ddd;
border: 1px solid #999;
height: 100px;
width: 100px;
}
<div class="container">
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
<div class="block">Foo</div>
</div>
If the browser support suits you - then use grid. If not, then read on....
As mentioned in @Web-tiki's answer, the best you can do with CSS is with a series of media queries.
That being said, if you are using a preprocessor such as LESS - this isn't such a difficult or error-prone task. (although, yes, the CSS will still be long and ugly)
UPDATED CODEPEN (Resize the window to see the results)
Here's how to take advantage of LESS to set up the media queries:
First set up some less variables according to the design which you need:
@item-width:100px;
@item-height:100px;
@marginV: 4px;
@marginH: 2px;
@min-cols:2;
@max-cols:9; //set an upper limit of how may columns you want to write the media queries for
Then:
Set up an iteration mixin like this: (You can paste this code into http://less2css.org)
.loopingClass (@index-width) when (@index-width <= @item-width * @max-cols) {
@media (min-width:@index-width) {
.container{
width: @index-width;
}
}
.loopingClass(@index-width + @item-width + 2*@marginH);
}
.loopingClass (@item-width * @min-cols + @min-cols*@marginH*2);
The above mixin will spit out a series of media queries in the form:
@media (min-width: 208px) {
.container {
width: 208px;
}
}
@media (min-width: 312px) {
.container {
width: 312px;
}
}
@media (min-width: 416px) {
.container {
width: 416px;
}
}
@media (min-width: 520px) {
.container {
width: 520px;
}
}
@media (min-width: 624px) {
.container {
width: 624px;
}
}
@media (min-width: 728px) {
.container {
width: 728px;
}
}
@media (min-width: 832px) {
.container {
width: 832px;
}
}
With remaining CSS (LESS):
.container {
margin: 0 auto;
text-align: center;
overflow: auto;
min-width: @min-cols * @item-width;
max-width: @max-cols * @item-width;
display: block;
list-style:none;
}
.block {
background-color: #ddd;
border:1px solid #999;
box-sizing:border-box;
float: left;
height: @item-height;
width: @item-width;
margin:@marginV @marginH;
}
... you get the desired result.
...and it's super easy to customize the layout:
All I need to do is change the variables that I used in the LESS mixin according to my needs - I get the exact layout that I'm after.