Modifying the way posts look in the loop


I've been struggling with this for a while, and finally decided to throw it out there to see if anyone can help me figure it out.

I want to make fairly drastic changes to the way posts look in the loop. The simplest is that I want to show the_excerpt() instead of the_content(). I have it set to "Summary" in WP settings, but I notice that that loop.php is just calling the_content(). So, I'd be happy with at least some direction on that basic thing.

What I really want is something like what you see toward the bottom of this page.

The posts showing here are in a hand-made template that's not in the loop, but rather called individually with the ID of a specific post. It's meant to be a way of hand-picking posts to show on that page. I would like the posts in the regular loop to appear this way, too if possible.

I got pretty far with the various HTML manipulation tricks that are available with Beans, but I'm not sure where/how to fire it. I have it firing in 'wp' now, removing all of the native actions and hoping to show my custom version, but it doesn't seem to have the $post object for each post.

So, I got myself down a deep hole. Can anyone get me out? πŸ™‚


Hey Michael,

Regarding the_content(), the best is to use the_content filter to modify the output. For example, the snippet below change the content to the excerpt if it exists and automatically add the read more button, thus only if it is the front page or home.

add_filter( 'the_content', 'beans_child_modify_post_content' );

function beans_child_modify_post_content( $content ) {

 // Return the excerpt() if it exists and if it is the home/front page.
  if ( has_excerpt() && ( is_home() || is_front_page() ) )
    return '<p>' . get_the_excerpt() . '</p><p>' . beans_post_more_link() . '</p>';

 return $content;

}

From there you may change the condition or output according to your need πŸ™‚

When in come to the loop, you can really add any loop anywhere on the page. For example, here is what the snippet below does.

  • Add a custom loop called featured before the main grid.
  • Set the query to show only 3 posts.
  • Add uk-h3 class to the post title to make it smaller.
  • Set the content to how the excerpt if it exists and automatically show the read more.
  • Remove the post meta.
  • Set a 3 columns responsive grid.
  • Reset everything after the loop to make sure it doesn't affect the main loop.
add_action( 'beans_loop_query_args[_featured]', 'beans_child_featured_query_args' );

function beans_child_featured_query_args() {

 // Only apply to front page.
  if ( !is_front_page() )
   return;

 return array(
   'posts_per_page' => 3
 );

}

add_filter( 'the_content', 'beans_child_modify_post_content' );

function beans_child_modify_post_content( $content ) {

  // Only apply to front page.
  if ( !is_front_page() )
   return;

 // Return the excerpt() if it exists.
 if ( has_excerpt() )
     return '<p>' . get_the_excerpt() . '</p><p>' . beans_post_more_link() . '</p>';

  return $content;

}

add_action( 'beans_main_grid_before_markup', 'beans_child_featured_post_loop' );

function beans_child_featured_post_loop() {

  // Only apply to front page.
  if ( !is_front_page() )
   return;

 beans_add_attribute( 'beans_post_title', 'class', 'uk-h4' );
  beans_remove_action( 'beans_post_meta' );
 beans_remove_action( 'beans_post_meta_categories' );
  beans_remove_action( 'beans_post_meta_tags' );
  beans_remove_action( 'beans_posts_pagination' );
  beans_wrap_markup( 'beans_post', 'beans_child_featured_post_grid_column', 'div' );

  ?><div class="uk-grid uk-grid-width-medium-1-3" data-uk-grid-margin><?php

   beans_loop_template( 'featured' );

  ?></div><?php

 // Reset.
    remove_filter( 'the_content', 'beans_child_modify_post_content' );
 beans_reset_attributes( 'beans_post_title' );
 beans_reset_action( 'beans_post_meta' );
  beans_reset_action( 'beans_post_meta_categories' );
 beans_reset_action( 'beans_post_meta_tags' );
 beans_reset_action( 'beans_posts_pagination' );
 beans_remove_markup( 'beans_child_featured_post_grid_column' );

}

