I've been building a theme completely from scratch and after a straightforward process up to this point, I've reached the comments.php file. Again, nothing too out of the ordinary, until this:

$callback (string) (optional) The name of a custom function to use to open and display each comment. Using this will make your custom function get called to display each comment, bypassing all internal WordPress functionality in this respect. Use to customize comments display for extreme changes to the HTML layout. Note that your callback must include the opening <div>, <ol>, or <ul> tag (corresponding with the style parameter), but not the closing tags. WordPress will supply the closing tag automatically, or you can use end-callback to override this default. The callback is separate from the end-callback to facilitate hierarchical comments. Use with caution.

Why is this so mad? Why isn't there a way to just have a comment.php template that gets used for each comment? (Or if there is, please do let me know)

  • For the context of "madness" WP supports a lot of stuff for comments like configurable nesting level and pagination. So even simplest linear display goes through all that logic and overall it's appropriately messy experience. :)
    – Rarst
    Apr 27, 2013 at 18:25

1 Answer 1


If you prefer simple template files, you can do that with custom comment callbacks too.

Call wp_list_comments() with a custom callback handler:

        'callback' => 'custom_comment_callback', 
        'style'    => 'ol' 

Now make that callback function very simple:

function custom_comment_callback( $comment, $args, $depth )
    include 'comment-template.php';

And now you can use comment-template.php like any other template.

Here is a simple example showing you what variables are available:

<?php # -*- coding: utf-8 -*-
print '<pre>$comment = ' . esc_html( var_export( $comment, TRUE ) ) . '</pre>';
print '<pre>$args = '    . esc_html( var_export( $args, TRUE ) )    . '</pre>';
print '<pre>$depth = '   . esc_html( var_export( $depth, TRUE ) )   . '</pre>';

You can also use the functions body of an existing callback handler like that from Twenty Twelve here, and it will work:

<?php # -*- coding: utf-8 -*-
$GLOBALS['comment'] = $comment;
switch ( $comment->comment_type ) :
case 'pingback' :
case 'trackback' :
    // Display trackbacks differently than normal comments.
    <li <?php comment_class(); ?> id="comment-<?php comment_ID(); ?>">
        <p><?php _e( 'Pingback:', 'twentytwelve' ); ?> <?php comment_author_link(); ?> <?php edit_comment_link( __( '(Edit)', 'twentytwelve' ), '<span class="edit-link">', '</span>' ); ?></p>
        default :
        // Proceed with normal comments.
        global $post;
    <li <?php comment_class(); ?> id="li-comment-<?php comment_ID(); ?>">
        <article id="comment-<?php comment_ID(); ?>" class="comment">
            <header class="comment-meta comment-author vcard">
                    echo get_avatar( $comment, 44 );
                    printf( '<cite class="fn">%1$s %2$s</cite>',
                        // If current post author is also comment author, make it known visually.
                        ( $comment->user_id === $post->post_author ) ? '<span> ' . __( 'Post author', 'twentytwelve' ) . '</span>' : ''
                    printf( '<a href="%1$s"><time datetime="%2$s">%3$s</time></a>',
                        esc_url( get_comment_link( $comment->comment_ID ) ),
                        get_comment_time( 'c' ),
                        /* translators: 1: date, 2: time */
                        sprintf( __( '%1$s at %2$s', 'twentytwelve' ), get_comment_date(), get_comment_time() )
            </header><!-- .comment-meta -->

            <?php if ( '0' == $comment->comment_approved ) : ?>
                <p class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.', 'twentytwelve' ); ?></p>
            <?php endif; ?>

            <section class="comment-content comment">
                <?php comment_text(); ?>
                <?php edit_comment_link( __( 'Edit', 'twentytwelve' ), '<p class="edit-link">', '</p>' ); ?>
            </section><!-- .comment-content -->

            <div class="reply">
                <?php comment_reply_link( array_merge( $args, array( 'reply_text' => __( 'Reply', 'twentytwelve' ), 'after' => ' <span>&darr;</span>', 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?>
            </div><!-- .reply -->
        </article><!-- #comment-## -->
    endswitch; // end comment_type check
  • 1
    Great answer! Wasn't expecting something so comprehensive!
    – Jack
    Apr 27, 2013 at 18:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.