Let’s say you have a bunch of images you want to display, and the goal is to get them edge-to-edge on the browser window with no gaps. Just because you think that would be cool. They are of all different sizes. You don’t care if they are resized, but they should maintain their aspect ratio. Like this:

Ideally we keep it pretty chill on the markup, like:
<section id="photos">
<img src="images/cat-1.jpg" alt="Cute cat">
<img src="images/cat-2.jpg" alt="Serious cat">
...
</section>
Without any CSS at all, the images will line up in a row since they are essentially inline-block:

But that’s not quite what we want. Your mind might go right to some JavaScript solution. Possibly the super cool Masonry project. The problem with the JavaScript option is that it relies on the window.resize event which (to me at least) always makes pages feel sluggish (even if you are hip and do the unbouncing thing).
We can get this working the way we want it to with just CSS. What we need are vertical columns in which to place the images. That way the images will stack on top of each other, and the height issue is moot.
We could wrap equal numbers of images in floated divs, but that’s not very easy to keep balanced. The trick is going to be to use Masonry CSS, where the vertical columns are made through the CSS3 property column-count
. Yeah, literally, the thing where you can set text in narrow columns automatically.
So as long as the parent with the multiple columns is as wide as the browser window (default) and the column-gap
is 0, we got it made in the shade. By setting the width of the image to 100%, they will take up exactly the width of one column.
Here’s the CSS:
#photos {
/* Prevent vertical gaps */
line-height: 0;
-webkit-column-count: 5;
-webkit-column-gap: 0px;
-moz-column-count: 5;
-moz-column-gap: 0px;
column-count: 5;
column-gap: 0px;
}
#photos img {
/* Just in case there are inline attributes */
width: 100% !important;
height: auto !important;
}
But what about when the browser window starts getting narrow? 5 columns might be great for a very large browser window but too many for a smaller browser window (5 images side-by-side might get too narrow). We can fix the problem super easily by having media queries test the browser width and adjust the number of columns accordingly.
@media (max-width: 1200px) {
#photos {
-moz-column-count: 4;
-webkit-column-count: 4;
column-count: 4;
}
}
@media (max-width: 1000px) {
#photos {
-moz-column-count: 3;
-webkit-column-count: 3;
column-count: 3;
}
}
@media (max-width: 800px) {
#photos {
-moz-column-count: 2;
-webkit-column-count: 2;
column-count: 2;
}
}
@media (max-width: 400px) {
#photos {
-moz-column-count: 1;
-webkit-column-count: 1;
column-count: 1;
}
}
Fannnnnncy.
Demo
See the Pen Seamless Responsive Photo Grid by CSS-Tricks (@css-tricks) on CodePen.
What is cool about this technique to me is that since it’s pure CSS, everything happens very smooth and fast. You can resize your browser all around and watch things resize and move very quickly.
What about, you know.
So as far as browser support, it’s pretty good, except IE, where it only works in 10+. Otherwise: Firefox 3.6+, Opera 11.1+, Safari 4+, Chrome 10+. Might even be a bit deeper than that.
You might just skip a fallback because whatever it’s not that bad it just has some white gaps. Or you might use the Modernizr/YepNope combo (Modernizr can test for it as csscolumns
) to load up jQuery Masonry and see what you can do with that. Or you could test for it and roll your own JS which counts the images and splits them up into equal groups and wraps floated divs around them. Whatever floats your boat.
Super cute cats!!
Totally. They are from LoremPixel. For the demo we grabbed photos in random sizes with jQuery:
function getRandomSize(min, max) {
return Math.round(Math.random() * (max - min) + min);
}
for (var i = 0; i < 25; i++) {
var width = getRandomSize(200, 400);
var height = getRandomSize(200, 400);
$('#photos').append('<img src="//www.lorempixel.com/'+width+'/'+height+'/cats" alt="pretty kitty">');
}
Very cool. :)
Hm… any way to fix the bottom though?

