CSS Grid is a fantastic new feature in CSS supported by all modern browsers (partial support in IE at the time of writing this) since March of this year.
Creating a grid is now as simple as declaring display
property of the parent container element as grid
.
The number of columns can be set in terms of fr
, which stands for a fraction of the available space. For example, for a 3-column grid we set grid-template-columns: 1fr 1fr 1fr
.
Want a 40px gap between the grid items? Simple. Just add grid-gap: 40px
.
In this tutorial, we are going to
- create a template part named `loop-archive.php` having the PHP to remove all hooks from the default Genesis loop actions, then add featured image, post title and entry meta in the loop, wrap all the posts in a div.articles so it can be declared as the grid.
- load the above template part inside `home.php` (for the Posts page) and `archive.php` (for all other archives).
- add the needed CSS including Flexbox fallback for non-supported browsers.
While the tutorial has been written for Genesis Sample, it should work with a few adjustments in any Genesis theme
Step 0 – Preparation
a) Let’s set 12 posts to be shown at Settings > Reading.
b) At Genesis > Theme Settings > Content Archives, include the featured image.
c) Create an empty Page titled say, Blog
and set it as the Posts page at Settings > Reading. Do NOT apply Blog Page Template.
Step 1 – The template part
Create a file named say, loop-archive.php
in the child theme directory having the following:
<?php
add_filter( 'body_class', 'custom_body_class' );
/**
* Add `content-archive` class to the body element.
*
* @param array $classes the current body classes
* @return array $classes modified classes
*/
function custom_body_class( $classes ) {
$classes[] = 'content-archive';
return $classes;
}
// Force full width content.
add_filter( 'genesis_pre_get_option_site_layout', '__genesis_return_full_width_content' );
// Add opening div.articles tag before the latest post.
add_action( 'genesis_before_entry', function () {
global $wp_query;
if ( 0 === $wp_query->current_post && is_main_query() ) {
echo '<div class="articles">';
}
} );
// Remove all hooks from genesis_entry_header, genesis_entry_content and genesis_entry_footer actions.
$hooks = array(
'genesis_entry_header',
'genesis_entry_content',
'genesis_entry_footer',
);
foreach( $hooks as $hook ) {
remove_all_actions( $hook );
}
// Add featured image inside entry header.
add_action( 'genesis_entry_header', 'genesis_entry_header_markup_open' );
add_action( 'genesis_entry_header', 'genesis_do_post_image' );
add_action( 'genesis_entry_header', 'genesis_entry_header_markup_close' );
// Add entry title and entry meta in entry content.
add_action( 'genesis_entry_content', 'genesis_do_post_title' );
add_action( 'genesis_entry_content', 'genesis_post_meta' );
add_filter( 'genesis_post_meta', 'custom_post_meta_filter' );
/**
* Customize entry meta.
* @param string $post_meta Existing entry meta
* @return string Modified entry meta
*/
function custom_post_meta_filter( $post_meta ) {
$post_meta = '[post_categories before=""]';
return $post_meta;
}
// Move .archive-pagination from under main.content to adjacent to it.
remove_action( 'genesis_after_endwhile', 'genesis_posts_nav' );
add_action( 'genesis_after_content', 'genesis_posts_nav' );
// Add closing div tag (for .articles) after the last post.
add_action( 'genesis_after_endwhile', function () {
if ( is_main_query() ) {
echo '</div>';
}
} );
If you want content to be displayed, add
add_action( 'genesis_entry_content', 'genesis_do_post_content' );
below
add_action( 'genesis_entry_content', 'genesis_do_post_title' );
Step 2 – Load the template part
Create files named home.php
and archive.php
in the child theme directory having the following:
<?php
get_template_part( 'loop', 'archive' );
genesis();
Step 3 – CSS
Add the following in child theme’s style.css:
.content-archive .content {
float: none;
}
.articles {
display: -ms-grid;
display: grid;
-ms-grid-columns: 1fr 1fr 1fr;
grid-gap: 40px;
grid-template-columns: 1fr 1fr 1fr;
}
.content-archive .content .entry {
margin-bottom: 0;
padding: 0;
border-radius: 3px;
-webkit-box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
}
.content-archive .content .entry-content {
padding: 20px;
}
.content-archive .content a.entry-image-link img {
margin-bottom: 0;
vertical-align: top;
}
.content-archive .content .entry-title {
font-size: 18px;
}
.content-archive .content p.entry-meta {
font-size: 14px;
font-size: 1.4rem;
}
.content-archive .content .entry-meta a {
color: #333;
text-decoration: none;
}
.content-archive .content .entry-meta a:hover {
color: #c3251d;
}
@media only screen and (max-width: 1023px) {
.articles {
-ms-grid-columns: 1fr 1fr;
grid-template-columns: 1fr 1fr;
}
}
@media only screen and (max-width: 500px) {
.articles {
-ms-grid-columns: 1fr;
grid-template-columns: 1fr;
}
}
A shortcut for grid-template-columns: 1fr 1fr 1fr
is grid-template-columns: repeat(3, 1fr)
. So for a 4-column grid, you could use grid-template-columns: repeat(4, 1fr)
.
Step 4 – Flexbox fallback
We can use display: flex
before display: grid
as the supporting browsers will override the flex declaration with the grid. Then in a feature query (like media query, but used to test for supporting features) un-set the width/margin etc. values used for the Flexbox fallback in Grid supporting browsers.
In the CSS added earlier, change
.articles {
display: -ms-grid;
display: grid;
-ms-grid-columns: 1fr 1fr 1fr;
grid-gap: 40px;
grid-template-columns: 1fr 1fr 1fr;
}
.content-archive .content .entry {
margin-bottom: 0;
padding: 0;
border-radius: 3px;
-webkit-box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
}
to
.articles {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
display: -ms-grid;
display: grid;
-ms-grid-columns: 1fr 1fr 1fr;
grid-gap: 40px;
grid-template-columns: 1fr 1fr 1fr;
}
.content-archive .content .entry {
margin-bottom: 0;
padding: 0;
border-radius: 3px;
-webkit-box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.2);
width: 31.25%; /* http://d.pr/i/sVsJRM */
margin-bottom: 3.125%;
}
.content-archive .content .entry:last-child {
margin-right: auto;
margin-left: 3.125%;
}
@supports ((display: -ms-grid) or (display: grid)) {
.content-archive .content .entry {
width: auto;
margin-bottom: 0;
}
.content-archive .content .entry:last-child {
margin-right: 0;
margin-left: 0;
}
}
and
@media only screen and (max-width: 1023px) {
.articles {
-ms-grid-columns: 1fr 1fr;
grid-template-columns: 1fr 1fr;
}
}
@media only screen and (max-width: 500px) {
.articles {
-ms-grid-columns: 1fr;
grid-template-columns: 1fr;
}
}
to
@media only screen and (max-width: 1023px) {
.articles {
-ms-grid-columns: 1fr 1fr;
grid-template-columns: 1fr 1fr;
}
.content-archive .content .entry {
width: 47.5%; /* http://d.pr/i/zHWeyP */
margin-bottom: 5%;
}
.content-archive .content .entry:last-child {
margin-left: 5%;
}
@supports ((display: -ms-grid) or (display: grid)) {
.content-archive .content .entry {
width: auto;
margin-bottom: 0;
}
.content-archive .content .entry:last-child {
margin-left: 0;
}
}
}
@media only screen and (max-width: 500px) {
.articles {
flex-direction: column;
-ms-grid-columns: 1fr;
grid-template-columns: 1fr;
}
.content-archive .content .entry {
width: 100%; /* http://d.pr/i/zHWeyP */
}
.content-archive .content .entry:last-child {
margin-left: 0;
}
}
That’s it!
Two excellent resources on CSS Grid are http://gridbyexample.com/ and https://css-tricks.com/snippets/css/complete-guide-grid/.
References:
[…] Posts Grid in Genesis using CSS Grid tutorial can be used to arrange the posts on all archives incl. author archives in a grid. This tutorial provides the steps to create a custom intro area that appears above the list of posts on author archives in Genesis showing info pertaining to the author of posts on that page. […]
[…] Sridhar Katakam wrote a tutorial on creating posts grid in Genesis using CSS Grid […]
[…] Rachel Andrew's Grid By Example A Complete Guide to Grid Posts Grid in Genesis using CSS Grid by Sridhar Katakam […]
Would it be possible to use CSS grid to display the posts like: first one full width, second row 3 col, third row 2 col, fourth row full width again, fifth row 3 or 4 col, etc… For example, similar to the http://demo.ghost.io
This is a good question. I too would also know if that is possible. thanks
Yes, that’s possible.
Have the loop add a numbered id to each post. Then in your Grid CSS control how each of those items will start, stop, and span.
Awesome Tutorial!
Thanks for your amazing work.
I had a question that I hope you could answer.
Using the same template, how could I isolate the newest post and display it above the grid? And then offsetting the grid posts by 1 so there are no duplicates?
Any direction you can point me in would be greatly appreciated!
Would love this option as well!
Made the changes on my website but when I use the inspect element within Firefox it doesn’t detect CSS Grid in use…
Hello, Sridhar Katakam,
This is an awesome tutorial. It works like a charm.
However, I need the primary sidebar to be displayed. How could I do that?
Thank so much
Jack
Thank you, Sridhar, a great tutorial and exactly what a non-codey person like myself needed. Much appreciated.
How can i add the Date and Author after the content?
[…] Sridhar Katakam wrote a tutorial on creating posts grid in Genesis using CSS Grid […]
Can you help me see what I did wrong using this in Business Pro? http://test.sharonhujik.com/category/classical-conversations-cycle-1/
Try adding
overflow: hidden;
for.content-archive .content .entry
.Perfecto! Thank you as always!!
I’d love to be able to use a sidebar with a two grid column, is there a way to achieve that?
Cheers and thanks for great info.
Removing
from the code in Step 1 will result in your content archives where the template is applied using the default layout.
After that, you need to edit the CSS for 2 columns.
Thanks so much Sridhar, really appreciate your help.
Dave
I’ve applied everything from your tutorial, the grid layout is indeed shown up, but it is simple. See the following URL.
https://www.seotimur.com/
What should I do to make it just like in your screenshot demo?
Thank you very much.
Hi,
Can you add any custom content, either above or below the grid to this?
Thanks!
Hi want to use post grid under each Blog category https://www.usefulinfolab.com/
Could please help me out….I was reading this article… I had confusion at one point; Create an empty Page titled say, Blog and set it as the Posts page at Settings > Reading. Do NOT apply Blog Page Template……………Why do we need this?