Justin Tadlock

Designing better nested comments

Screenshot of nested comments

I’ve always had a love/hate relationship with nested comments. I like the idea of finding replies to comments without having to scroll up and down the page. I hate how unruly they get when more than two or three levels deep.

In my most recent theme, Extant, and the newest theme I’m building, I’m testing a different design concept.

Most nested comment designs I’ve seen just keep indenting each level farther from the left. This gets messy quick. This new concept is based off how Facebook handles threads, only allowing one indention. Even replies to replies are lined up with the second level. You can get a feel for what I’m talking about in the above screenshot.

This is also far easier to handle on mobile devices where screen space is limited and cannot handle multiple levels of nested comments.

The design aspect

This is going to be different for each theme. Some designs use margin to make comments look nested. Some use padding. How you handle that will ultimately be up to you. I opted for stopping the “indentation” at the second level. You could go higher.

WordPress has some handy “depth” classes, which you can use. These are added to the individual comment wrapper. .depth-1 is added to the first-level comment. .depth-2 is added to the second-level comment. And, so on.

Each outter wrapping element (an <ol> by default) is given the .children class, starting with the second level.

Here’s a quick look at some example code for handling this sort of thing:

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

    .comment-list ol.children {
        list-style:  none;
        margin-left: 0;
    }

           .comment-list .depth-1 > ol.children { margin-left: 1.5rem; }

“In reply to” link

Part of the trouble with not indenting each level is that there’s no way to know which comment a level 3+ comment is in reply to. For that, I wrote a little PHP code to display a link, which you can see in the screenshot at the beginning of this post.

The following is both a function for outputting the link and a function for getting it.

function jt_comment_parent_link( $args = array() ) {

    echo jt_get_comment_parent_link( $args );
}

function jt_get_comment_parent_link( $args = array() ) {

    $link = '';

    $defaults = array(
        'text'   => '%s', // Defaults to comment author.
        'depth'  => 2,    // At what level should the link show.
        'before' => '',   // String to output before link.
        'after'  => ''    // String to output after link.
    );

    $args = wp_parse_args( $args, $defaults );

    if ( $args['depth'] <= $GLOBALS['comment_depth'] ) {

        $parent = get_comment()->comment_parent;

        if ( 0 < $parent ) {

            $url  = esc_url( get_comment_link( $parent ) );
            $text = sprintf( $args['text'], get_comment_author( $parent ) );

            $link = sprintf( '%s<a class="comment-parent-link" href="%s">%s</a>%s', $args['before'], $url, $text, $args['after'] );
        }
    }

    return $link;
}

Here’s how you’d use the function to output the link. This would go in whatever function you use to handle your comment callback (see docs on wp_list_comments() if you’ve never written a custom callback).

<?php jt_comment_parent_link(
    array(
        'depth'  => 3,
        'text'   => __( 'In reply to %s', 'extant' ),
        'before' => '<div class="comment-parent">',
        'after'  => '</div>'
    )
); ?>

That’s all we need to do to handle this different design for nested comments.

Other ideas?

At this point, I haven’t had enough feedback to determine whether this makes for a good user experience. It’s still in the early testing stages, but I like the idea.

A lot more can be done with it stylistically as well (e.g., colors, smaller avatars, etc.). I just wanted to share how I was handling the nesting aspect of it.

Have you tried anything different with your nested comment designs? I’d like to see how others are tackling this issue.