I kinda hope comments had markdown… oh well. :/
Very well Chris. I had posted in forums how to create such grid layout a couple of days back. Thanks for creating a tut on it :)
Great article! There’s definitely a “Masonry” trend going around the web, especially for images galleries. But this is a pure CSS solution.
Good work! And Thanks!
This is cool, but I would think, in most cases, you would want your images to load left to right and not top to bottom in columns…. I guess you could sort your images so they would load that way, but that seems like a lot of work unless it’s a static list.
1|2|3|4
5|6|7|8
vs
1|3|5|7
2|4|6|8
There could be some kind of jQuery thing that arranges the photos the right way:
1|2|3|4
5|6|7|8
If anyone can do it, then you can earn another yellow star!
Very nice article, thanks for the tip. Interesting concept for portfolio sites.
-Matt
too bad css columns don’t allow for “column-min-width” and “column-max-width.” that’d be “made in the shade” with no media queries.
Nice article. Pretty nifty idea. This will certainly inspire my next image wall.
Have to correct on compatibility though. At least in my Firefox 3.6.18 it does not work. Images are scaled 100% of the browser window. Seems as if the columns are not used.
I will investigate later.
Thx for the article
Sascha
Cool Chris, thanks for this tut. Was discussing this exact format with some development guys the other day, they wanted to minimize any jquery etc for a design they are converting to cms so if we still need to go down this route I will definitely show them this all CSS technique.
What does the ‘rand(200, 400)’ do in the php? It doesn’t seem to be a height, but part of the image link.
original code:
prints out this:
rand(200,400) is giving a random number between 200 and 400 and printing(echoing) it in the height portion of the url.
It is part of the URL. The service (placedog) takes arguments from the url and returns dog pictures with the dimensions given.
Great stuff!
Hey Chris! I wonder why you’ve stopped using
rel="(CSS, HTML, PHP etc)"
I was just lazy, I fixed these.
Thanks! Although, then it wouldn’t be necessary, for example, to include ‘PHP:’ before the code and then PHP being written inside the ‘code-box’ again. I suggested using
rel
again because I thought then you’d not have to say ‘PHP:’ or ‘Here’s the CSS:’ before the code-box.And, if the above comment sounds rude, then please don’t mind it, I apologize in advance =)
Hi Chris, nice article and a very funky technique.
If I’m not mistaken, there’s a small typo inside your media queries.—shouldn’t
#people
be#photos
?Yes it should :-) Just spend way too much time debugging everything in the download.
Yeah… fixed thanks
Wow this is so straight forward and useful. Cheers.
Cool. And how nice would that be as plugin for WordPress: An Overview of every pic ever published, linked to its post… ;o)
How about the idea of a wordpress template that would post thumbnailed images like this at full-screen as short cuts to blog posts? Yet one box would remain in a fixed location as a logo?
That’s actually a great idea. I can see this being very useful, especially for portfolio type WordPress sites. There could text that appears when an image is hovered to describe the post briefly as well. So many different things could be done with this.
I agree Darryl. My main idea on this is an easy place to mix pix messages (via phone), as well as other photos, designs, graphics and posts. I’ll see what I can do about making one. Not sure how I’m going to get the functions to loop yet keep a single box in place.
Great idea…got the gears turning on that one!
Your solution is so close in IE7…great tutorial! Thanks.
Thats really nice!
pretty cool.
i’ve been using this technique on one of my lifestyle websites:
http://iliketheweekend.com/
one thing to note is on the img style, if you add any positioning such as relative or whatever, safari has a weird bug which will break the css3 column layout.
AWSUM!! Wall to wall kittens by power of pure CSS. The day just can’t get better! ;-) Good work.
Another idea for non-CSS fallback would be to use the attribute ‘align=”absmiddle”‘ on the img tags. This would line up the image centers horizontally.
Nice CSS only Solution.
Nice. It’s useful CSS .
Very Nice! I will have to give this one a try, much nicer (and cleaner) than one (not by you) I have used in the past. Thanks!
Very very cool!
Hey, Chris!
That’s an excellent use for the “Masonry” style! And to see you use my column-count technique to do it is about the greatest confirmation that it was a good idea that I could have hoped for.
Cheers and thanks!
P.S.: +1 on the “make this a WordPress plugin” idea.
Great Article, gotta love the Ghost Busters Quote put in there.
Nifty. It’s nice to see CSS techniques getting applied to solve problems that aren’t always obvious.
I’m a big fan of keeping HTML markup super simple, and CSS3 allows us to do some fantastic stuff without cluttering the markup.
Keep up the good work!
Wow! I really love this site. You all offer some good information. I love your use of kittens too. I am a Tucson web designer, so this is all super useful for me. Keep up the good work. I’ll be checking in regularly to get more tips and hints. Thanks.
That’s a really nice solution to an age-old problem. Very useful.
Instead of doing CSS3, couldn’t you have left them inline-block and done vertical-align top? And you could’ve removed the white space between them by setting font-size to 0?
I don’t want to be beating a dead horse, but the download still has the mistake of the section id=’people’ instead of section id=’photos’.
Great tut! I have been looking for this for a long time! And pure CSS!
There’s a placedog.com? awesome!
Hey Chris, love this idea.
I’m trying to implement a version of this technique on my site but I think I’m running into a few issues with how webkit handles columns?
I have 6 images / 6 columns at high resolutions and 6 images / 3 columns at lower resolutions. It behaves as expected in Firefox but not in Chrome or Safari. When you return to the higher resolutions it remains at 3 columns?
If anyone could take a quick look it would be greatly appreciated – http://jsfiddle.net/Pa7mU/2/
Thanks
The same happened to me. It’s webkit issue, it handles css3 stuff differently usually. I’m trying to find a solution to make it look better, but ineffectually yet… Have you solved this problem?
As far as I saw, some kind of bug also appears, if you declare line-height, and works pretty fine without this. Sort of.
@Janos – I basically gave up trying to find a fix for this using just CSS and ended up using jQuery Masonry instead.
What a neat technique, thanks!
But something grabbed me in your PHP at the end:
if ($i % 2 == 1) {
You can of course omit the ‘== 1’ since PHP treats 1 as true and 0 as false. Might seem petty but I think it’s a little more elegant:
Great stuff!
I’m having a pesky problem with adding some captions though, and I’m wondering if anyone can help.
Here’s the test page: http://souchi.com/pages/celebrity3 As you can see, the text that ends up at the bottom of the longest column won’t stay at the bottom of that column. It wants to wrap to the top of the next column.
My html look like this:
and my CSS looks like this:
Anyone know the solution for getting that caption to stick with the image? Cheers.
By the way, hey Chris! You could use
column-width
and remove the media queries completely… Here’s a demo: http://jsfiddle.net/tovic/nX9NT/1/embedded/result%2Chtml%2Ccss/Hey Chris, thanks for the genius-ly simple code, took me hours and hours to make work on iphone though; i finally discovered the head must contain meta name=”viewport” content=”width=device-width,initial-scale=1.0″ otherwise the phone sticks think its resolution is in between 800px and 1000px (3 columns, 2 images wide). your code worked on http://iphonetester.com/ and i could re-size my laptop chrome screen and watch it downsize nicely but iphone it was broken… so I think you should add the all important viewport line to your download :)
a question, can you make the images load across the rows instead of down the columns? In a five column screen i want the story to go left to right down through the rows…
What is lost when you change the column gap from 0 to something larger? 1px, 2px? I love the effect, but would love the option of a little spacing between images. Tried 1px gap in Firefox and looks okay. Does it affect mobile/responsiveness? Thanks!
Take a look to this site Im finishing now:
http://www.moopio.com/pictures.php?id=439441916098422&page=1
Using Bootstrap + Masonry + Inifnite Scroll Plugin
Greets!
Nice technique. Placedog.com appears to have expired and been bought by a speculator so the dog images are not showing in the demo. Maybe it’s time to go all-out cats?
Fixed with all cats for now, thanks!
As usual when visiting your website i’am impressed of the capabilities of a simple css propriety. You are really awesome, I love your site !! Thank you for sharing so interesting knowledge and tricks!