WordPress: Advanced Comment Customization

Comments are an important part of a WordPress run site. It not only allows your visitors to chime in on your rantings, but it elevates the interactivity of your website, and helps keep visitors coming back.

It’s unfortunate that there really isn’t much built in customization when it comes to comments. WordPress by default allows you to:

  • Determine how comments are ordered (ascending/descending)
  • Automatic closing of comments
  • How many comments should display before a page break
  • What type of avatar

And that’s really about it. You can edit your comments.php file, but there’s only so much you can do there. The comments themselves are generated via a function, and therefore cannot simply be edited in comments.php.

The function where all the real magic happens is wp_list_comments(), located in the comments.php file in your theme. It’s used only in WordPress 2.7+, so go figure that this will only apply to WordPress 2.7+ users.

This post will show you how to implement your own HTML for you comments, along with a few extra little bits.

The wp_list_comments() Function

There are a few things you should know about wp_list_comments() before we begin. There are many arguments that you can apply to the function in your comments.php file. Below are the most important arguments:

  • avatar_size
  • type
  • reply_text
  • callback

For a full list and explanation of each argument the function accepts, check out the WordPress Codex on it.

Another thing to touch on is the method the functions accepts arguments. You can either apply your arguments as a string OR an array. For example:

1
2
3
4
5
wp_list_comments("type=comment&style=ul");
wp_list_comments(array(
  'type' => 'comment',
  'style' => 'ul'
));

Both will achieve the same effect, so whichever one you choose can simply be about preference. For the rest of this post, I’ll be using the string method (Simply because it’s faster to type out ;-)).

Avatar Size:

The avatar_size argument is pretty self explanatory. It allows your the specify the pixel size each avatar should be. The default is 32. What avatars are displayed is defined by your options in the Settings->Discussion Options Panel.

1
wp_list_comments("avatar_size=50");

Type:

The type argument specifies what comments you want to be displayed. By default it displays all comments, but you can choose to display only comments (comment), trackbacks (trackback), pingbacks (pingback), or trackback and pingbacks (pings).

1
2
3
wp_list_comments("type=comment"); // Display only comments
wp_list_comments("type=pingback"); // Display only pingbacks
wp_list_comments("type=ping"); // Display pingback and trackbacks

Reply Text

The reply_text argument let’s you specify the text for the ‘reply to comment‘ link. By default it’s ‘Reply‘.

1
wp_list_comments("reply_text=Reply to this Comment");

Callback

The callback argument is the big one here. With this you can specify a function that will be run to display each comment. This is where all the advanced customization goes. With this, you can have your comments display however you want.

1
2
3
4
5
wp_list_comments("callback=custom_comment_fun");
 
function custom_comment_fun() {
  // Code goes here
}

The next part of this post will address this argument specifically, and shows you how to write the function.

Callback Function

With this callback function, you can format your comments however you want. Below should be a good starting point that you can add to, or remove from. I suggest placing this function in your functions.php file. If you don’t already have one, I strongly suggest making one.

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
<?php
function custom_comment_fun($comment, $args, $depth) {
  $GLOBALS['comment'] = $comment; ?>
  <li <?php comment_class(); ?> id="li-comment-<?php comment_ID() ?>">
    <div id="comment-<?php comment_ID(); ?>" class="comment-body">
      <div class="comment-author vcard">
        <?php echo get_avatar($comment,$size=$args['avatar_size']); ?>
        <cite class="fn"><?php get_comment_author_link();?></cite> <span class="says">says:</span>
      </div>
      <?php if ($comment->comment_approved == '0') : ?>
      <em><?php _e('Your comment is awaiting moderation.') ?></em>
      <?php endif; ?>
      <div class="comment-meta commentmetadata">
        <a href="<?php echo htmlspecialchars( get_comment_link( $comment->comment_ID ) ) ?>"><?php echo get_comment_date();?> at <?php echo get_comment_time();?></a>
        <?php edit_comment_link(__('(Edit)'),'&nbsp;&nbsp;','') ?>
      </div>
      <?php comment_text(); ?>
      <div class="reply">
        <?php comment_reply_link(array_merge( $args, array('depth' => $depth, 'max_depth' => $args['max_depth']))) ?>
      </div>
    </div>
   <?php
  // Do not include the </li> tag.
}
?>

Make sure to note not to include the closing tag for <li>. WordPress adds this later after it has run another function to determine if the comment has any replies.

Example

Here’s an example of the callback function I use to display the comments on my site:

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
<?php
function custom_commenter($comment, $args, $depth) {
  $GLOBALS['comment'] = $comment; ?>
  <li <?php comment_class(); ?> id="li-comment-&lt;?php comment_ID() ?>">
    <div id="comment-<?php comment_ID(); ?>" class="comment-body">
      <div class="top rtop">
        <div class="comment-avatar">
          <?php echo get_avatar($comment,$size=$args['avatar_size']); ?>
        </div>
        <div class="comment-author vcard">
          <?php echo get_comment_author_link(); ?>
          <span class="comment-meta commentmetadata"><a href="<?php echo htmlspecialchars( get_comment_link( $comment->comment_ID ) ) ?>">(<?php printf(__('%1$s at %2$s'), get_comment_date(), get_comment_time()) ?>)</a> <?php edit_comment_link(__('(Edit)'),' ','') ?></span>
        </div>
        <?php if ($comment->comment_approved == '0') : ?>
        <em><?php _e('Your comment is awaiting moderation.') ?></em>
        <?php endif; ?>
      </div>
      <div class="comment-text">
        <?php comment_text(); ?>
      </div>
      <div class="reply rbot">
        <?php comment_reply_link(array_merge($args, array('depth' => $depth, 'max_depth' => $args['max_depth']))) ?>
      </div>
      <div class="clear"></div>
    </div>
<?php
}
?>

