Genesis Grid Loop Advanced Revamped Genesis tutorial from Bill Erickson and Gary Jones

This post is an update to a previous post on the Genesis Grid Loop.

That previous post had some shortcomings, especially concerning the number of grid posts and the number of posts as set in Settings -> Reading. If they didn’t match, then WordPress would declare one or more pages at the end of the pagination for those query of posts as being a 404 Not Found. We needed a better solution, and between legendary Genesis developer Bill Erickson and myself, we’ve come up with one.

The Code

Here’s some starting code that you can customise. More explanation is given below the code.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
<?php
 
/**
* Possibly amend the loop.
*
* Specify the conditions under which the grid loop should be used.
*
* @author Bill Erickson
* @author Gary Jones
* @link http://code.garyjones.co.uk/genesis-grid-loop-advanced/
*
* @return boolean Return true of doing the grid loop, false if not.
*/
function child_is_doing_grid_loop() {
 
// Amend this conditional to pick where this grid looping occurs.
// This says to use the grid loop everywhere except single posts,
// single pages and single attachments.
return ( ! is_singular() );
 
}
 
/**
* Grid Loop Arguments
*
* Specify all the desired grid loop and query arguments
*
* @author Bill Erickson
* @author Gary Jones
* @link http://code.garyjones.co.uk/genesis-grid-loop-advanced/
*
* @return array $arguments
*/
function child_grid_loop_arguments() {
 
$grid_args = array(
'features' => 1,
'feature_content_limit' => 0,
'feature_image_size' => 0,
'feature_image_class' => 'alignleft post-image',
'grid_content_limit' => 0,
'grid_image_size' => 'grid-thumbnail',
'grid_image_class' => 'alignleft post-image',
'more' => __( 'Continue reading &#x2192;', 'genesis' ),
);
 
$query_args = array(
'posts_per_page' => 6,
);
 
return array(
'grid_args' => $grid_args,
'query_args' => $query_args,
);
}
 
add_action( 'genesis_before_loop', 'child_prepare_grid_loop' );
/**
* Prepare Grid Loop.
*
* Swap out the standard loop with the grid and apply classes.
*
* @author Gary Jones
* @author Bill Erickson
* @link http://code.garyjones.co.uk/genesis-grid-loop-advanced/
*/
function child_prepare_grid_loop() {
 
if ( child_is_doing_grid_loop() ) {
// Remove the standard loop
remove_action( 'genesis_loop', 'genesis_do_loop' );
// Use the prepared grid loop
add_action( 'genesis_loop', 'child_do_grid_loop' );
// Add some extra post classes to the grid loop so we can style the columns
add_filter( 'genesis_grid_loop_post_class', 'child_grid_loop_post_class' );
}
}
 
add_action( 'pre_get_posts', 'child_grid_query' );
/**
* Grid query to get the posts that will appear in the grid.
*
* Any changes to the actual query (posts per page, category…) should be here.
*
* @author Bill Erickson
* @author Gary Jones
* @link http://code.garyjones.co.uk/genesis-grid-loop-advanced/
*
* @param WP_Query $query
*/
function child_grid_query( $query ) {
// Only apply to main query, if this matches our grid query conditional, and if it isn't in the back-end
if ( $query->is_main_query() && child_is_doing_grid_loop() && ! is_admin() ) {
 
 
// Get all arguments
$args = child_grid_loop_arguments();
// Don't edit below, this does the logic to figure out how many posts on each page
$posts_per_page = $args['query_args']['posts_per_page'];
$features = $args['grid_args']['features'];
$offset = 0;
$paged = $query->query_vars['paged'];
if ( 0 == $paged )
// If first page, add number of features to grid posts, so balance is maintained
$posts_per_page += $features;
else
// Keep the offset maintained from our page 1 adjustment
$offset = ( $paged - 1 ) * $posts_per_page + $features;
$query->set( 'posts_per_page', $posts_per_page );
$query->set( 'offset', $offset );
}
}
 
/**
* Prepare the grid loop.
*
* Only use grid-specific arguments. All query args should be done in the
* child_grid_query() function.
*
* @author Gary Jones
* @author Bill Erickson
* @link http://code.garyjones.co.uk/genesis-grid-loop-advanced/
*
* @uses genesis_grid_loop() Requires Genesis 1.5
*
* @global WP_Query $wp_query Post query object.
*/
function child_do_grid_loop() {
 
global $wp_query;
 
// Grid specific arguments
$all_args = child_grid_loop_arguments();
$grid_args = $all_args['grid_args'];
 
// Combine with original query
$args = array_merge( $wp_query->query_vars, $grid_args );
 
// Create the Grid Loop
genesis_grid_loop( $args );
 
}
 
