17

I'm working on a WordPress site for my band and I'd like to mark every 3rd post on our blog page to have a special class applied to it, anybody have any pointers on how to achieve this? Any help is very very appreciated, thanks! rock n roll.

5 Answers 5

15

My approach. No extra function, no filter. :)

<?php $GLOBALS['wpdb']->current_post = 0; ?>
<div <?php post_class( 0 === ++$GLOBALS['wpdb']->current_post % 3 ? 'third' : '' ); ?>>

Alternative:

<div <?php post_class( 0 === ++$GLOBALS['wpdb']->wpse_post_counter % 3 ? 'third' : '' ); ?>>
4
  • this killed it @toscho! turns out this one worked the best since im using this on a category page and a fn was styling posts everywhere. thanks man, +1. i dont think i have the privs to +1 yet officially.
    – Zoran M
    Mar 9, 2012 at 2:43
  • 1
    Doesn't this actually affect the Globals value (due to the pre-increment operator) and potentially screw up something else that might be depending on the current_post count property? I mean, the likelihood is slim, right, but wouldn't it be safer to just do ( 0 === ( $GLOBALS['wpdb']->current_post + 1 ) % 3 ? 'third' : '' ) ?
    – Tom Auger
    Mar 14, 2012 at 12:59
  • 1
    @TomAuger For some not so obvious reason it doesn’t seem to have any side effect. But from a perspective of elegance – you are right. I added a better example. :)
    – fuxia
    Mar 14, 2012 at 16:49
  • 4
    Notice: Undefined property: wpdb::$current_post in
    – Knott
    Feb 29, 2016 at 10:04
9

As an addition to @helgathevikings answer

Use the post_class() fn without polluting the global namespace

  1. Using static variables inside a class allows the same behavior as having global variables: They stay in place and don't change, unless you don't alter them.
  2. Even better (as @Milo suggested in the comments), take the current post from the DB class.
The Example:
function wpse44845_add_special_post_class( $classes )
{
    // Thanks to @Milo and @TomAuger for the heads-up in the comments
    0 === $GLOBALS['wpdb']->current_post %3 AND $classes[] = 'YOUR CLASS';

    return $classes;
}
add_filter( 'post_class','wpse44845_add_special_post_class' );

Update

We could utilize the current_post property of the global $wp_query object. Let's use an anonymous function, with the use keyword, to pass on the global $wp_query by reference (PHP 5.3+):

add_filter( 'post_class', function( $classes ) use ( &$wp_query )
{
    0 === $wp_query->current_post %3 AND $classes[] = 'YOUR CLASS';

    return $classes;
} );

Further on, we could restrict it to the main loop with a in_the_loop() conditional check.

8
  • 1
    i like it. don't quite understand static variables. one more thing to learn today! Mar 8, 2012 at 15:33
  • 3
    why not just use $wpdb->current_post?
    – Milo
    Mar 8, 2012 at 16:04
  • @Milo Good catch +1
    – kaiser
    Mar 8, 2012 at 16:20
  • thank you dudes so much, really appreciate the help! adding this in right now!
    – Zoran M
    Mar 9, 2012 at 2:11
  • ah this function is badass @kaiser and beautifully simple! turns out i needed something just for a category page. this shall save me later on in life my friend, thanks for learning me something new. +11!
    – Zoran M
    Mar 9, 2012 at 2:49
3

if your theme uses post_class() to generate post classes you could try. i'm not 100% sure how it will handle pagination b/c i don't have enough posts on my local install to test it out

add_filter('post_class','wpa_44845');

global $current_count;

$current_count = 1;

 function wpa_44845( $classes ){

    global $current_count;

    if ($current_count %3 == 0 ) $classes[] = 'special-class';

    $current_count++;

    return $classes;

 }
4
  • Not 100% sure, but I guess you could use a static var instead of a global to keep the namespace clean. Anyway: +1.
    – kaiser
    Mar 8, 2012 at 12:36
  • you mean change both global $current_count to static $current_count? doesn't seem to do anything when i test it. not familiar enough w/ variable scope, though i agree it is better to not pollute the namespace if you can. Mar 8, 2012 at 14:22
  • See the answer below
    – kaiser
    Mar 8, 2012 at 14:39
  • 3
    you could also use $wpdb->current_post without having to create another variable.
    – Milo
    Mar 8, 2012 at 14:49
2
$i = 0;
if ( have_posts ) :
while( have_posts ) :
    the_post();

    $class = 'class="BASIC-CLASS';
    if ( 0 === ( $i % 3 ) )
        $class .= 'YOUR-SPECIAL-CLASS';
    $class .= '"';

    echo "<div {$class}>";
        // do stuff
    echo '</div>';

    $i++;
endwhile;
endif;
1

There are also ways to do this with CSS and javascript.

With CSS3 you target every third post with an nth-child selector.

article.post:nth-child(3n+0)
{
    background-color: #777;
}

Or with jQuery, you could add the CSS class using the same technique.

jQuery(function($) {
    $( "article.post:nth-child(3n+0)" ).addClass("custom-class");
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.