1

Is there a way to count the amount of posts in a CPT and add a different class to 1/3 of said posts?

I am using Masonry for a grid and want two different image sizes displayed randomly. I got all that working but the images aren't aligning perfectly which is why the grid looks off (with gaps in between). I figured if 1/3 of the posts are smaller size it would align better.

So what I want is:

  • Grid with two different image sizes that changes on refresh (so the layout is different with each refresh and the large & small images switch)
  • The loop displays the items randomly

This is my current code:

        <?php
        /**
         * Template Name: Teampagina
         *
         * @link https://codex.wordpress.org/Template_Hierarchy
         *
         * @package Deliciae Design custom
         * @since 1.0.0
         */

        get_header(); ?>

            <div id="primary" <?php astra_primary_class(); ?>>

                <?php astra_primary_content_top(); ?>

                <main id="main" class="site-main team-page" role="main">

                    <header class="entry-header <?php astra_entry_header_class(); ?>">

                        <h1 class="entry-title text-center" itemprop="headline"><?php echo post_type_archive_title(); ?></h1>

                        <form class="quicksearch">
                            <div class="input-group">
                                <input type="text" id="qs-input" placeholder="Zoek op naam">
                                <i class="fa fa-search"></i>
                            </div>
                        </form><!-- quicksearch -->

                    </header><!-- .entry-header -->

                    <?php 
                    $args = array(
                        'orderby' => 'rand',
                        'post_type'  => 'focus_team'
                    );
                    $query = new WP_Query( $args );
                    $count = 0; if ( $query->have_posts() ) : ?>


                    <ul id="team-masonry">
                        <li class="grid-sizer"></li>

                        <?php while ( $query->have_posts() ) : $query->the_post();
        ?>              
                            <li class="grid-item size-<?php echo rand(1,2); ?>">
                                <a href="<?php echo get_post_permalink(); ?>">
                                    <div class="fo--info">
                                        <?php the_post_thumbnail('team_member'); ?>
                                        <div class="fo--overlay">
                                            <div class="table">
                                                <div class="item">
                                                <?php the_title( '<h3 class="entry-title" itemprop="headline">', '</h3>' ); ?>
                                                <p>functie</p>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </a>
                            </li>


                    <?php endwhile; wp_reset_postdata(); ?><!-- reset loop -->

                    </ul>
                <?php endif;?>

                </main><!-- #main -->

                <?php astra_primary_content_bottom(); ?>

            </div><!-- #primary -->

        <?php get_footer(); ?>

        <script>
        (function($){

            var qsRegex; 
            var $container = $('#team-masonry');

            $container.isotope({
                itemSelector: '.grid-item'
            });

            var $grid = $('#team-masonry').isotope({
                resizable: true,
                  // set itemSelector so .grid-sizer is not used in layout
                itemSelector: '.grid-item',
                columnWidth: 300,
                masonry: {
                    columnWidth: '.grid-sizer'
                },
              filter: function() {
                return qsRegex ? $(this).text().match( qsRegex ) : true;
              }
            });

            // layout Isotope after each image loads
            $grid.imagesLoaded().progress( function() {
              $grid.isotope('layout');
            });

            // use value of search field to filter
            var $quicksearch = $('input#qs-input').keyup( debounce( function() {
              qsRegex = new RegExp( $quicksearch.val(), 'gi' );
              $grid.isotope();
            }, 200 ) );


            // debounce so filtering doesn't happen every millisecond
            function debounce( fn, threshold ) {
              var timeout;
              return function debounced() {
                if ( timeout ) {
                  clearTimeout( timeout );
                }
                function delayed() {
                  fn();
                  timeout = null;
                }
                timeout = setTimeout( delayed, threshold || 100 );
              }
            }

        })( jQuery );

        </script>
0

The explanation is in the comments:

<?php

...

if ( $query->have_posts() ) :
    //number of small ones needed = a third of total number of posts
    $numsmallneeded = round($query->post_count / 3);

    ...

    while ( $query->have_posts() ) : $query->the_post();

        //if no more small sizes are needed, use big
        if ( !$numsmallneeded ) $size = 1;
        //if number of small sizes needed = number of remaining posts, use small
        else if ( $numsmallneeded == $query->post_count - $query->current_post) $size = 0;
        //else pick at random
        else $size = rand(0, 1);

        //if small was picked, reduce number of small ones needed by 1
        if ( !$size ) $numsmallneeded--;

    ?>              

        <li class="grid-item size-<?php echo ++$size; /*add 1 before printing*/ ?>">

        ...

    <?php endwhile; wp_reset_postdata(); ?><!-- reset loop -->

                </ul>
<?php endif;?>
  • Great! Thank you so much! Also for the comments! Makes it a lot better to understand. – Naomi Dec 4 '17 at 16:20
  • Inarilo, could you help me again, please? The code works and it looks pretty decent but somehow not everything gets placed perfectly. You can look at the demo here: dev.focusorange.com/team What do you think is wrong? – Naomi Jan 5 '18 at 8:49
  • the number of posts seems to keep changing and the division seems to be more like 1/2 instead of 1/3? (i don't know if that is the issue) – inarilo Jan 5 '18 at 9:20
  • It's 1/3. The number of posts are the same but they are currently adding the photo's which is why it could look off. Just wondering why I'm having gaps between some of the items. This is the full code: gist.github.com/Deliciae/01af42e0433266250c3b9c6fa05bc207 – Naomi Jan 5 '18 at 9:30
  • Would I need to include Packery? When I use Layoutmode, the filter stops working and I can't seem to fix it... Can anyone help??? – Naomi Jan 5 '18 at 10:47
0

The WP_Query class offers both of what you are looking for:

By using $query->post_count you can get the total number of posts in your query.

By using $query->current_post you get the index of current post in the loop.

So, to check if the current post is in the first third of your total posts, you can use:

<?php if ( $query->current_post < floor( $query->post_count / 3 ) ) { echo 'some-class'; } ?>
  • This is really confusing for me. When I added the code it only displayed 3 posts. How do I output the whole loop and add a different class to 1/3 of them? – Naomi Dec 4 '17 at 9:24
  • You should only put your class inside the brackets. I've updated the answer. – Jack Johansson Dec 4 '17 at 9:32
  • I added the code but it only adds the class to the first three posts. I want to add it to one third (33.33%) of the posts. How? – Naomi Dec 4 '17 at 9:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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