Get the Official WPSaviour App Now!


How to Create a Custom Comments Callback in WordPress

The WordPress comments template (callback) is not only one of the more complicated steps when creating a custom WordPress theme, but the default comments code is also quite complicated to customize. If you are a theme developer and have gotten stuck trying to customize your comments to make them look the way you want, but can’t because you need to add extra div classes or have to remove some, then you need to check out this post. I will show you how to easily create a custom call-back template that WordPress will use for your comment structure so you can have complete control over your comment design.

A note to developers.. When building a WordPress theme for the WordPress.org directory or for redistribution on any other marketplace it’s best to leave the default comment design to make sure there aren’t any possible conflicts with 3rd party plugins. This tutorial is intended primarily for those looking for a custom solution on their active site (by making the modification via a child theme) or for those developing a custom design for their client.

Now on to the actual tutorial and if you have any questions or suggestions on how we can improve the guide please let me know in the comments section below the guide.

Step 1: Create better-comments.php

Make a new php file to your parent or child theme (you can call it anything, but I like to call it better-comments.php) and paste the code below.

// My custom comments output html
function better_comments( $comment, $args, $depth ) {

	// Get correct tag used for the comments
	if ( 'div' === $args['style'] ) {
		$tag       = 'div';
		$add_below = 'comment';
	} else {
		$tag       = 'li';
		$add_below = 'div-comment';
	} ?>

	<<?php echo $tag; ?> <?php comment_class( empty( $args['has_children'] ) ? '' : 'parent' ); ?> id="comment-<?php comment_ID() ?>">

	// Switch between different comment types
	switch ( $comment->comment_type ) :
		case 'pingback' :
		case 'trackback' : ?>
		<div class="pingback-entry"><span class="pingback-heading"><?php esc_html_e( 'Pingback:', 'textdomain' ); ?></span> <?php comment_author_link(); ?></div>
		default :

		if ( 'div' != $args['style'] ) { ?>
			<div id="div-comment-<?php comment_ID() ?>" class="comment-body">
		<?php } ?>
			<div class="comment-author vcard">
				// Display avatar unless size is set to 0
				if ( $args['avatar_size'] != 0 ) {
					$avatar_size = ! empty( $args['avatar_size'] ) ? $args['avatar_size'] : 70; // set default avatar size
						echo get_avatar( $comment, $avatar_size );
				// Display author name
				printf( __( '<cite class="fn">%s</cite> <span class="says">says:</span>', 'textdomain' ), get_comment_author_link() ); ?>
			</div><!-- .comment-author -->
			<div class="comment-details">
				<div class="comment-meta commentmetadata">
					<a href="<?php echo htmlspecialchars( get_comment_link( $comment->comment_ID ) ); ?>"><?php
						/* translators: 1: date, 2: time */
							__( '%1$s at %2$s', 'textdomain' ),
						); ?>
					edit_comment_link( __( '(Edit)', 'textdomain' ), '  ', '' ); ?>
				</div><!-- .comment-meta -->
				<div class="comment-text"><?php comment_text(); ?></div><!-- .comment-text -->
				// Display comment moderation text
				if ( $comment->comment_approved == '0' ) { ?>
					<em class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.', 'textdomain' ); ?></em><br/><?php
				} ?>
				<div class="reply"><?php
				// Display comment reply link
				comment_reply_link( array_merge( $args, array(
					'add_below' => $add_below,
					'depth'     => $depth,
					'max_depth' => $args['max_depth']
				) ) ); ?>
			</div><!-- .comment-details -->
		if ( 'div' != $args['style'] ) { ?>
		<?php }
	// IMPORTANT: Note that we do NOT close the opening tag, WordPress does this for us
	endswitch; // End comment_type check.

This is a starter template for you to work with, which includes the basic output you’ll want for your comments with some extra divs included for easier styling.

Step 2: Include your new better-comments.php Template

Place the newly created file inside your parent or child theme then go to your functions.php file and use the require_once function to load your file. See the example below (make sure to change the location if you’ve added the better-comments.php file to a different subfolder in your theme – I usually put my custom functions in a functions or inc folder to keep it seperate from the core template files).

Note: The snippet below has 2 examples you’ll want to use the correct line of code depending if you are adding the template into a parent or child theme.

// Include better comments file from a Parent theme
require_once get_parent_theme_file_path( '/functions/better-comments.php' );

// Or include via a child theme
require_once get_stylesheet_directory() . '/functions/better-comments.php';

You can add the code wherever you want in your functions.php file, just make sure to add it within the <?php and ?> tags.

Step 3: Add Better Comments Callback To wp_list_comments

Now we just need to tell WordPress to use our custom output template for the comments. And there are two ways to do this depending on if you are working with a parent or altering the default parent theme function (aka a child theme or plugin).

Parent theme: If you are working with a parent theme you’ll want to locate the comments.php file and you will want to edit the wp_list_comments function to include the callback in the arguments array like such:

// Display comments
wp_list_comments( array(
    'callback' => 'better_comments'
) ); ?>

Child theme or plugin: If you are working with a child theme or a plugin and want to filter the comment html output than you want to use the wp_list_comments_args filter and pass on your new callback argument like such:

// Filter the comment list arguments
add_filter( 'wp_list_comments_args', function( $args ) {
    $args[ 'callback' ] = 'better_comments';
	return $args;
} );

And of course, in both cases we are referencing the function name we used in step 1 (better_comments).

Step 4: Tweaking The Custom HTML Output

If you did everything correctly WordPress will now use your better_comments function for the comment html output in your theme. As opposed to just using the wp_list_comments function you can now edit all the code that will show up with each comment. Now the “sky is the limit”. Edit your function to make WordPress comments look the way YOU want. Below are some examples of the awesome stuff you can do:

Display Pingbacks & Regular Comments Differently

If you look at the code you can see it has a switch statement which is used to display the pingbacks/trackbacks differently than standard comments. While we normally recommend disabling the pingbacks/trackbacks if you use them on your site or you want them to look good for your end product (if you are a theme developer) then you can use this method to completely alter the output depending on the comment type.

Display a comment user “badge”

If you are running a community style blog where your readers are logged in you could insert a “badge” for each comment that shows the “role” of the person whom left the comment. So you could display a badge for subscriber, contributor, author, administrator…etc.

global $wp_roles;
if ( $wp_roles ) {
	$user_id = $comment->user_id;
	if ( $user_id && $user = new WP_User( $user_id ) ) {
		if ( isset( $user->roles[0] ) ) { ?>
			<div class="comment-user-badge <?php echo esc_attr( $user->roles[0] ); ?>"><?php esc_html( translate_user_role( $wp_roles->roles[ $user->roles[0] ]['name'] ) ); ?></div>'
		<?php }
	} else { ?>
		<div class="comment-user-badge guest"><?php esc_html_e( 'Guest', 'textdomain' ); ?></div>
	<?php }

Change Gravatar Size

Another cool thing you can do with the better comments is change the avatar size, we’ll sure, you could have changed it via the wp_list_comments array manually or using the wp_list_comments_args filter but now you can also manually change it, this means you could even use different sizes depending on the comment (maybe you want the author avatar to be larger, that could cool).

Change Default Gravatar or Remove It Completely

You could modify the get_avatar function to add a 3rd parameter for a default gravatar if you want to manually set the URL of your default avatar icon. This means you could add a fun default avatar that matches your website. Alternatively, you could remove the avatar code completely if you rather not use them (this can be a good idea for sites with tons of comments as gravatars can load a bit slow and also bloat up the site).

<?php echo get_avatar( $comment, $avatar_size, 'URL TO CUSTOM DEFAULT AVATAR' ); ?>


Download The WPSaviour App Now

Related posts

How To Use Pop-ups Without Harming SEO


10 WordPress Resources You Need to Bookmark Right Now


An Intro to the Anatomy of a WordPress Theme


Redesigning Your WordPress Website To Add a Personal Touch (The Sequel)

Sign up for our Newsletter and
stay informed

Leave a Reply

Your email address will not be published.