0

I need to create masonry grid containing the latest posts. I created a grid based on https://masonry.desandro.com/ - the grid displays correctly.

I am asking for help in creating a wp loop that will display posts in the grid.

This is my grid:

<!-- grid masonry layout -->
<div class="news-wrapper container">
  <div class="grid">
    <div class="grid-sizer"></div>
    <div class="gutter-sizer"></div>
    <div class="grid-item grid-item--width2"></div>
    <div class="grid-item grid-item--height2"></div>
    <div class="grid-item grid-item--width2"></div>
    <div class="grid-item"></div>
    <div class="grid-item grid-item--width2"></div>
    <div class="grid-item grid-item--width2"></div>
    <div class="grid-item grid-item--height2"></div>
    <div class="grid-item grid-item--height2"></div>
    <div class="grid-item grid-item--width2"></div>
    <div class="grid-item grid-item--width2"></div>
  </div>
</div>

A single grid element should contain a single post (name of the post category, title, description, read more button). Posts should be displayed from the date of inclusion, from selected categories.

I created this code:

    <?php
    $args = array( array( 'category__and' => array( 55, 61, 53, 59, 57 ) ), 'post_status' => 'publish', 'orderby' => 'ASC' );
    $news_query = null;
    $news_query = new WP_Query( $args );
   ?>
    <!-- grid masonry layout -->
    <div class="news-wrapper container">
       <div class="grid">
                <?php if ($news_query->have_posts()) : ?>
                <?php $count = 0; ?>
                <?php while ($news_query->have_posts()) : $news_query->the_post(); ?>
                <?php $count++; ?>
       <div class="grid-sizer"></div>
       <div class="gutter-sizer"></div>
            <?php if ( $count == 1 ) : ?>
       <div class="grid-item grid-item--width2">
            <div class="card card-media">
            <a href="#">
              <div class="news-cat"><?php the_category(', '); ?></div>
            </a>
            <div class="card-body">
              <h5 class="card-title"><a href="<?php the_permalink() ?>" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h5>
              <p class="card-text"><?php the_excerpt(); ?></p>
              <a href="#" class="btn"><span class="nav-text">Read more</span><i class="fa-xs fas fa-arrow-right"></i></a>
            </div>
        </div>
      </div>
            <?php elseif ($count == 2) : ?>
          <div class="grid-item grid-item--height2"> (..and next grid item...)

I have introduced counting, because the grid elements have different styling (sometimes double width, double height), so I can not create identical grid elements in the loop, so how to change counting to display all posts (regardless of their number)?

  • The order of the different stylings is always the same (width2, height2, width2, width2, height2, height2) and repeats? – D. Dan Jan 29 '18 at 12:45
  • Yes, that was the idea of graphic designer...the next page of posts should be the duplication of the earlier, with the same arrangement. Of course, if there are only 4 posts on the next page (instead of the next 12), boxes should be displayed and arranged according to the grid, but this is done by the masonry script. – sunnyluk Jan 29 '18 at 13:32
  • Your code as written, will break pagination if you need such. The question as it is, is specifically about wrtting PHP code which is off topic here. – Mark Kaplun Jan 29 '18 at 13:49
  • Thanks, but I'm wondering now, would it not be better to use a simple loop to display all posts from the category within the grid class div, each with the grid-item class, and then, for example, in JS add individual classes: ... width2 and. ..height2 to the right items – sunnyluk Jan 29 '18 at 14:00
  • That would work if you added the classes before the masonry script runs. I would maybe look a little off while the page loads completely, but I think it would be ok. – D. Dan Jan 30 '18 at 7:15
0

Instead of $count == 1 you should use ($count % 12) == 0, 1, and so on till 11. This gives back the remaining of the division. So if $count is 6 you would get 6, but if $count was 16 it would give back 4.

0

As I mentioned before, I created a single loop.

<div class="grid">
    <div class="grid-sizer"></div>
    <div class="gutter-sizer"></div>
        <!-- the loop -->
        <?php while ( $wpb_all_query->have_posts() ) : $wpb_all_query->the_post(); ?>
        <div id="grid-item-nr-<?php echo $post_nr; ?>" <?php post_class( 'grid-item' ); ?>>
          <div class="card">
            <div class="news-cat"><?php the_category(', '); ?></div>
            <div class="card-body">
                <h5 class="card-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h5>
                <p class="card-text">
                <?php if ( is_category() || is_archive() ) {
                echo excerpt(20);
                    } else {
                echo excerpt(20);
                    } ?>
                </p>
                <a href="<?php the_permalink(); ?>" class="btn"><span class="nav-text">Czytaj więcej</span><i class="fa-xs fas fa-arrow-right"></i></a>
             </div>
          </div>
       </div>
    <?php $post_nr++; endwhile; ?>
    <!-- end of the loop -->
</div>

Then I created a script (which I could certainly optimize ...) adding classes to the appropriate boxes, repeating every next 11 elements.

$(function() {
    var item = 0;
    var a = 0; // 1 element
    var b = 3; // 4 element
    var c = 5; // 6 element
    var d = 6; // 7 element
    var e = 9; // 10 element
    var f = 10; // 11 element
    var g = 1; // 2 element
    var h = 7; // 8 element
    var i = 8;; // 9 element
    var j = 2; // 3 element
    var k = 4; // 5 element

for (item = 0; item < 100; item++) {
      $('.grid').find("div.grid-item:eq(" + a + ")").addClass('grid-item--width2');
      $('.grid').find("div.grid-item:eq(" + b + ")").addClass('grid-item--width2');
      $('.grid').find("div.grid-item:eq(" + c + ")").addClass('grid-item--width2');
      $('.grid').find("div.grid-item:eq(" + d + ")").addClass('grid-item--width2');
      $('.grid').find("div.grid-item:eq(" + e + ")").addClass('grid-item--width2');
      $('.grid').find("div.grid-item:eq(" + f + ")").addClass('grid-item--width2');
      $('.grid').find("div.grid-item:eq(" + g + ")").addClass('grid-item--height2');
      $('.grid').find("div.grid-item:eq(" + h + ")").addClass('grid-item--height2');
      $('.grid').find("div.grid-item:eq(" + i + ")").addClass('grid-item--height2');
      $('.grid').find("div.grid-item:eq(" + j + ") p.card-text").hide();
      $('.grid').find("div.grid-item:eq(" + k + ") p.card-text").hide();
      a += 11;
      b += 11;
      c += 11;
      d += 11;
      e += 11;
      f += 11;
      g += 11;
      h += 11;
      i += 11;
      j += 11;
    };
  });

Classes are added before calling the masonry script. The effect has been achieved.

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.