Blog: Starting a new design for my blog – part 9 (More Posts)
In previous posts, I’ve looked at the following aspects of making a WordPress theme
- Taking the time to plan, and prototype our theme before converting it to a compatible theme.
- Dynamic Menus; Page and Search Templates
- Using the WordPress Loop.
- Working with single.php templates.
- Using and managing WordPress widgets.
- Using Pagination methods.
- Category and Author Templates.
I want to dedicate this next blog in my WordPress Theme series to the discussion and comments system.
This is a useful exploration for me because as it stands today (15-03-2023), I have comments for blog posts in my official blog but they’re not specific to each blog post.
Allowing comments
The capability to add comments to a post is made available in the admin area. There are a couple of settings you need to know about to make this happen
(settings -> discussion page)
Under “Other comment settings” make sure the following setting is checked: “Comment author must fill out name and email”.
Other settings to look at include
- Requiring users to be logged in before they can add a comment – “Users must be registered and logged in to comment“
- Automatically close comments on posts older than [N] days – “ [N] “
- For the ability to add page pagination – “Break comments into pages with“
From this point on the blog will be looking at comments/discussion in PHP code; taken from the WordPress Developer Handbook.
Pull in the comments template
Here’s the code snippet that looks for comments.php and if it exists, displays its contents. This should go in an appropriate place in your single.php template. It checks that comments have been allowed in the admin area or has at least one comment posted. And if it does, returns what it finds.
<php
// single.php - If comments are open or we
// have at least one comment, load up the comment template.
if ( comments_open() || get_comments_number() ) :
comments_template();
endif;
In comments.php you can put in a simple bit of text to ensure that the condition check is working and showing the template.
<?php echo "<p>comments.php - successfully retrieved</p>";
If you see those words on the screen, the check has worked.
The comments template itself requires a number of components
- A comment header
- A user password protection check
- A check to see if there are comments associated with a post
- The comment listing
- Some pagination
A customisable comment header
The comment header exists to simply identify the template.
<?php
/**
* The template for displaying Comments.
*
* The area of the page that contains comments and the comment form.
*
* @package WordPress
* @subpackage A_Theme_Title
* @since Theme Title 1.0
*/
Let’s make sure the comments.php template exists and is working.
Remember what we’ve done so far with single.php is make a simple check for the WordPress comments template. With a simple condition check we can load the comments list but only if WordPress detects that a post has comments.
This is done with a simple WordPress function, have_comments().
<?php if ( have_comments() ) : ?>
. . .
<?php endif; ?>
If there are comments, it returns an area of HTML, in single.php designed to contain all comments associated with a post. All this inside a containing <div> element.
<div id="respond" class="comment-respond">
</div>
Function Reference as per WordPress Handbook – [Link]
This is a list of the comment functions used on comment templates – per the function reference in the handbook.
wp_list_comments(): Displays all comments for a post or Page based on a variety of parameters including ones set in the administration area.
comment_form(): This tag outputs a complete commenting form for use within a template.
comments_template(): Load the comment template specified in the first argument
paginate_comments_links(): Create pagination links for the comments on the current post.
get_comments(): Retrieve the comments with possible use of arguments
get_approved_comments(): Retrieve the approved comments for post id provided.
Making sure comments.php is working
We’ve already made sure single.php and comments.php are “talking” to each other, as it were.
<?php
echo "<p>comments.php has successfully been found</p>";
?>
Now let’s look deeper at the code to make sure it’s doing what it needs to do. At this point, we’re assuming we’ve applied the settings correctly so that comments work.
With this code example in single.php, we’re loading in the comment template only when comments have been turned on and or there’s an existing comment. It’s a check that loads the comment template when it’s appropriate to do so.
// If comments are open or we have at least one
// comment, load up the comment template.
if ( comments_open() || get_comments_number() ) :
comments_template();
endif;
The comment_form() method is what actually displays the form for adding new comments.
<?php if ( have_comments() ) : ?>
. . .
<?php endif; ?>
<?php comment_form(); ?>
It will return HTML including a form element inside a container div element.
<div id="respond" class="comment-respond">
comment form fields
</div>
And inside goes the HTML form with some hidden fields that WordPress uses to do the database magic behind the scenes.
<form action=""><p class="logged-in-as"> . . . </p>
<p class="comment-form-submit"> . . . </p>
<p class="form-submit">
<input name"submit" class="submit" />
</p>
</form>
The fields we’re concerned about are
- A text area field for writing your comment
- And a “Submit” button
There are also some hyperlinks that let the user log out of their WordPress user account and also edit their profile.
The complete list of CSS selectors to style this form looks like this.
comment-respond {
.comment-reply-title {
}
.comment-form {
.logged-in-as {
.required-field-message {
.required {
}
}
}
.comment-form-comment {
#comment {
}
}
.form-submit {
.submit {
}
}
}
We can add a style to the title
<!-- ID: #respond class: .comment-respond -->
<h3 class="comment-reply-title"> logged in
Leave a Reply
<small></small>
</h3>
A more detailed HTML snippet for the comment form is below…
<form class="comment-form">
<p class="logged-in-as">
<a>
<span class="required-field-message">required fields marked *</span>
<p class="comment-form-comment">
<label for="comment">
<span class="required">*</span>
</label>
<textarea id="comment"></textarea>
</p>
<p class="form-submit">
<input type="submit" class="submit">
</p>
</form>
Working with the Comments list
Styling for when comments exist in a WordPress post is controlled with the .comments-area div element. It exists on the same level in the document tree as the comment-respond class.
<div id="comments" class="comments-area">
</div>
Inside is an ordered list
<ol class="comment-list"> <ol>
It gets more complicated when you go deeper into the list element. It returns a whole host of classes that identify specific users and more general classes that you can use for CSS styling.
<ol class="comment-list">
<li class="comment byuser">
<div class="comment-body">
<div class="comment-author">
<div class="comment-meta"></div>
<div class="reply">
<a comment-reply-link></a>
</div>
</div>
</div>
</li>
</ol>
The code snippet below shows the wp_list_comments() function generates its own unordered list for threaded comments. Each page of paginated comments (we’ll get to this later in this blog) resets the numbered list back to one and threaded posts have their own separate numbered system as well.
<ol class="comment-list">
<?php
wp_list_comments( array(
'style' => 'ol',
'short_ping' => true,
'avatar_size' => 74,
) );
?>
</ol><!-- .comment-list -->
If there are no comments or comments are closed for whatever reason you can add a simple message to your theme.
<?php if ( ! comments_open() && get_comments_number() ) : ?>
<p class="no-comments">
<?php _e( 'Comments are closed.',
'textdomain' ); ?>
</p>
<?php endif; ?>
Pagination for comments
WordPress comment templates have their own pagination system. It’s activated and controlled in the admin area with the Discussion setting, “admin area setting Break comments into pages with [N] top level comments per page“.
The function below is just a simple function that provides a simple row of numbered pagination links which is similar to the the_posts_pagination() method in your standard templates
<!-- Numbered pagination links -->
<div class="pagination">
<?php paginate_comments_links(); ?>
</div>
What we have below is a check for comment_pages count, that there are more than one pages of comments for the template to display. If there is only one, there’s no need to display any pagination links.
You can also modify the string arguments in the pagination methods to suit your design.
<?php if ( get_comment_pages_count() >
1 && get_option( 'page_comments' ) ) : ?>
<nav class="navigation comment-navigation">
<h3 class="screen-reader-text section-heading">
<?php _e( 'Comment navigation', 'jgdm_blog' ); ?>
</h3>
<div class="nav-previous">
<?php previous_comments_link( __(
'← Older Comments', 'jgdm_blog' ) );
?>
</div>
<div class="nav-next">
<?php next_comments_link( __(
'Newer Comments →', 'jgdm_blog' ) );
?>
</div>
</nav><!-- .comment-navigation -->
<?php endif; // Check for comment navigation ?>
Conclusion
I have a fresh WordPress installation and in this installation (and my code) I have a comments system with comments lists specific to a blog post.
comment list pagination links if a comment list exceeds the setting in the admin area (“Break comments into pages with…”) I have a numbered row of pagination links as well as the links provided by the methods, previous_comments_link() and next comment_link().