/**
* Add some extra body classes to grid posts.
*
* Change the $columns value to alter how many columns wide the grid uses.
*
* @author Gary Jones
* @author Bill Erickson
* @link http://code.garyjones.co.uk/genesis-grid-loop-advanced/
*
* @global array $_genesis_loop_args
* @global integer $loop_counter
*
* @param array $grid_classes
*/
function child_grid_loop_post_class( $grid_classes ) {
 
global $_genesis_loop_args, $loop_counter;
 
// Alter this number to change the number of columns - used to add class names
$columns = 3;
// Be able to convert the number of columns to the class name in Genesis
$fractions = array( '', 'half', 'third', 'fourth', 'fifth', 'sixth' );
 
// Only want extra classes on grid posts, not feature posts
if ( $loop_counter >= $_genesis_loop_args['features'] ) {
// Make a note of which column we're in
$column_number = ( ( $loop_counter - $_genesis_loop_args['features'] ) % $columns ) + 1;
// Add genesis-grid-column-? class to know how many columns across we are
$grid_classes[] = sprintf( 'genesis-grid-column-%d', $column_number );
 
// Add one-* class to make it correct width
$grid_classes[] = sprintf( 'one-' . $fractions[$columns - 1], $columns );
// Add a class to the first column, so we're sure of starting a new row with no padding-left
if ( 1 == $column_number )
$grid_classes[] = 'first';
}
 
return $grid_classes;
 
}
view raw functions.php hosted with ❤ by GitHub

Woah! That’s a ton more code, but it is a more stable solution as a base from which you can customise the how the grid loop works for you. Here’s the breakdown.

Explanation of The Code

child_is_doing_grid_loop()

This first function simply returns true or false. You can use the conditional tags to choose under which situations you want the grid loop to kick in. By default, we want it when it is not a single post (including custom post types), not a single page and not a single attachment. Luckily WordPress has a tag to cover all three of those at once. Every other time we want to use the grid loop.

child_grid_loop_arguments()

The second function is where you’ll want to fine tune how the grid appears. Most of the array values should be intuitively named. If you want to limit a template to show a particular query (i.e., posts from the same category), then you’d amend the $query_args here.

child_prepare_grid_loop()

You shouldn’t really need to touch much in this function. This basically says to swap out the default function for our grid loop function and also amend the post class so we can add some styling later.

child_grid_query()

This amends what the query would have been for this page, with our grid loop and query arguments. After checking that this is the main loop, that we are indeed supposed to be showing the grid loop, and we’re on the front end, then it grabs a copy of our arguments. To allow for featured posts on the first page, and to keep the balance right on pages after the first page, some logic is done, which you probably won’t need to edit. The result of this logic is then set on the main query.

child_do_grid_loop()

This function gets our grid loop arguments, the query arguments (as potentially amended by the logic in the previous function), and merges them together before sending them all off to Genesis, which does the actual database query, and starts echoing the markup and content for this grid posts.

child_grid_loop_post_class()

The previous version of this tutorial also included some styles to paste into your style.css file, to ensure that the grid posts appeared in the correct columns. We now do a bit more work here, and make use of the column classes that have been included with Genesis child themes since Genesis 1.5 was released. If you find the grid isn’t appearing correctly, copy the Column Classes section of the Genesis style sheet into your own theme style sheet.

Sticky Posts

If you amend the query arguments for a grid on the blog archive page to only include posts from a certain category, tag or taxonomy, and find that sticky posts stop working, add the following code to fix it:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
<?php
 
add_filter( 'posts_results','child_query_is_home' );
/**
* Fixes an issue where a query that targets a taxonomy stops sticky posts from working
* on is_home.
*
* The code suggests that sticky posts should only be on the blog archive (is_home) page.
* However, if that query is amended with an inclusive cat, tag or tax restriction, then
* WP doesn't count the query as being the blog archive page anymore.
*
* In wp-includes/query.php, for each tax query that is not a "NOT IN" operator, the
* relevant is_category, is_tag, or is_tax property is set to true. This in turn means
* that is_archive is set to true, and this means is_home is set to false. Since the
* rearrangements of sticky posts requires is_home to be true, sticky posts aren't
* moved to the top under these circumstances.
*
* This function doesn't actually filter anything, but uses the raw results filter hook
* to jump in and set is_home back to true on the global $wp_query so that sticky posts
* start appearing first again. If you have multiple queries on a page, you may want to
* set conditions under which this tweak is made.
*
* @author Gary Jones
* @link https://gist.github.com/1950278
*
* @global WP_Query $wp_query Posts query object.
*
* @param array $args Raw results array of posts and current WP_Query object.
*
* @return array Original untouched $args.
*/
function child_query_is_home( array $args ) {
global $wp_query;
$wp_query->is_home = true;
return $args;
}
view raw functions.php hosted with ❤ by GitHub