Custom Reply Link

Here’s a filter that will let you adjust your own reply link. I needed this because I wanted to add the comment ID to the <a> tag.

1
2
3
4
5
6
7
8
9
10
11
function my_replylink($c='',$post=null) {
  global $comment;
  // bypass
  if (!comments_open() || $comment->comment_type == "trackback" || $comment->comment_type == "pingback") return $c;
  // patch
  $id = $comment->comment_ID;
  $reply = 'Reply to this Comment';
  $o = '<a class="comment-reply-link" rel="'.$comment->comment_author.'" id="'.$id.'" href="'.get_permalink().'?replytocom='.$id.'#respond">'.$reply.'</a>';
  return $o;
}
add_filter('comment_reply_link', 'my_replylink');

Separate Comments from Pingback and Trackbacks

You may want to display your comments with no Pingback/Trackbacks or with them separated. To do this, you only need to change a few lines in your comments.php file. :-D

Before

You comments.php files should contain this code, or something similar:

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
<?php
if (have_comments()) :
?>
 
<h4 class="txt1" id="comments">&lt;?php comments_number('No Responses', 'One Response', '% Responses' );?> to &#8220;&lt;?php the_title(); ?>&#8221;</h4>
<ol class="commentlist">
  <?php wp_list_comments(); ?>
</ol>
<div class="comment-navigation">
  <div class="alignleft">
    <?php previous_comments_link() ?>
  </div>
  <div class="alignright">
    <?php next_comments_link() ?>
  </div>
  <div class="fix"></div>
</div>
 
<?php  else : // this is displayed if there are no comments so far 
  if ('open' == $post->comment_status) : ?>
    <p>No Comments</p>
  <?php else : // comments are closed ?>
    <p>Comments are Closed</p>
  <?php endif; ?>
<?php endif; ?>

After

To separeate your comments and pings, we’ll use the following conditional statement:

1
2
3
4
$comments_by_type = &separate_comments(get_comments('status=approve&post_id='.get_the_ID()));
if ( !empty($comments_by_type['comment']) ) :
  // Display comments
endif;

This combined with the type argument in wp_list_comments(), you will be abel to effectively display ONLY what you specify.

Here’s a full code example:

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
<?php
if (have_comments()) :
  $comments_by_type = &separate_comments(get_comments('status=approve&post_id='.get_the_ID()));
  if ( !empty($comments_by_type['comment']) ) : // check to see that there are comments
?>
<h4 class="txt1" id="comments">&lt;?php comments_number('No Responses', 'One Response', '% Responses' );?> to &#8220;<?php the_title(); ?>&#8221;</h4>
<ol class="commentlist">
  <?php wp_list_comments(array('avatar_size' => 42,'callback' => 'custom_comment_fun', 'type' => 'comment')); // Added type and callback argument ?>
</ol>
<div class="comment-navigation">
  <div class="alignleft">
    <?php previous_comments_link() ?>
  </div>
  <div class="alignright">
    <?php next_comments_link() ?>
  </div>
  <div class="fix"></div>
</div>
 
<?php endif; // end comment display ;?>
<?php if ( !empty($comments_by_type['pings']) ) : // check to see that there are pings ?>
 
<ol class="commentlist">
  <?php wp_list_comments(array('avatar_size' => 42,'callback' => 'custom_comment_fun_ping', 'type' => 'pings')); ?>
</ol>
 
<?php endif; // end ping display
 else : // this is displayed if there are no comments so far 
  if ('open' == $post->comment_status) : ?>
    <p>No Comments</p>
  <?php else : // comments are closed ?>
    <p>Comments are Closed</p>
  <?php endif; ?>
<?php endif; ?>

With those few additions, you can have your comments and ping separated. You can also create a new call back for your pings, so they can look different that your comments.

Hope this post helps! Good luck!

August 27th, 2009 | Wordpress

6 Responses to “WordPress: Advanced Comment Customization”

  1. Great post with a lot of good coded info, but I was trying this on my homepage and it didn’t work. I found that wp_list_comments() needs to run for a single post or page in the loop… You can’t pass it a post id or get all comments. You can use get_comments(), but that function doesn’t take “type”. Seem like they could consolidate all the comments functions into a more robust function.

    Thanks again for the info.

  2. Thanks so much for this post! It was very helpful. I couldn’t figure out how to get the avatars to display at the proper size, and this saved me. Thanks again!

  3. Hi there,

    I am in desperate need of help because I really need to paginate my comments, yet the WordPress option in the Admin panel isn’t working. Upon further inspection, I’ve found that in my comments.php file, I don’t have the wp_list_comments function. Is there any way to alter my comments.php code so that I can use WordPress’s paginated comments function? Any help you can provide would be GREATLY appreciated! Thanks so much!

  4. Thanks to you, I managed to fix a bit of comment/trackback separation. Just goes to show you that wordpress is beautifully complex and you can learn something new about it every day.

  5. Excellent site, keep up the good work

2 Pinback/Trackback's to “WordPress: Advanced Comment Customization”

Leave a Reply

Name:
Email:
Website:
Message:
SUBMIT