How to output custom HTML for WordPress comments

Ralph J. Smit Laravel Software Engineer

When you're developing a WordPress theme, chances are that you want to or need to implement comments. WordPress makes this really easy with the wp_list_comments() function. How do we output the comments in a custom HTML format?

The wp_list_comments() function can take over fourteen arguments, so you would think: choices enough! But unfortunately, there is no parameter with which you can modify the HTML output. You can of course apply CSS, but sometimes you do need a different HTML output to accomplish a certain design.

In this tutorial I'll demonstrate how to use a custom function to output WordPress comments.

A short recapitulation

The following should be part of your comments.php template in most cases. There is a unordered list as a container (<ul>), because the wp_list_comments() only outputs list items (<li>).

<!-- Comments list -->
<ul id="comments" class="rjs-comments-list">
 
<?php wp_list_comments( [
'type' => 'comment', //Don't output pingbacks & trackbacks
'reverse_top_level' => true, //Newest first
'max_depth' => 20, //Maximum comments depth
] ); ?>
 
</ul>

Note: it's not 100 per cent correct that the wp_list_comments() only outputs <li> elements. It can also output <div> elements by using the 'style' argument. See the Codex.

Export custom HTML from comments

In order to export custom HTML, we'll use a callback function. A callback function is a PHP function that replaces the default function which determines the HTML output. If we define our own function, we can choose what to output. Thus, let's add the following:

  1. a call to a function with the custom HTML output; and

  2. the callback function itself (in the functions.php or in a different PHP-file).

Adding the callback function to `wp_list_comments()`

How does this look like? We'll add the argument 'callback' and the function name.

'callback' => 'rjs_comments_walker',
 
//This references the function rjs_comments_walker() { /// }
<!-- Comments list -->
<ul id="comments" class="rjs-comments-list">
 
<?php wp_list_comments( [
'type' => 'comment', //Don't output pingbacks & trackbacks
'reverse_top_level' => true, //Newest first
'max_depth' => 20, //Maximum comments depth
'callback' => 'rjs_comments_walker',
] ); ?>
 
</ul>

Writing the callback function

In our functions.php, we'll start by adding the basic markup for the callback function. Then, you can modify it to your own liking. For this tutorial, I took the code I used on my website as the basis.

<?php
function rjs_comments_walker() { ?>
 
<li class="rjs-comment" id="comment-<?php comment_ID() ?>">
 
 
<!-- Adding the reply button -->
<div class="rjs-comment-reply">
<?php comment_reply_link( [
'add_below' => true,
'depth' => 20,
'max_depth' => 200,
'before' => '<div class="reply">',
'after' => '</div>'
] ); ?>
</div>
 
</li>
 
<?php }

As a short explanation, I first added the 'container' list item. This list item each has a unique id, generated with the comment_ID() function. In this way, you can use an anchor link to navigate to a specific comment.

The second thing I added, is the function that outputs a reply link. Together with the first <li>, this makes up the 'frame' of each comment.

Keep your file structure organised

It is okay if you place the callback function in the functions.php. Better still, is to create a new PHP file (like comment-callback.php) and require that file from the functions.php.

Adding more content

Let's now add more content. We'll add the author avatar, the author name and url, the date and of course the comment itself. There are a lot of WordPress functions that are usable to retrieve information about an individual comment.

How to add avatars to WordPress comments

We'll first get the author e-mail and then retrieve the avatar. We check if the option to show avatars is set to true in the WordPress admin. If yes, we place the avatar on the right place.

<?php
$rjs_comment_email = get_comment_author_email();
$rjs_gravatar = get_avatar( $rjs_comment_email, 160 ); //Second argument is the avatar size
 
<?php if (get_option('show_avatars', true) && $rjs_gravatar) : ?>
<div class="rjs-comment-authorimage"><?php if ($rjs_gravatar) { echo $rjs_gravatar; } ?></div>
<?php endif; ?>
How to get WordPress comment author information

We'll check if there's an author URL. If so, the author name is a link. If not, the author name is just plain text.

<div class="rjs-comment-authorinfo rjs-sans">
<?php if (get_comment_author_url()) : ?>
<a href="<?php echo get_comment_author_url(); ?>" rel="external nofollow ugc" class="rjs-comment-authorurl rjs-comment-authorname url"><?php echo get_comment_author(); ?></a>
<?php else : ?>
<p class="rjs-comment-authorname"><?php echo get_comment_author(); ?></p>
<?php endif; ?>
Getting the WordPress comment text

Next we'll retrieve the text of the comment itself. This is perhaps the most easy part of everything.

<p class="rjs-comment-text"><?php echo get_comment_text(); ?></p>

The overview

My complete code, including indentation, looks like the following:

<?php
function rjs_comments_walker() {
$rjs_comment_email = get_comment_author_email();
$rjs_gravatar = get_avatar( $rjs_comment_email, 160 ); ?>
 
<li class="rjs-comment" id="comment-<?php comment_ID() ?>">
 
<div class="rjs-comment-body comment-body">
 
<?php if (get_option('show_avatars', true) && $rjs_has_gravatar) : ?>
<div class="rjs-comment-authorimage"><?php if ($rjs_gravatar) { echo $rjs_gravatar; } ?></div>
<?php endif; ?>
 
<div class="rjs-comment-authorinfo rjs-sans">
<?php if (get_comment_author_url()) : ?>
<a href="<?php echo get_comment_author_url(); ?>" rel="external nofollow ugc" class="rjs-comment-authorurl rjs-comment-authorname url"><?php echo get_comment_author(); ?></a>
<?php else : ?>
<p class="rjs-comment-authorname"><?php echo get_comment_author(); ?></p>
<?php endif; ?>
<p class="rjs-comment-date"><?php echo get_comment_date(); ?></p>
</div>
 
<p class="rjs-comment-text"><?php echo get_comment_text(); ?></p>
 
<div class="rjs-comment-reply">
<?php comment_reply_link( [
'add_below' => true,
'depth' => 20,
'max_depth' => 200,
'before' => '<div class="reply">',
'after' => '</div>'
] ); ?>
</div>
</div>
</li>
 
<?php }

💡Change the HTML format by modifying the above HTML.

In this way, you're not bound anymore to the default <li> or <div> format outputted by the wp_list_comments() function.

I hope this is useful if you want learn how to change the default HTML output with the WordPress comments function. Have you used this? Or do you have some other nifty trick? Let me know in the comments 👇

Published by Ralph J. Smit on in Wordpress-theme-development . Last updated on 12 March 2022 .