A few notes on this snippet.

  • Important: it uses beans_reset_attributes which was recently added and not released yet. So you may either pull from the development github repository or remove the function from the snippet.
  • In the beans_child_featured_query_args() you may set what ever query you want (custom post type or even set your specific posts ids 'post__in' => array( 1, 2, 3 ), for example).
  • It is made to be added in your child theme functions.php and that is why there is the if ( !is_front_page() ) condition in every functions which you can remove if you add it to a page template, or change to what every condition you need.
  • All the actions are reset because it is place before the main loop but if it is after the main loop, you don't need to reset it.
  • If you are interested to know how to apply that to the main loop, let me know and I will modify the snippet accordingly πŸ™‚

I hope that shows a little be more how to use Beans loop HTML to build highly customized loops. You could really become even lot more creative in the beans_child_featured_post_loop() and make heavy usage of UIkit (aka make it a slider or what ever floats your boat).

Please don't hesitate to ask if you have any questions!


Thanks Thierry,

That's a lot to chew on, but I'll give it a go. I would like to know how to apply this to the native loop, actually. I wasn't planning to do any custom loops, although it's interesting to see this.

Also, this is just a basic WordPress question, I guess, but I would like to show either a hand-crafted excerpt, or ugly WordPress-truncated summary if no excerpt exists. I thought this is what the_excerpt() does. (It's weird; I've been using WordPress for many years, but some basic things like this just don't come up that often.)

Many thanks!


Hey Michael,

Don't worry too much if it is a lot to take, you will soon master it I am sure πŸ™‚

Below is a revised script which applies the changes to the main posts loop beside single views. You will see that I have modified the beans_child_modify_post_content() to display the excerpt if it exists, otherwise trim the post content to 40 words using WP core funtion wp_trim_words(). The Read More is added after the content in both case.

Regarding modifying the loop, I have added inline comments in the codes which should be self-explanatory. The only reason we added to a wp action is because this snippet is meant to go to your child theme functions.php so we need add the is_singular() check which is not accessible before the wp action is called. Actions order is very important in WP and it might take a bit of practice to understand. For example if you where running the same script directly in your front-page.php page template, then you would not need to do the is_singular() check and all the stuff in beans_child_setup_document() would not be in a wp callback.

add_filter( 'the_content', 'beans_child_modify_post_content' );

function beans_child_modify_post_content( $content ) {

 // Stop here if we are on a single view.
  if ( is_singular() )
    return;

 // Return the excerpt() if it exists other truncate.
  if ( has_excerpt() )
    $content = '<p>' . get_the_excerpt() . '</p>';
  else
    $content = '<p>' . wp_trim_words( get_the_content(), 40, '...' ) . '</p>';

  // Return content and readmore.
 return $content . '<p>' . beans_post_more_link() . '</p>';

}

add_action( 'wp', 'beans_child_setup_document' );

function beans_child_setup_document() {

 // Stop here if we are on a single view.
  if ( is_singular() )
    return;

 // Make title smaller.
  beans_add_attribute( 'beans_post_title', 'class', 'uk-h4' );

  // Remove meta.
 beans_remove_action( 'beans_post_meta' );
 beans_remove_action( 'beans_post_meta_categories' );
  beans_remove_action( 'beans_post_meta_tags' );

  // Remove featured image.
 beans_remove_action( 'beans_post_image' );

  // Add grid.
  beans_wrap_inner_markup( 'beans_content', 'beans_child_posts_grid', 'div', array(
   'class' => 'uk-grid uk-grid-match',
   'data-uk-grid-margin' => ''
 ) );
  beans_wrap_markup( 'beans_post', 'beans_child_post_grid_column', 'div', array(
    'class' => 'uk-width-large-1-3 uk-width-medium-1-2'
 ) );

  // Move the posts pagination after the new grid markup.
 beans_modify_action_hook( 'beans_posts_pagination', 'beans_child_posts_grid_after_markup' );

}

My best advise is to take one step at the time and practice. Paste the code snippet in your functions.php which will work and then try to get in working in a front-page.php page template and fix it (don't cheat but this is what your page template code will look like). For the front page template to apply, you must set a page in your Settings->Reading->Front page.

Hope that helps,


Hi Michael,

How is your post loop modifications going? Were you able to apply your modifications to the main loop based on my latest reply?


Hi Thierry,

Thanks for checking in! I have not had a chance to implement this yet, but it looks clear what I need to do. In fact, I will need this to run just in the index looop, but not on the Front Page.

Part of the problem has to do with my wanting to use the featured image with uk-overlay. I thought it would make sense to wrap a uk-overlay div around both beans_post_header and beans_post_content, and then use beans_post_header as the uk-overlay-panel. The problem was that the loop did not work properly and it only knew returned the correct title and permalink for the first item. So that's the hole I'd dug myself.

Here's some of the code that attempted to achieve this. It's fired in a 'wp' action like your example. It's kind of a mess, I know...

beans_wrap_inner_markup( 'beans_content', 'mk_dynamic_grid', 'div', array( 'data-uk-grid' => '{gutter: 20}' ) );
beans_wrap_markup( 'beans_post', 'mk_dynamic_grid_item_wrapper', 'div', array( 'class' =>'uk-width-medium-1-3 mk-content-grid-item' ) );
beans_wrap_inner_markup( 'beans_post_header', 'mk_post_panel', 'div', array('class' =>'uk-panel uk-padding-remove'));
beans_wrap_inner_markup( 'mk_post_panel', 'mk_image_overlay', 'div', array('class' =>'uk-overlay uk-overlay-hover'));
beans_wrap_inner_markup( 'mk_image_overlay', 'mk_image_overlay_caption', 'figure', array( 'class' => 'uk-overlay-panel uk-overlay-background uk-ignore' ) );

add_action( 'mk_image_overlay_caption_prepend_markup', 'mk_post' );
add_action( 'mk_image_overlay_append_markup', 'mk_permalink' );

Thanks!

Michael


Hey Mickael, that is great.

I think you could do it a bit simpler but adding the overlay class to the image and append the overlay content. There is also a few other small tweaks such as only applying to non-single layouts and moving the pagination below the grid. Here is my version of the code:

add_action( 'beans_uikit_enqueue_scripts', 'mk_enqueue_uikit_assets' );

function mk_enqueue_uikit_assets() {

 beans_uikit_enqueue_components( 'overlay' );
  beans_uikit_enqueue_components( 'grid', 'add-ons' );

}

add_action( 'wp', 'mk_setup_document' );

function mk_setup_document() {

 // Only apply to non-single view.
 if ( !is_singular() ) {

   // Dynamic grid.
    beans_wrap_inner_markup( 'beans_content', 'mk_dynamic_grid', 'div', array(
      'data-uk-grid' => '{gutter: 20}'
    ) );
    beans_wrap_markup( 'beans_post', 'mk_dynamic_grid_item', 'div', array(
      'class' => 'uk-width-large-1-3 mk-content-grid-item'
    ) );

    // Move the posts pagination after the new grid markup.
   beans_modify_action_hook( 'beans_posts_pagination', 'mk_dynamic_grid_after_markup' );

   // Add image overlay.
   beans_add_attribute( 'beans_post_image_item_wrap', 'class', 'uk-overlay uk-overlay-hover' );

    // Add image overlay content.
   add_action( 'beans_post_image_item_wrap_append_markup', 'mk_post_image_overlay' );

  }

}

function mk_post_image_overlay() {

  // Since this is called in the post loop, you may add logic using the post id (aka get_the_ID()).

 ?>
  <figcaption class="uk-overlay-panel uk-overlay-background">
   Overlay content
 </figcaption>
 <?php

}

Note that I have added the mk_enqueue_uikit_assets() as a reference in case other users would like to use this snippet. I kept mk prefix according to your project though πŸ™‚

Thanks,

Write a reply

Login or register to write a reply, it's free!