WordPress 2.7 and Comment Display

WordPress 2.7 has a great interface. I’ve also found that many of the theme designs I’ve created in the past still work well in 2.7. So it was a no-brainer to move on up. There’s too much cool stuff back here to not do it.

However, I can say that one thing that was always “fun” to work with was the comments. My comments.php file is immense. I have so much stuff going on in there that I even get confused every time I look at it.

But 2.7 had a solution. You may not know it, but they now have “wp_list_comments()” as an available tag. Shiny and sparkly new.

Unfortunately, it’s so shiny and sparkly new that there isn’t much documentation on how to use it. A lot of what you find in the codex is standard WordPress code jargon, and you have to read between the lines to glean the info you really need.

in redoing this site, I needed that gleaning. I spent quite a lot of time yesterday messing with this tag. I’ve discovered that, if you just use the basic “wp_list_comments()” tag, you get a default layout – basically what you find when using the default theme. Commenter name on top, date he posted, comment below. But what if you want a more stylized comment layout?

Basically, you *can* do this. The basic idea is, if you know how you want ot have your comments designed, all you have to do is write a simple layout for it, and place it in your functions.php file. Give it a name, and use the “callback” feature for “wp_list_comments()“. And that’s it. Pretty simple.

Your parameters for the tag are:

  1. avatar_size you can set how large, in pixels, you want the avatar to appear. it’s square – so it only takes on number and applies it to both axis.
  2. style the default is an ordered list, but you can change it to “div” or “ul”. You’ve got to be careful with this though, and I’ll explain why in a minute.
  3. callback this is the string for any customizations you want to have in the commenting template. The codex doesn’t recommend you use this function – it’s there for advanced purposes. But hey – where’s the fun in safety? This is really what this post is all about.

Now, I’m not going to go into ALL the details of what should go into your comments.php file. You can see the vast majority of the goodies by just saving the file from the default theme into your own. All I’m covering at the moment is the “wp_list_comments()” tag, and how to customize the look of it.

Now, before, I mentioned that if you changed the way the comments are laid out (i.e. change it from the default “ol” to “div”) you needed to be careful. That’s because – for some reason I haven’t been able to determine yet, whatever you choose will have a closing tag placed at the end. So, for example, when I changed mine to “div” (wp_list_comments('style=div')), my site layout broke – because the new commenting thing added a closing “div” tag at the end of each comment. According to my layout, I didn’t need it (because I already put it in there), so what happened was it added an extra one, and hat broke everything. Same for “ul”. So when you customize your comment display, you need to *not* add in that closing tag – as much as you’d like to.

Now, all you have to do is come up with your layout design. For simplicity’s sake, we’ll say you want the avatar, name, date and reply to be *beneath* the comment – not at the top (as is the default setup). I always find it easiest to come up with the layout first, and add tags later – so what we’re looking for is this:


<div class="comment" id="comment-ID">
<p>comment text here</p>
<img src="avatar here" />
<p class="commentmetadata">
Name<br />
date</p>
</div>

Pretty simple, right? So now you want to take the above, and add in all the “code-y” stuff.


<div class="comment" id="comment-<?php comment_ID(); ?>" <?php comment_class(); ?>>

  1. comment_ID(); is, of course, the ID of the comment in the database.
  2. comment_class(); is not required, but it’s nice. What this does is, on every odd-numbered comment, it’ll add a class of “odd”; for every even-numbered comment, it’ll add a class of “even”. It’ll also add a “byuser” class if the comment is left by someone who is subscribed and logged in. And finally, it’ll add a class that contains the author’s username so you can get really specific with your styling.

<p><?php comment_text(); ?></p>
which is, of course, for the actual “meat” of the comment.

<?php echo get_avatar($comment,$size='48',$default='<path_to_url>' ); ?>
This get’s the avatar and the link settings for it. the “echo get_avatar()” part obviously gets the avatar, and..

  1. $comment would associate the image with the comment.
  2. $size is the size – in pixels – of the image. In this case it’s a 48 x 48px image.
  3. $default is the URL to the commenter (which they put in the “website” field of the form).

<p class="commentmetadata">
<?php printf(__('<cite class="fn">%s</cite>'), get_comment_author_link()) ?><br />
<a class="date" href="<?php echo htmlspecialchars( get_comment_link( $comment->comment_ID ) ) ?>"><?php printf(__('%1$s at %2$s'), get_comment_date(), get_comment_time()) ?></a>
</p>

The above does pretty much what you think it does. I hate the “says” in the comment (shows up after the “cite” tag), so I’ve removed it. But you can make it say whatever you want. Then it shows a link to the site again, the name, the date, the time, etc.
</code>

..and the end. (don’t forget – we’re removing the closing div tag!)

Now there’s some extra goodies you’ll also want to add to this basic setup:


<?php if ($comment->comment_approved == '0') : ?>
<em><?php _e('Your comment is awaiting moderation.') ?></em><br />
<?php endif; ?>

..is, of course, the message you want to show when a comment is awaiting moderation.

<div class="reply">
<?php comment_reply_link(array_merge( $args, array('add_below' => 'div-comment', 'depth' => $depth, 'max_depth' => $args['max_depth']))) ?>
<?php edit_comment_link(__('e'),' | ','') ?>
</div>

..is what you’ll want to add when you want to create “threaded” comments. This provides a link so that someone can pick a comment and reply to it – then you can style it later so the threading shows.

