{"id":13372,"date":"2011-07-24T19:18:17","date_gmt":"2011-07-25T02:18:17","guid":{"rendered":"http:\/\/css-tricks.com\/?p=13372"},"modified":"2018-02-19T17:04:21","modified_gmt":"2018-02-20T00:04:21","slug":"seamless-responsive-photo-grid","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/seamless-responsive-photo-grid\/","title":{"rendered":"Seamless Responsive Photo Grid"},"content":{"rendered":"

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:<\/p>\n

Nice and seamless<\/figcaption><\/figure>\n

Ideally we keep it pretty chill on the markup, like:<\/p>\n

<section id=\"photos\">\r\n  <img src=\"images\/cat-1.jpg\" alt=\"Cute cat\">\r\n  <img src=\"images\/cat-2.jpg\" alt=\"Serious cat\">\r\n  ...\r\n<\/section><\/code><\/pre>\n

Without any CSS at all, the images will line up in a row since they are essentially inline-block:<\/p>\n

Rivers of whitespace<\/figure>\n

But that’s not quite what we want. Your mind might go right to some JavaScript solution. Possibly the super cool Masonry<\/a> 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).<\/p>\n

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.<\/p>\n

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<\/strong>, where the vertical columns are made through the CSS3 property column-count<\/a><\/code>. Yeah, literally, the thing where you can set text in narrow columns automatically.<\/p>\n

\"\" <\/p>\n

So as long as the parent with the multiple columns is as wide as the browser window (default) and the column-gap<\/a><\/code> 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.<\/p>\n

Here’s the CSS: <\/p>\n

#photos {\r\n  \/* Prevent vertical gaps *\/\r\n  line-height: 0;\r\n   \r\n  -webkit-column-count: 5;\r\n  -webkit-column-gap:   0px;\r\n  -moz-column-count:    5;\r\n  -moz-column-gap:      0px;\r\n  column-count:         5;\r\n  column-gap:           0px;  \r\n}\r\n\r\n#photos img {\r\n  \/* Just in case there are inline attributes *\/\r\n  width: 100% !important;\r\n  height: auto !important;\r\n}<\/code><\/pre>\n

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.<\/p>\n

@media (max-width: 1200px) {\r\n  #photos {\r\n  -moz-column-count:    4;\r\n  -webkit-column-count: 4;\r\n  column-count:         4;\r\n  }\r\n}\r\n@media (max-width: 1000px) {\r\n  #photos {\r\n  -moz-column-count:    3;\r\n  -webkit-column-count: 3;\r\n  column-count:         3;\r\n  }\r\n}\r\n@media (max-width: 800px) {\r\n  #photos {\r\n  -moz-column-count:    2;\r\n  -webkit-column-count: 2;\r\n  column-count:         2;\r\n  }\r\n}\r\n@media (max-width: 400px) {\r\n  #photos {\r\n  -moz-column-count:    1;\r\n  -webkit-column-count: 1;\r\n  column-count:         1;\r\n  }\r\n}<\/code><\/pre>\n

Fannnnnncy.<\/p>\n

Demo<\/h3>\n

See the Pen Seamless Responsive Photo Grid<\/a> by CSS-Tricks (@css-tricks<\/a>) on CodePen<\/a>.<\/p>\n

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. <\/p>\n

What about, you know.<\/h3>\n

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. <\/p>\n

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<\/a> (Modernizr can test for it as csscolumns<\/code>) to load up jQuery Masonry<\/a> 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.<\/p>\n

Super cute cats!!<\/h3>\n

Totally. They are from LoremPixel<\/a>. For the demo we grabbed photos in random sizes with jQuery:<\/p>\n

function getRandomSize(min, max) {\r\n  return Math.round(Math.random() * (max - min) + min);\r\n}\r\n\r\nfor (var i = 0; i < 25; i++) {\r\n  var width = getRandomSize(200, 400);\r\n  var height =  getRandomSize(200, 400);\r\n  $('#photos').append('<img src=\"\/\/www.lorempixel.com\/'+width+'\/'+height+'\/cats\" alt=\"pretty kitty\">');\r\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"

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.<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[1382,686,586],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":315873,"url":"https:\/\/css-tricks.com\/how-to-guide-for-creating-edge-to-edge-color-bars-that-work-with-a-grid\/","url_meta":{"origin":13372,"position":0},"title":"How-to guide for creating edge-to-edge color bars that work with a grid","date":"July 1, 2020","format":false,"excerpt":"Hard-stop gradients are one of my favorite CSS tricks. Here, Marcel Moreau combines that idea with CSS grid to solve an issue that's otherwise a pain in the butt. Say you have like a 300px right sidebar on a desktop layout with a unique background color. Easy enough. But then\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/06\/grid-rows.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":302363,"url":"https:\/\/css-tricks.com\/full-width-elements-by-using-edge-to-edge-grid\/","url_meta":{"origin":13372,"position":1},"title":"Full-Width Elements By Using Edge-to-Edge Grid","date":"February 6, 2020","format":false,"excerpt":"If you have a limited-width container, say a centered column of text, \"breaking out\" of that to make a full-width element involves trickery. Perhaps the best trick is the one with left relative positioning and a negative left viewport-based margin. While it has its caveats (e.g. requiring hidden overflow on\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/01\/grid-sketch-r3.jpg?fit=1200%2C675&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":317422,"url":"https:\/\/css-tricks.com\/a-lightweight-masonry-solution\/","url_meta":{"origin":13372,"position":2},"title":"A Lightweight Masonry Solution","date":"August 3, 2020","format":false,"excerpt":"Back in May, I learned about Firefox adding masonry to CSS grid. Masonry layouts are something I've been wanting to do on my own from scratch for a very long time, but have never known where to start. So, naturally, I checked the demo and then I had a lightbulb\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/05\/bricks-with-gaps.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":313231,"url":"https:\/\/css-tricks.com\/patternico\/","url_meta":{"origin":13372,"position":3},"title":"Patternico","date":"June 20, 2020","format":false,"excerpt":"I remember searching for tutorials for making seamless patterns in Photoshop\u00b9 all the time back in the day. It's fun to see this little website for building repeating patterns as its one job. It does everything you'd expect: pick a background, drag some decorations onto it and position them (overlapping\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-06-20-at-6.49.16-AM.png?fit=1200%2C895&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":372396,"url":"https:\/\/css-tricks.com\/css-grid-and-custom-shapes-part-2\/","url_meta":{"origin":13372,"position":4},"title":"CSS Grid and Custom Shapes, Part 2","date":"August 22, 2022","format":false,"excerpt":"Alright, so the last time we checked in, we were using CSS Grid and combining them with CSS clip-path and mask techniques to create grids with fancy shapes. Here's just one of the fantastic grids we made together: CodePen Embed Fallback CSS Grid and Custom Shapes series Part 1Part 2\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2022\/08\/zig-zag-panel.png?fit=1104%2C492&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":323307,"url":"https:\/\/css-tricks.com\/full-bleed\/","url_meta":{"origin":13372,"position":5},"title":"Full Bleed","date":"October 15, 2020","format":false,"excerpt":"We've covered techniques before for when you want a full-width element within a constrained-width column, like an edge-to-edge image within a narrower column of text. There are loads of techniques. Perhaps my favorite is this little utility class: .full-width { width: 100vw; position: relative; left: 50%; right: 50%; margin-left: -50vw;\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/10\/full-bleed-breakout.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"featured_media_src_url":null,"_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/13372"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=13372"}],"version-history":[{"count":13,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/13372\/revisions"}],"predecessor-version":[{"id":267264,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/13372\/revisions\/267264"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=13372"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=13372"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=13372"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}