Using CSS Grid Layout for blog post listings
Yesterday, I re-read some articles and a codepen about CSS Grid Layout (for example, grid listing of boxes and auto-placement) and recoded part of my site to use more grid. Specifically, my blog page which has a conventional list of posts in date order.
Update 7-May-2018: This post describes what I did with CSS Grid in April 2017. Since then, I’ve changed back to a flexbox layout because, with more posts, CSS Grid and grid-auto-flow: dense;
wasn’t working as well as I expected.
Site structure
I started this work by thinking that I should create a grid for my overall site structure. So, I added display:grid
to my .wrapper
div. But, do I actually need grid when the child elements, i.e <header>
and the .content
area, aren’t forming a grid? No, I don’t. At the moment, the site is simple and there’s no grid needed for the overall site structure. That may change, of course.
Blog post listings
For the blog page, at the outset I used CSS Flexbox as follows:
The HTML is:
<ul class="hfeed listing">
<li class="hentry">Post content here</li>
... more list items ...
</ul>
…. with these CSS flexbox rules:
.listing {
display: flex;
flex-wrap: wrap;
}
.hentry {
flex: 1 1 91.8%;
}
@media (min-width: 600px) {
.hentry {
flex: 1 1 45.9%;
}
}
This means that the posts occupy a single column on smaller screen sizes and two columns at widths greater than 600px.
The Flexbox version is great and works well. But, I want to try Grid Layout so…
I have two types of post (and may add others later), standard posts and posts with a feature image. I want the image posts to take up more space (width) in my layout than the standard posts. I need a way to do that.
I added a post type field to my Perch CMS template so that the feature image posts get a new class, ‘image’, added to the list items. Now, I can style these differently if I wish.
Here’s my Grid Layout CSS:
.listing {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-gap: 1em;
grid-auto-flow: dense;
}
.hentry {
grid-column: auto / span 12;
}
@media (min-width: 600px) {
.hentry {
grid-column: auto / span 4;
}
.hentry.image {
grid-column: auto / span 8;
}
}
There are a couple of things to explain.
I set up display:grid
on <ul class="hfeed listing">
and use grid-template-columns
to specify a grid with 12 columns, each with a width of one fraction unit (fr).
For my .hentry
list items, I’ve used grid-column
with the span keyword to specify that items are 12 columns wide.
And, in my media query for larger screens, I change this to 4 columns for the standard posts and 8 columns, i.e double the width, for the feature image posts.
Filling the grid ‘gaps’
That’s all working great except for one thing. In some situations, there will be two standard posts in a row and they will occupy 8 columns in total leaving a 4 column gap. Whilst, that doesn’t look too bad, I’d rather have no gap. I want the post items to fill the entire grid.
Enter grid-auto-flow: dense;
which will backfill the grid gaps where possible. In my case, it moves a standard post item into a gap in the previous row. This does not change the DOM order of items but only how they are displayed.
- More: Read about auto-placement here
This means that the posts are not displayed in exact chronological order but, to be honest, that’s not a big deal on my site. Here’s the blog page with this implemented.
What about older browsers?
There’s a great article by Rachel Andrew which explains grid fallbacks and overrides. The key thing for me is that flexbox items become grid items when display:grid
is used meaning that I can keep my flexbox rules for browsers that don’t support Grid Layout.
I may need to do more reading about this but that’s my understanding. I’ve tested with Microsoft Edge on Windows 10 and the flexbox layout is used.
- NB: Conversely, on my home page, I stick with flexbox because there are only two items.
Overall
I have learnt a lot from this work. It took me while to figure out a few things with Grid Layout but that’s the best way of learning! There may be more work to do but I’m happy with the result so far.
One final point. Grid Layout is absolutely fantastic! It’s well documented and the implementation is very well thought out. It’s sure to become the most widely used layout method for websites.