Now you want to place all of this in the functions.php file. But you have to start by telling WordPress that things are changing, and you want new stuff to take effect. If you don’t, then you’ll get a bunch of blank/anonymous postings, because you’re basically pulling out of the standard version. So to make it connect properly, you have to put in a small command: $GLOBALS['comment'] = $comment;

In the end, your function will look like so:

function format_comment($comment, $args, $depth) {
$GLOBALS['comment'] = $comment; ?>
<div class="comment" id="comment-<?php comment_ID(); ?>" <?php comment_class(); ?>>

<?php if ($comment->comment_approved == '0') : ?>
<em><?php _e('Your comment is awaiting moderation.') ?></em><br />
<?php endif; ?>

<p><?php comment_text(); ?></p>

<div class="reply">
<?php comment_reply_link(array_merge( $args, array('add_below' => 'div-comment', 'depth' => $depth, 'max_depth' => $args['max_depth']))) ?>
<?php edit_comment_link(__('e'),' | ','') ?>
</div>

<p class="commentmetadata">
<?php printf(__('<cite class="fn">%s</cite>'), get_comment_author_link()) ?><br />
<a class="date" href="<?php echo htmlspecialchars( get_comment_link( $comment->comment_ID ) ) ?>"><?php printf(__('%1$s at %2$s'), get_comment_date(), get_comment_time()) ?></a>
</p>

}

Now your final step is to make the tag in your comments.php file take all of the above into account. We’ll be making the style “div” and using the callback parameter – which you define with your function name. So open up the file, and find the “wp_list_comments()” tag and add in your parameters:

wp_list_comments('style=div&callback=format_comment')

Voila! You now have a customized comment layout – free for you to style as you see fit.

Comments

  • Nic

    I love that you do these little tutorials. To be honest, I stumbled on to your site when I was in search of designing WP Themes. (these were on your old Anekio Studio site). Thank you for taking the time in (spelling out) sharing your knowledge on WordPress. You are truly an asset to the WP Community and web designing as well. I hope to follow in your foot steps sometime soon. (Provided my feet don’t end up hurting).

    Thank you again,

    Nicholas

    January 5, 2009 at 5:47 pm Reply
  • Mike

    i was just curious how the reply function displayed it self

    January 13, 2009 at 5:24 am Reply
    • Shelly

      Well, in my site it doesn’t. But that’s a good question, and thanks for bringing that up. It’s actually due to a few things. First you need to add in the header.php file:

      <?php if ( is_singular() ) wp_enqueue_script( 'comment-reply' ); ?>

      The wp_enqueue_script() function will call in default scripts into WordPress. The above pulls in/activates the “comment-reply” script (only to single post pages which is really only where you need it to be), which enables the JS threading of comments.

      Then in the comments.php file, you need to add in:

      <?php comment_id_fields(); ?>

      (if you have “comment_post_ID” in your comments.php file, just replace that with the above code – you can’t have both at the same time.) This replaces the ID with a hidden field that tells the page if the comment is a parent or a child.

      Your comment textarea field also MUST have an id of “comment” – don’t change it to “message” or anything else. Also, to enable linking from other sources, your “respond” ID has to be set on a div, not just the anchor tag. (in the past, it was “<a id="respond" rel="nofollow"></code>" - now it should be "<div id="respond"><a>"

      The "<h3>Leave a Comment</h3>" Should be converted to this:

      <h3><?php comment_form_title(); ?></h3>

      That's pretty much it. You can read more on customizing these variables here.

      January 13, 2009 at 9:00 am Reply
  • adrian

    wow, great blog u got here…i must digg and stumble it…when i get home…

    keep up the great work….

    June 1, 2009 at 7:57 am Reply
  • Adam

    Thanks for writing this. I was having a difficult time finding an explanation for the comment_class() function.

    Could you explain how to style/code parent and child comments differently in a nested comment configuration?

    I like your use of jQuery for the “Show/Hide Replies” option. It keeps things clean and readable.

    June 9, 2009 at 11:14 am Reply
    • Shelly

      Hey Adam :)

      Actually, the styling is nothing more than CSS. If you view the source code of the site (when it’s loaded) you’ll see all the classes and ID’s that are attributed to the commenting section.

      Basically, you can alternate colors for every other comment by styling the “odd” and “even” classes in the stylesheet. Then there’s a third attribute for an author commenting on his own post. You can delve into it even a bit more (and get as complicated as you like( because there’s also classes set for whether or not a comment is threaded or not (“thread-even”, “thread odd” and even the depth level: “depth-1″)

      Hope that helps :)

      June 9, 2009 at 11:36 am Reply
      • Adam

        I overlooked the depth level class even when looking at my source, doh! Thank you for pointing it out and for responding so quickly.

        I noticed that the magnifying glass icon’s border isn’t level with the rest of the search box’s border at the top of your site, maybe some padding/margin is off? I don’t know if this is intended but I thought I’d let you know :D

        June 9, 2009 at 2:56 pm Reply
      • Shelly

        NO problem :)

        And yeah, I know about the magnifying glass (in FF2 – I think? I use FF3 and it doesn’t do that) I just haven’t had a chance to fix it. I need to get scheduling in order so I can fix things like this! :)

        June 9, 2009 at 3:11 pm Reply
      • Adam

        I’m using Firefox 3.0.10 on Windows XP SP3 :(

        June 9, 2009 at 6:01 pm Reply
      • Shelly

        Interesting. I have FF3 on my XP box as well, and I’m not seeing it over there.

        XP is so much fun. (That’s why I love my Mac! LOL)

        June 9, 2009 at 8:40 pm Reply
  • Have your say: