• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Creating Your First Custom Standard WordPress Comment Templates Without Breaking Site Responsiveness

Creating Your First Custom Standard WordPress Comment Templates Without Breaking Site Responsiveness

Understanding WordPress Comment Template Hierarchy

Before diving into customization, it’s crucial to grasp how WordPress resolves comment templates. When a theme needs to display comments, it follows a specific hierarchy. The primary template file for comments is comments.php. However, WordPress also looks for more specific templates based on the post type. For instance, if you’re on a custom post type called ‘product’, WordPress will first look for product-comments.php. If that’s not found, it falls back to comments.php. This hierarchy is key to creating targeted comment displays without affecting other parts of your site.

Creating a Basic Custom Comment Template

Let’s start with a straightforward modification. We’ll create a new comments.php file in our theme’s root directory. If your theme already has one, we’ll be modifying it. If not, we’ll create it from scratch. This file will contain the HTML structure and PHP logic to display comments and the comment form.

Here’s a minimal comments.php structure:

<?php
/**
 * The template for displaying comments.
 *
 * This file is used to display the comments.
 *
 * @package YourThemeName
 */

if ( post_password_required() ) {
    return;
}
?>

<!-- wp:paragraph --><div id="comments" class="comments-area">

    <?php if ( have_comments() ) : ?>
        <h2 class="comments-title">
            <?php
                $comment_count = get_comments_number();
                if ( 1 === $comment_count ) {
                    esc_html_e( 'One thought on “%1$s”', 'yourthemename' );
                } else {
                    printf( esc_html__( '%1$s thoughts on “%2$s”', 'yourthemename' ), number_format_i18n( $comment_count ), get_the_title() );
                }
            ?>
        </h2>

        <ol class="comment-list">
            <?php
                wp_list_comments( array(
                    'style'       => 'ol',
                    'short_ping'  => true,
                    'avatar_size' => 60,
                ) );
            ?>
        </ol><!-- .comment-list -->

        <?php if ( get_comment_pages_count() > 1 && get_option( 'page_comments' ) ) : ?>
        <nav id="comment-nav-below" class="comment-navigation">
            <h1 class="screen-reader-text"><?php esc_html_e( 'Comment navigation', 'yourthemename' ); ?></h1>
            <div class="nav-previous"><?php previous_comments_link( esc_html__( '&#8678; Older Comments', 'yourthemename' ) ); ?></div>
            <div class="nav-next"><?php next_comments_link( esc_html__( 'Newer Comments &#8680;', 'yourthemename' ) ); ?></div>
        </nav><!-- #comment-nav-below -->
        <?php endif; ?>

    <?php endif; ?>

    <?php
    // If comments are closed and there is no comment status, leave the comments template.
    if ( ! comments_open() && get_comments_number() && post_type_supports( get_post_type(), 'comments' ) ) :
    ?>
        <p class="no-comments"><?php esc_html_e( 'Comments are closed.', 'yourthemename' ); ?></p>
    <?php endif; ?>

    <?php
    comment_form( array(
        'comment_field' => '<div><label for="comment">' . esc_html__( 'Comment', 'yourthemename' ) . '</label><textarea id="comment" name="comment" cols="45" rows="8" aria-required="true"></textarea></div>',
        'class_submit' => 'submit',
        'label_submit' => esc_html__( 'Post Comment', 'yourthemename' ),
    ) );
    ?>

</div><!-- #comments -->

In this example:

  • We check if the post is password protected.
  • We use have_comments() to see if there are any comments to display.
  • get_comments_number() and get_the_title() are used to dynamically generate the comment count heading.
  • wp_list_comments() is the core function that iterates through and displays each comment. We’ve passed arguments for styling, short ping, and avatar size.
  • Comment pagination is handled with get_comment_pages_count(), previous_comments_link(), and next_comments_link().
  • The comment form is displayed using comment_form(). We’ve customized the ‘comment_field’ and ‘label_submit’ arguments.
  • All output is escaped using WordPress’s sanitization functions like esc_html_e() and esc_html__() for security.

Styling Your Custom Comments

The PHP file only structures the HTML. To make it look good and ensure responsiveness, you’ll need to add CSS. This CSS should be placed in your theme’s style.css file or a dedicated CSS file enqueued by your theme.

Here’s some example CSS to get you started:

.comments-area {
    margin-top: 30px;
    padding: 20px;
    background-color: #f9f9f9;
    border: 1px solid #eee;
    border-radius: 5px;
}

.comments-title {
    font-size: 1.8em;
    margin-bottom: 20px;
    border-bottom: 1px solid #ddd;
    padding-bottom: 10px;
}

.comment-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.comment-list .comment {
    margin-bottom: 25px;
    padding-bottom: 25px;
    border-bottom: 1px dotted #ccc;
    display: flex; /* For avatar alignment */
    align-items: flex-start; /* Align items to the top */
}

.comment-list .comment:last-child {
    border-bottom: none;
    margin-bottom: 0;
    padding-bottom: 0;
}

.comment-author .avatar {
    margin-right: 15px;
    border-radius: 50%;
    width: 60px; /* Matches avatar_size in wp_list_comments */
    height: 60px;
    flex-shrink: 0; /* Prevent avatar from shrinking */
}

.comment-body {
    flex-grow: 1; /* Allow comment body to take remaining space */
}

.comment-meta {
    font-size: 0.9em;
    color: #777;
    margin-bottom: 10px;
}

.comment-author .fn {
    font-weight: bold;
    color: #333;
}

.comment-content p {
    margin-bottom: 15px;
    line-height: 1.6;
}

.comment-reply-link {
    display: inline-block;
    margin-top: 10px;
    padding: 5px 10px;
    background-color: #eee;
    border-radius: 3px;
    text-decoration: none;
    color: #555;
}

.comment-reply-link:hover {
    background-color: #ddd;
}

/* Comment Form Styling */
.comment-form {
    margin-top: 30px;
    padding-top: 30px;
    border-top: 1px solid #eee;
}

.comment-form label {
    display: block;
    margin-bottom: 10px;
    font-weight: bold;
}

.comment-form input[type="text"],
.comment-form input[type="email"],
.comment-form input[type="url"],
.comment-form textarea {
    width: 100%;
    padding: 10px;
    margin-bottom: 15px;
    border: 1px solid #ccc;
    border-radius: 4px;
    box-sizing: border-box; /* Include padding and border in the element's total width and height */
}

.comment-form textarea {
    min-height: 120px;
    resize: vertical;
}

.comment-form .submit {
    background-color: #0073aa;
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 1em;
    transition: background-color 0.3s ease;
}

.comment-form .submit:hover {
    background-color: #005177;
}

/* Responsive adjustments */
@media (max-width: 768px) {
    .comments-area {
        padding: 15px;
    }
    .comment-list .comment {
        flex-direction: column; /* Stack avatar and comment body on smaller screens */
        align-items: center; /* Center items when stacked */
        text-align: center;
    }
    .comment-author .avatar {
        margin-right: 0;
        margin-bottom: 15px;
    }
    .comment-body {
        text-align: left; /* Align comment text left when stacked */
    }
    .comment-form input[type="text"],
    .comment-form input[type="email"],
    .comment-form input[type="url"],
    .comment-form textarea {
        width: calc(100% - 20px); /* Adjust for padding */
    }
}

Advanced: Customizing Comment Structure with `wp_list_comments` Callbacks

For more granular control over how each individual comment is displayed, you can use the callback argument of the wp_list_comments() function. This allows you to define a custom PHP function that will be responsible for rendering each comment’s HTML.

First, define your callback function. This function will receive an object containing comment data as its argument. You can place this function in your theme’s functions.php file.

<?php
/**
 * Custom callback for displaying comments.
 *
 * @param object $comment The comment object.
 * @param array  $args    An array of comment arguments.
 * @param int    $depth   The depth of the comment.
 */
function my_custom_comment_callback( $comment, $args, $depth ) {
    $GLOBALS['comment'] = $comment; // Ensure the global $comment object is available
    ?>
    <li id="comment-<?php comment_ID(); ?>" <?php comment_class( empty( $args['toplevel_comment'] ) ? 'comment' : 'comment depth-' . $depth ); ?>>
        <article id="div-comment-<?php comment_ID(); ?>" class="comment-body">
            <footer class="comment-meta">
                <div class="comment-author vcard">
                    <?php if ( 0 != $comment->user_id ) echo get_avatar( $comment, $args['avatar_size'] ); ?>
                    <?php printf( '<b class="fn">%s</b>', get_comment_author_link() ); ?>
                    <span class="says"><?php esc_html_e( 'says', 'yourthemename' ); ?></span>
                </div><!-- .comment-author -->

                <div class="comment-metadata">
                    <a href="<?php echo esc_url( get_comment_link( $comment->comment_ID ) ); ?>">
                        <time datetime="<?php comment_time( 'c' ); ?>">
                            <?php printf( esc_html__( '%1$s at %2$s', 'yourthemename' ), get_comment_date(), get_comment_time() ); ?>
                        </time>
                    </a>
                    <?php edit_comment_link( esc_html__( 'Edit', 'yourthemename' ), '<span class="edit-link">', '</span>' ); ?>
                </div><!-- .comment-metadata -->
            </footer><!-- .comment-meta -->

            <div class="comment-content">
                <?php comment_text(); ?>
            </div><!-- .comment-content -->

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

            <div class="reply">
                <?php
                comment_reply_link( array_merge( $args, array(
                    'add_below' => 'div-comment',
                    'depth'     => $depth,
                    'max_depth' => $args['max_depth'],
                ) ) );
                ?>
            </div><!-- .reply -->
        </article><!-- .comment-body -->
    <?php // The closing  tag is handled by wp_list_comments() when using the callback.
}
?>

Then, in your comments.php file, you’ll pass this function to wp_list_comments():

<?php
// ... inside your comments.php file ...

<?php if ( have_comments() ) : ?>
    <h2 class="comments-title">...</h2>

    <ol class="comment-list">
        <?php
            wp_list_comments( array(
                'style'    => 'ol',
                'callback' => 'my_custom_comment_callback', // Use your custom callback function
                'avatar_size' => 60,
                'max_depth' => 5, // Set a maximum depth for nested comments
            ) );
        ?>
    </ol><!-- .comment-list -->

    // ... pagination and comment form ...

<?php endif; ?>

This callback approach gives you complete control over the HTML structure for each comment, including nested replies. You can add custom classes, attributes, or even conditionally display elements based on comment data.

Advanced Diagnostics: Troubleshooting Common Issues

When implementing custom comment templates, several issues can arise. Here’s how to diagnose and fix them:

Issue: Comments Not Displaying

  • Check comments.php existence: Ensure comments.php is in your theme’s root directory. If using a child theme, it must be in the child theme’s directory.
  • Verify have_comments(): Add a temporary <?php echo '<p>Debug: Have comments? ' . (have_comments() ? 'Yes' : 'No') . '</p>'; ?> before the comment loop in your comments.php. If it outputs ‘No’, the issue might be with the post itself (e.g., comments are disabled for that post type or globally).
  • Check wp_list_comments() arguments: Ensure the arguments passed to wp_list_comments() are valid. Incorrect arguments can cause the function to fail silently.
  • Theme conflicts: Temporarily switch to a default WordPress theme (like Twenty Twenty-Three) to rule out conflicts with other plugins or theme features. If comments display correctly on the default theme, the problem lies within your custom theme.

Issue: Comment Form Not Appearing

  • Check comments_open(): Ensure comments are enabled for the post and globally in WordPress settings (Settings > Discussion). Add a debug line: <?php echo '<p>Debug: Comments open? ' . (comments_open() ? 'Yes' : 'No') . '</p>'; ?>.
  • Verify comment_form() call: Make sure comment_form() is called correctly within your comments.php file.
  • Plugin conflicts: Some security or form plugins might interfere with the default comment form. Test by deactivating other plugins.
  • Theme structure: Ensure the comment_form() call is not wrapped in a conditional that prevents it from being displayed (e.g., inside an if (!is_user_logged_in()) block without an `else` for logged-in users).

Issue: Responsiveness Problems (Layout Breaks on Mobile)

  • Inspect CSS: Use your browser’s developer tools (Inspect Element) to examine the HTML structure and applied CSS. Look for elements that are not behaving as expected on smaller viewports.
  • Check box-sizing: Ensure your CSS uses box-sizing: border-box; for form elements and containers. This is crucial for predictable sizing with padding and borders.
  • Flexbox/Grid issues: If you’re using Flexbox or CSS Grid for layout (e.g., aligning avatars), ensure you have appropriate media queries to adjust the layout for smaller screens. The example CSS provided uses Flexbox with a media query to stack elements vertically on smaller screens.
  • Fixed-width elements: Avoid using fixed pixel widths for elements that should be fluid. Use percentages, `vw` units, or `max-width` instead.
  • Image/Avatar sizes: Ensure avatars and other images are responsive. The example CSS sets a fixed avatar size but uses `flex-shrink: 0` to prevent it from distorting and `max-width: 100%` on images within the comment content.

Issue: Nested Comments Display Incorrectly

  • Check $depth in callback: If using a custom callback, ensure the $depth variable is correctly passed and used to apply appropriate CSS classes (e.g., depth-X) for indentation.
  • CSS for nesting: Your CSS needs to account for nested comments. Typically, this involves adding left padding to elements with higher depths. For example: .comment-list .depth-2 { margin-left: 20px; } .comment-list .depth-3 { margin-left: 40px; }.
  • max_depth argument: Ensure the max_depth argument in wp_list_comments() is set appropriately if you want to limit the nesting level.

Conclusion

By understanding the WordPress comment template hierarchy and leveraging functions like wp_list_comments() with custom callbacks, you can create highly customized and responsive comment sections for your WordPress themes. Remember to always prioritize security by escaping output and to thoroughly test your customizations across different devices and browsers.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability
  • Scala Pekko vs. Go Goroutines: Actor Model vs. CSP for Event-Driven Reactive Systems
  • Java Loom Virtual Threads vs. Go Goroutines: Under-the-Hood Scheduler and Thread Overhead Comparison

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (584)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (806)
  • PHP (5)
  • PHP Development (21)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (19)
  • Ruby on Rails (1)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (357)

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (806)
  • Debugging & Troubleshooting (584)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala