Learn Development at Frontend Masters
Comment threads are one of those things that look really simple when executed right. When designing them yourself, you may find that they are rather deceptively simple. There is a lot that goes into designing nice and usable comment threads, and in this article, I will try my best to walk you through the steps to building a comment thread, that is great to look at, and a joy to use.
Before diving into designing and writing code, let’s break down what actually makes a good comment thread. A good comment thread will have the following characteristics:
As you can see, that’s quite a lot to consider! There are also some nice-to-haves that we won’t cover in this article, but are certainly good enhancements:
The above features would require at least a bit of JavaScript to pull off. Moreover, depending on the tech stack, these features could just as likely be implemented server side, especially keeping track of the number of votes and flag status of comments. That is why we will focus only on styling the comment threads in this article. With that out of the way, let’s knock out the first set of points and design our comment thread.
A comment by itself has a pretty simple structure. Here’s a skeleton of a single comment:
So far, so good. Notice how the replies have an extra margin to the left. This is meant to satisfy the visual hierarchy (point #3 above). The markup for the above structure could look something like this:
There is nothing to explain here — just a bunch of containers with some basic elements. So instead, let’s look at a real-life example, with a comment that also has a reply.
Looks pretty nice, right? The above example satisfies the first three points, so we are already on our way. A few things to understand about the code above:
Now that we have a basic comment thread going, let’s add a feature to help users quickly scroll to a comment. As mentioned above, this is especially useful when someone wants to jump to the parent comment of a reply.
In order to build it, we need to decide what these links look like. While this is entirely subjective, one particular design I really like is a clickable “border” on the left hand side of the comment, something like this:
In order to accommodate the link, we are pushing the comment body to the right and aligning it with the replies. This design also has the added benefit of reinforcing the hierarchy between the comments, because you can simply look at the number of border links to the left and determine the level of nesting of the comment you are currently reading. And of course, you can also immediately jump to any upper level by clicking on the border links.
To actually create these border links, we need to add anchor elements (<a href="...">
) inside each of our comments, and style these anchor elements to look like the borders that can be clicked. Let’s add them to our first code example above.
Here are a few things to understand about the changes made:
With all that, we have knocked out the first four of the points mentioned above. Let’s add more comments to the code example to see how it would look.
At this point, we have a pretty darn satisfactory comment thread. This design by itself can work for quite a lot of real life use cases. However, let’s go one step farther and add our toggle feature, i.e. hiding and showing comments with a click.
The quickest and easiest way to allow users to hide and show comments with a click is to make use of the <details>
and <summary>
elements. To put it simply, the visibility of the entire <details>
can be toggled by clicking on the <summary>
. There is no JavaScript involved, and these tags are supported by ~96% of browsers at this moment. Once again, if you are unfamiliar with these concepts, you can learn more in yet another article from Chris.
Anyway, to actually implement this, we need to make the following changes to our code:
Seems easy enough. Anyway, here’s our new implementation:
Here are the final things to understand about the changes made:
Before we end this article, let’s talk about a few more things that is worth considering when designing comment threads in real-life applications.
This may be a very simple problem to solve, but it is often easy to overlook these simple things. If a comment thread does not have any comments (empty state), we need to communicate that clearly to the user. A simple paragraph containing the line “There are no comments yet.” along with a form containing a text box and submit button can go a very long way, and should be the bare minimum when dealing with empty states. If you want to go the extra mile, you can also have a nice image (that communicates the message) accompanying the form.
When it comes to the form for replying to a comment, different websites have different implementations. Some use the old fashioned way of redirecting users to a new page which contains the form — a simple text box with a submit button. Others open up a form right within the comment thread itself, usually with a simple toggle. The latter paradigm obviously requires JavaScript, but it is more more popular these days. For instance, in our example above, we could have a simple form which can be toggled by clicking on the Reply button, like so:
In the above example, we added simple forms inside the comment bodies, and gave them the class .d-none
by default, which sets display: none;
and hides them from view. Thanks to the simple event listener, any button with the attributes data-toggle="reply-form"
and data-target="{{ comment_reply_form_id }}
can be clicked to toggle the visibility of the forms. This is a very simple example of handling the reply forms with ease.
Let’s say a user replies to a comment using a form similar to the one shown above. Do you show it above the existing replies or below it? The answer is that it should always be shown above the other replies right after the user posts it for the first time. When a person fills out a form and submits it, they want immediate feedback to tell them that it worked. Therefore, by placing the new reply above the others, we are providing this feedback to the user without them needing to scroll down. On subsequent loads, you can of course arrange your comment replies according to whatever algorithm you see fit for your website.
Many websites, particularly developer blogs, need to support markdown and code blocks in their comments. This is a much bigger discussion, perhaps warranting a dedicated article on this topic. However, for the sake of this article, let’s just say that there are plenty of Markdown editors out there that you can attach to a text box quite easily. Most of them work with JavaScript, so they should be fairly easy to integrate in our examples. One such plugin is markdown-it, which has a permissive MIT license. You can also look into WYSIWYG editors, which also serve a very similar purpose when it comes to comments on the web.
If you give users a form to provide their inputs, you can guarantee that you will find spam coming your way, so this is obviously an issue to address when building comment threads. A great way to reduce spam is to use services like reCAPTCHA from Google. For instance, in our example above, a reCAPTCHA box could be placed right below the Submit button in the reply forms. This would protect our website from abuse.
Another way to prevent spam is to only allow authenticated users to post comments, i.e. a user must have an account and be logged in to post a comment. Every comment would obviously be linked to an account, so this has the benefit of allowing moderators to handle users who continuously post spam or low effort content. In terms of handling it in the UI, a great way of doing it is by redirecting users to a login page when they click on the Reply or Post comment button if they are not logged in. Once they complete the authentication process, we can simply redirect them back to the comment thread and open up the form.
And we are done! We have fulfilled all five of our points, and have designed a nice-looking comment thread that is highly usable and accessible, with some cool features like jumping to comments, and togging the visibility of each comment. We also talked about forms inside comment threads, and discussed other things to consider in real-life applications. The bulk of our comment thread works using only CSS (no JavaScript), which goes to show you how far CSS has actually come.
Frontend Masters is the best place to get it. They have courses on all the most important front-end technologies, from React to CSS, from Vue to D3, and beyond with Node.js and Full Stack.
Frontend Masters is the best place to get it. They have courses on all the most important front-end technologies, from React to CSS, from Vue to D3, and beyond with Node.js and Full Stack.
I feel that an important real-world requirement is that there is a limit to the nesting. As in, replying to a reply to a reply (etc.) at some point stops the indenting and use some other method to communicate a comment is a reply to another. Otherwise, at some point there would be no room
left for the comment. Any tips on that.
You don’t need to limit nesting, you can work around that. As an example Reddit allows infinite nesting replacing deeply nested comment chains with “continue this thread” links to individual comment pages where the rest of the chain the be accessed. Twitter does something similar. There is also this StackExchange question with other examples. If you still prefer limiting nesting those can still serve as examples.
I definitely agree with what qgustavor said. At some level of nesting, you have to change the base level of nesting with a “Continue this thread” link. Horizontal scrolling with a minimum width is another option, but I don’t think that is very user friendly. I am not entirely sure about this, but there might be some merit to a further discussion that addresses this issue in details.
You may write comments in Markdown thanks to Jetpack Markdown. This is the best way to post any code, inline like `<div>this</div>` or multiline blocks within triple backtick fences (“`) with double new lines before and after. All comments are held for moderation. Be helpful and kind and yours will be published no problem.
The related posts above were algorithmically generated and displayed here without any load on my server at all, thanks to Jetpack.
CSS-Tricks* is created, written by, and maintained by Chris Coyier and a team of swell people. The tech stack for this site is fairly boring. That’s a good thing! I’ve used WordPress since day one all the way up to v17, a decision I’m very happy with. I also leverage Jetpack for extra functionality and Local for local development.
*May or may not contain any actual “CSS” or “Tricks”.
CodePen is a place to experiment, debug, and show off your HTML, CSS, and JavaScript creations.
CSS-Tricks is hosted by Flywheel, the best WordPress hosting in the business, with a local development tool to match.
ShopTalk is a podcast all about front-end web design and development.