A Better and Easier Grid Loop

It should be noted that the grid loop code above is for when you want to create a second loop on the page, or make use of some custom query loop that won’t produce the same posts as what would naturally have appeared there anyway.

If you do just want to style the existing posts, then take a look at a new tutorial from Bill Erickson, as he explains about a better and easier grid loop.

Comments

  1. Dave Kuhar says:

    Thanks for the code!

    Everything about this is working great, except for assigning the number of posts per page. With ‘posts_per_page’ in query_args, I’m not getting the desired number of posts. Moving that argument to grid_args fixed the problem. Am I doing something wrong here?

    Also, I’m curious about something else. If I want one feature at the top of the page and an even number of posts in two columns below, I’d set posts per page to 5. This works great on the first page of posts, but every subsequent page then has one lonely post at the bottom of the left column. Can this code be altered to determine whether the “home” page of the category is being displayed and adjust the number of posts accordingly?

    • I’ll have to do more testing when I get a chance (absolutely swamped right now). I think the issue might be that Genesis *incorrectly* applies posts_per_page => get_option( ‘posts_per_page’ ) as the default query args, so we’ll need to add it to both. Putting it in the grid_args will ensure those posts are displayed, and putting it in query_args will ensure you don’t get a 404 when trying to load the page.

      For your second question, that logic should already be built into the code above. Let’s say you want 4 grid posts (2 columns with 2 rows) and 1 feature post. You set features to 1 and posts_per_page to 4.

      • Bill, thank you for your answer on how to remove a featured post. After two hours of searching articles and forums I’m grateful to have found your article.

  2. Dave Kuhar says:

    Thanks for the reply, Bill (and thank you for everything else you do for the world of Genesis — we make heavy use of your advice).

    I’d thought the logic would do what you’re describing – that is, not count the featured post into the second page of an archive – but it does.

    Rather than try to explain all this here, I did a quick screencast: http://screencast.com/t/6L7me3xnr

    In that video I show you that I get a 404 when I try to display the second set of posts. This video shows what happens when I change the Reading settings from showing at most 20 post to showing no more than 10 posts: http://screencast.com/t/50pWsmUN9

    • Dave Kuhar says:

      So, I set the number of posts to display (in Settings -> Reading) to 1, and it (mostly) works now. I still have the issue with pages 2 through x showing the wrong number of posts. Anyone else see this?

      • Marina says:

        Hi Dave- I have this same issue with the grid loop- it is showing correctly on the homepage of my site when I set the number to 7 (it is showing the first full post and then 6 excerpts underneath) but on the other pages it is showing 7 posts in two columns so it looks off balance. Did you ever find a solution for this? Thank you!

        • Dave Kuhar says:

          Sorry, no I didn’t. I just asked the client to live with it until I can figure it out. Maybe Bill or Gary have come up with something.

          • Helen says:

            Hi Dave and Marina,

            I have the exact same issue with the grid loop…. Have you found a solution for this? I’m working on a site which I will be putting online soon…. Thanks, Helen

          • Dave Kuhar says:

            Hi Helen,

            Unfortunately, no. We’ve ended up using Types & Views for this kind of thing now. In some cases it’s like shooting a raccoon with a bazooka* when a pellet gun would do, but it gets the job done.

            *Note: no wildlife or livestock have been harmed in the building of our websites.

  3. aski says:

    Hi,
    Could you check if 4 columns work?

    I changed the section Alter this number to change the number of columns – used to add class names to:

    $columns = 4;

    But then the grid shows only 1 column. When I set it to 2,3,5 or 6 it does show 2, 3, 5 or 6 columns. But 4 isn’t working.

  4. Thanks for sharing snippet.

    –0–

    Hi @aski:

    I have checked sample theme, there is no ‘one-quarter’ class, it should be ‘.one-fourth’

  5. aski says:

    Thank you palPalani and Gary.

  6. Hi Gary,

    The detailed explanation that you have provided here is simply awesome. Thanks for the help. I have a quick question. I would like to add a few widgets as part of thye grid loop. like say, after the featured section I have two widgets then two blogs of content then widgets again.

    Is this even possible and can you help me figure this out.

    • Not easily Eddie. The actual output is left to genesis_grid_loop() which does the actual looping through each post. You’d have to roll your own eddie_custom_grid_loop() where you took genesis_grid_loop() as the starting point, and then tweaked it to output widget areas after a certain number of posts, and finally amending the code above to call your grid loop function instead of the one in Genesis.

  7. Amy Kvistad says:

    Thanks for your Genesis grid code and explanation.
    I had the Genesis grid working but would like to have 3 or more columns instead of just 2. I put your code in the child functions.php file and plan to have the grid on a page template so I modified the following to the template name.
    return ( is_page_template(‘portfolio-place.php’) );

    I am getting this: Sorry, no posts matched your criteria. (I am working locally so I can’t post a link.)

    Any help is appreciated. Thanks!

  8. Amy Kvistad says:

    Just when you ask for help you figure it out! I used the regular genesis code from the studiopress.com site and added classes to it for styling on the page template. I modified ‘more’ to remove it, added ‘cat’ to display only certain categories, removed the image after the title and added it above, and removed the post meta and post info.

    0,
    ‘feature_image_size’ => 0,
    ‘feature_image_class’ => ‘alignleft post-image’,
    ‘feature_content_limit’ => 0,
    ‘grid_image_size’ => 0,
    ‘grid_image_class’ => 0,
    ‘grid_content_limit’ => 0,
    ‘more’ => ”,
    ‘posts_per_page’ => 9,
    ‘cat’ => ‘3,7,8,11,13,14,15,22’
    ) );
    } else {
    genesis_standard_loop();
    }
    }

    function child_grid_loop_image() {
    if ( in_array( ‘genesis-grid’, get_post_class() ) ) {
    global $post;
    echo ”.get_the_post_thumbnail($post->ID, ‘child_thumbnail’).”;
    }
    }

    /** Remove the post info and meta from grid loop **/
    remove_action( ‘genesis_before_post_content’, ‘genesis_post_info’ );
    remove_action( ‘genesis_after_post_content’, ‘genesis_post_meta’ );
    add_action(‘genesis_before_post_title’, ‘child_grid_loop_image’);

    // Add some extra post classes to the grid loop so we can style the columns
    add_filter( ‘genesis_grid_loop_post_class’, ‘child_grid_loop_post_class’ );

    /** Add column classes to style **/
    function child_grid_loop_post_class( $grid_classes ) {

    global $_genesis_loop_args, $loop_counter;

    // Alter this number to change the number of columns – used to add class names
    $columns = 3;

    // Be able to convert the number of columns to the class name in Genesis
    $fractions = array( ”, ‘half’, ‘third’, ‘fourth’, ‘fifth’, ‘sixth’ );

    // Only want extra classes on grid posts, not feature posts
    if ( $loop_counter >= $_genesis_loop_args['features'] ) {
    // Make a note of which column we’re in
    $column_number = ( ( $loop_counter – $_genesis_loop_args['features'] ) % $columns ) + 1;

    // Add genesis-grid-column-? class to know how many columns across we are
    $grid_classes[] = sprintf( ‘genesis-grid-column-%d’, $column_number );

    // Add one-* class to make it correct width
    $grid_classes[] = sprintf( ‘one-‘ . $fractions[$columns - 1], $columns );

    // Add a class to the first column, so we’re sure of starting a new row with no padding-left
    if ( 1 == $column_number )
    $grid_classes[] = ‘first';
    }

    return $grid_classes;

    }

    genesis();

    Then in the style.css file I added the following code and removed the odd and even code. It is not pretty yet but it is working!

    /* Portfolio grid
    ———————————————————— */
    #content .genesis-grid {
    float: left;
    margin: 0;
    border: 1px #fff solid;
    background: #e1e1e1;
    min-height: 450px;
    padding: 15px 0 10px 3%;
    }
    #content .genesis-grid-column-1 {
    clear:left;
    padding-left: 0;
    }
    .size1of2 {
    width: 48%;
    }
    .size1of3 {
    width: 31%;
    }
    .size1of4 {
    width: 22.5%;
    }
    .size1of5 {
    width: 17.4%;
    }
    .size1of6 {
    width: 14%;
    }
    /* Above widths assume 0 left padding on the first column, 3% left padding on all
    subsequent columns, and a total sum of 99% to avoid browser rounding errors */

    I would like to adjust the responsive design to drop from 3 columns to 2 and then to 1 instead of dropping from 3 to 1. It may not look good on a tablet as is.

  9. Great article. I am attempting to apply this to the idea of creating a page that lists a set of child pages (of that page) with excerpts and stumped as to what to do to make that happen.

    I can’t seem to get it to display anything except posts… how do you modify this code to make it work for pages displaying children and children excerpts?

    Thanks
    Chris

    • You would just need different query args, with results that had a parent ID the same as the current post (Page) ID. See the codex on WP_Query to know what query args are available.

  10. Anton says:

    Would there be a way to add a widget inside of the grid loop? I am trying to have the first post go 100% width, then have a widget with social icons and a subscribe button go 100% and then have 4 more posts in a grid going 50% each. Hopefully that makes sense :)

    I know that I can add a widget above or below the grid using this tutorial: http://www.briangardner.com/home-widget-area-eleven40/ but it does not help me to add a widget area between posts 1 and 2.

    Thanks!

    • You can do something close to Brian’s tutorial, but hook into genesis_after_post. You’ll need a conditional and check against a global – I *think* Genesis has one called $loop_counter, but I’m pretty sure there’s a WP global one too.

  11. Bruce Munson says:

    Thanks Gary and Bill for all you do for the Genesis and WP community. This was very helpful, and very well explained. :)

  12. A. Tate says:

    I have a grid loop that has 4 featured posts (that I make semi-static with sticky posts) and then 6 normal recent posts. First, I would like to only display the post title and featured post image on every featured post in the grid loop, but would like the remaining recent posts of the grid loop as default. Secondly, I would like to add an html wrapper around the first two featured posts and the last two featured posts (I would prefer to avoid javascript). Is there a way to do this? Any help would be wonderful and well appreciated.

  13. Thien says:

    Hi Gary,

    I have a question: How can i styling with css code in genesis grid loop, i can add element into column by use “#content .genesis-grid-column-1 {” with column 1 and “#content .genesis-grid-column-2 {” with column 2, so i can add some style like background-color, shadow, font-size …. but the problem is i can’t change contain in features post grid area (i created page with 2 column and 1 post featured on front), beacause i don’t know what class base on “features”, i think.
    Please help me solve this problem.

    Thank you Gary.

  14. Gary,
    How would I modify code to use in a page template?
    David

  15. Mike says:

    Thanks for the code! It’s working great so far.

    One question: How can I target my post classes when using add_action and remove_action?
    For instance, let’s say I want my featured post to have an excerpt, but I want my grid posts to hide the excerpt.

    Thanks,
    – Mike

  16. thanks alot Gary, i have had series of issues regarding my sticky post in the genesis eleven40 child themes, but this post had just solved the problem.

  17. Thank you Gary. I’m trying to add a new query arg to the main query but I’m not sure where to put it. Can you help? Thank you!

  18. Nevermind – this is exactly what I was looking for! Thank you.

  19. I cannot get this to work – the query args just aren’t ‘taking’. The other grid args are working fine. The grid is showing up. The only thing that is NOT working are the query args. Posts per page, orderby, and order. I’m using this in an archive page… if that makes any difference?

    • This part seems to take into account the grid args only? Not the query_args?

      function child_do_grid_loop() {
       
      	global $wp_query;
       
      	// Grid specific arguments
      	$all_args = child_grid_loop_arguments();
      	$grid_args = $all_args['grid_args'];
       
      	// Combine with original query
      	$args = array_merge( $wp_query->query_vars, $grid_args );
       
      	// Create the Grid Loop
      	genesis_grid_loop( $args );
       
      }
  20. In my Genesis Theme Settings, I have asked it to exclude a specific category ID from showing on the blog template. However, this code doesn’t seem to respect that. I’m trying to figure out how I add a !in_category query to the child_grid_query. Thanks for your help!!

  21. Sadly not working for me…

  22. Gary, do you know how to remove inner-site, and content-sidebar-wrap from a template? I’ve removed every other div on the page. I just want a blank canvas for starting point on all of my landing pages.

  23. Hello Gary,
    thanks a lot for this work.
    I’m trying to integrate this code into my site, using it for the archive of post+thumbnails.
    I’ve used the plugin, but as I need two separate loops in my site, and the ability to stylize the grid, this option falls short.

    As a non programmer, I find that very very hard to do and I guess if it would be possible for you to explain the process point by point.
    Ideally with a screencast !

    Sorry to bother, but I think this is something many people would appreciate.

    Thanks a lot!
    fosco lucarelli

Trackbacks

  1. [...] I love the Grid Loop setup that Gary and Bill did here. However, both Gary and Bill admit that there are other better options than using the [...]

  2. [...] Advanced Genesis Grid Loop Tutorial [...]

Speak Your Mind

*