Like the blog? Get the book »

Custom Comments HTML Output

Custom Comments HTML Output

With WordPress, displaying all the comments on a Post or Page is incredibly easy. In your theme’s single.php file you probably have a line like this:

<?php comments_template(); ?>

That line basically calls/includes your comments.php file. Within that, the line to output all comments is something really simple like this:

<ol class="commentlist">
   <?php wp_list_comments(); ?>

But that doesn’t leave much by way of customizing the HTML that gets output, does it? Fortunately it’s fairly easy to specify your own formatting in a non-destructive non-core-altering way. Although personally, I’m having one little issue with it. Let’s take a look.

Why would you need this?

This is what you get as the defacto standard comment output:

Screenshot of default markup for WordPress commentsThis is from the new 2010 theme slated to come out with WordPress 3

But what if you wanted something more like this?

Screenshot of alternate comment displayFrom a new client site I’ve been working on

The best way to get into that new skin is to get your hands on the HTML, as CSS alone isn’t quite going to get us there.

Custom output through a callback function

The trick is is that the wp_list_comments function accepts a parameter for a callback function. This function overrides what the output of each comment will be. Here is an example of that:

<ol class="commentlist">
    <?php wp_list_comments('type=comment&callback=format_comment'); ?>

The above code will only output “comments” (and not trackbacks or pingbacks) and will call a custom function “format_comment” for formatting the comment. This function needs to be built in your functions.php file, and better be present before you call this function otherwise you’ll throw an error.

The callback function is completely in charge of the comment formatting. It could be something completely whacky like this:

    function format_comment() {  ?>
           <li>This is whack, yo.</li>
   <?php } 

Which would return that ridiculous sentence for every single comment, instead of the actual comment. Of course you wouldn’t (probably) ever do that. What you probably want to do, is just adjust how the different standard comment-related data is output. To do that, first you pull in the comment globals, then you can use all the comment functions that return the stuff that you probably want:

  • get_comment_link
  • get_comment_author
  • get_comment_date
  • get_comment_time
  • get_comment_text
  • etc.

Here is a customized formatting function I recently used:


    function format_comment($comment, $args, $depth) {
       $GLOBALS['comment'] = $comment; ?>
        <li <?php comment_class(); ?> id="li-comment-<?php comment_ID() ?>">
            <div class="comment-intro">
                <em>commented on</em> 
                <a class="comment-permalink" href="<?php echo htmlspecialchars ( get_comment_link( $comment->comment_ID ) ) ?>"><?php printf(__('%1$s'), get_comment_date(), get_comment_time()) ?></a>
                <?php printf(__('%s'), get_comment_author_link()) ?>
            <?php if ($comment->comment_approved == '0') : ?>
                <em><php _e('Your comment is awaiting moderation.') ?></em><br />
            <?php endif; ?>
            <?php comment_text(); ?>
            <div class="reply">
                <?php comment_reply_link(array_merge( $args, array('depth' => $depth, 'max_depth' => $args['max_depth']))) ?>
<?php } ?>

When NOT to customize output

Remember that CSS is quite the handyman at whipping things into shape. Let’s say your goal was to get rid of the gravatars that the default comment formatting outputs. Well that’s as simple as:

.avatar { display: none; }

And with more powerful tools like absolute positioning, you can take the default output and really do a ton of customization. There are some times though, when you need to alter the HTML to do it right, and that’s when all this is useful.

My little problem

My custom output works really well, save for one little problem. That is nested replies. The WORK, it’s just the output is invalid, as nested lists sit directly within the list above it instead of being wrapped in a list item like they should be. See:

Comparison of comment display and markup

I’m not quite sure how to fix that, although I imagine it can be done within the custom function somehow? If anyone knows, let me know.


It was my mistake, although in my defense, the answer is a little weird. What you need to is OMIT the closing </li> tag in the callback function. WordPress will add that automatically for you.

In other news, if you find your callback function breaks the “Reply” button functionality, take a look at the add_below parameter:

<?php comment_reply_link(array_merge( $args, array('reply_text' => 'Reply', 'add_below' => $add_below, 'depth' => $depth, 'max_depth' => $args['max_depth']))); ?> 

That parameter takes a string, like “div-comment” for example, and then the reply links on each comment will be looking for the page element of “div-comment-XXXX” to jump the comment form up to (where XXXX is the ID of the comment). So your theme better have page elements with matching ID’s, or the reply link will “fail” and reload the page. I say “fail” in quotes because replying will still work, it just doesn’t do the cool jump-up technique which is the whole point of the comment-reply.js file that most themes load on single pages.

14 responses

  1. First answer, perfect anwser ! Hole in One !

    Thx Nico.

  2. In your format_comment() just dump the closing </li> at the end, WP will put it in itself, after the replies. You can read that here after the last code section: “Note the lack of a trailing </li>. WordPress will add it itself once it’s done listing any children and whatnot.”

  3. Thanks a lot for the tips on comments. I have been trying to make a blog of my own and styling the comments has been one of the hard parts, this helped so much. Thanks

  4. Truly will be helpful, Chris. I had quite a lot of “fun” sorting out the css and how it applied to the default html output. Thanks for breaking it down so plainly!

  5. This is a gem. I hate not having control of the auto-generated markup.

    Cheers, Chris.

  6. Thanks fot tips

  7. .avatar { display: none; }

    Hmm – will the images still get downloaded? I think it would be better to disable avatars properly (not sure how to off the top of my head)…

  8. Eric Lightbody

    This is very useful. I usually start with a comments template, and I just realized that the author of this template is the same Ian you used for the code sample. Pretty cool.

  9. Thank you for article to tech people how to custom their comment list wordpress blog. I will try to doing follow your article. Hope it will helpful and look like what I think on mind.

  10. Nikola Lazarevic

    Nice tip, but i have small problem. When I hit submit, it takes me to the top of the page, not on comment I just submited. If I scroll down, to the comment everything is ok. It says Your comment is awaiting moderation etc…

    How can I fix this issue? Thanks!

Comments are closed for this post. Contact us with any critical information.
© 2009–2024 Digging Into WordPress Powered by WordPress Monzilla Media shapeSpace