How to Animate Threaded Comments with CSS and jQuery

With many social applications the use of threaded comments has become a staple in functionality. Webmasters today are focusing much more on user experience rather than content generation, and because of this there has been a rise in custom animation effects.

Below I’ll be going over a guide to building your own custom jQuery threaded comments from scratch. For the ease of our tutorial we won’t be using any backend system to actually store the data anywhere. This means no MySQL databases or PHP calls to a server – all comments are added in-page and will be lost upon page refresh.

jQuery Animated Comments Thread

Granted, the system is very simple to work with and extrapolate data from. This tutorial not only introduces the inner workings of jQuery, but gives developers a framework of which to base a simple comments application on.

As always if you have questions feel free to post them in the comments below. Much of the code introduced here is easy to understand and well documented in the jQuery wiki.

Starting with Core HTML

To get started we should focus on document structure and HTML processing. Jumping into the beginning I’ve created a directory named jquery-comments which will include all of our project files. There isn’t much required to include here.

The list starts with an index.html and style.css document overview. These two docs will contain your page structure and layout, respectively. We’ll also need a .js file to house our custom jQuery functionality. I’ve named this file “jcs.js”, short for jQuery comments. But feel free to name the script anything you desire.

Full Preview for Application

The last step I’ve done is to create an images directory. Inside I have a few pre-cropped avatars for our example, along with a comment bubble icon for additional page effects. To get started let’s example the proper code inside index.html first!

[cc lang=”html”]

CSS/jQuery Animated Threaded Comments


We have a heading area just like any other webpage instilled at the top of our document. Inside we’ve included our style.css and also our remote JavaScript file. Additionally I’ve added the jQuery 1.4.2 miniaturized library hosted in Google’s code repositories. This has the benefit of reducing calls to the server at runtime and keeping your physical file count low.

Comment Blocks

Inside our body we have a division with an ID “comments”. Inside this is where all our code resides. To dive right in let’s examine a piece of code containing the first 3 page comments. The 1st in our set is the root node while the other two are threaded replies.

[cc lang=”html”]


userman posted 7 hr 32 min ago

Here is some sample text for a comment. Man what a nice day outside!



DuckDude posted 5 hr 11 min ago

Here is a unique rebuttal. Hmm…



snowhockey1 posted 4 hr 16 min ago

Also, by the way if you were wondering. This isn’t a real username it’s actually pretty fake.



The code may seem a bit messy at first, but each section does have an echo effect. Each comment in-page is housed inside a div with the class “comment-thread”. The container divisions for “comment-block” houses all of the comment information.

This includes the username and avatar, date/time of posting, comment content, and reply button. Directly after this area we have a new opening division classed under “thread-replies”. Note this is still inside our root node “comment-thread” and will contain further threaded replies to our original.

Linux Reboot Kernels

If you examine the threaded replies closely you’ll notice not only are they also enclosed inside a “comment-thread” but each has their own “thread-replies” section. For internal comments this div is left blank on purpose – this is how we can use jQuery to manipulate and add further comments without refreshing the page.

You may also notice each comment-block contains a unique ID parameter. This would be set by an internal system giving each new comment an incrementing ID value. I’ve generated static values and added them directly into the HTML code per this example, although it’s fully customizable from any alternative CMS.

Accessing the DOM with jQuery

The Document Object Model is a structural way of viewing each web page. It’s built upon HTML nodes which are referenced with each page element and housed within contain child element(s).

With jQuery we are able to access individual elements in our page and manipulate their information. Not only this, but we are also able to add new page elements without even so much as a refresh! Getting started with jQuery code, added below is the first few lines in our script.

[cc lang=”javascript”]$(document).ready(function() {
var totalcommid = 31;

$(“.option-reply”).live(“click”, function() {

We start off with a standard document.ready() clause checking if our page has fully loaded. Once the DOM is ready we can start calling functions and pulling data. We have a single variable set named totalcommid. This is a static number put in place so we don’t accidentally overwrite any existing comment IDs.

The next line is a selector targeting all elements under the classname “option-reply”. These happen to be the small “Reply” hyperlinks placed after each comment. Our code is checking for a click event handler to call an internal function.

In layman’s terms this means jQuery puts a trigger on each “reply” link in our page. Every time one of them is clicked we have an internal function called to display a new comment text field. Once added we either have the option of closing the comment box or adding new content and appending our comment into the thread.

[cc lang=”javascript”]var currtxt = $(this).text();
var curroptlink = $(this);
var cid = $(this).parent().parent().parent().attr(“id”);
var poundcid = “#link-“+cid;

var htmlform = ‘<form id=”commsubform”><label>Add Comment:</label> <textarea id=”thecomment” class=”commtxtfield”></textarea> <br /><br /> <a class=”savecommbtn” id=”link-‘+cid+'”>Save Comment</a></form>’;

The first thing we set are common page variables which we’ll be accessing repeatedly. currtxt is set to the current selector’s text value. curroptlink is a selector targeting the current link we’ve just clicked. Although the code seems mildly repetitive it can save time when manipulating data later in our function.

jQuery programming on laptop studio

cid is a unique variable which contains our current comment thread ID. This takes a bit of DOM traversing until we get to the proper parent element containing our ID value. This is one great aspect to working with jQuery since each comment we add will have the same format, thus our code is fully functional and expands regardless of how many threads.

Our htmlform variable should be pretty self-explanatory. It contains all the HTML code needed to embed into the page for a new comment form. Note we make good use of our cid variable by giving our save link the value of our next comment ID.

Functional Page Manipulation

From here we’ve got most of the variables we need set and ready. We’re already inside of our selector and just need to offer a few more bits of code to exercise.

Getting started we have to understand when our users want to show or hide the comment form. It should be just as easy to close a reply box as to open it. We can accomplish this task with two individual toggle functions based on the current link text.

[cc lang=”javascript”]// toggle between show/hide comment form views
if(currtxt == “Reply”) {
$(this).text(“Hide form”);

if(currtxt != “Reply”) {
curroptlink.parent().next(“.showhidecommform”).html(” “);

The logic here is very simple but works well for what we need. Broken apart we see 2 if conditional statements checking the value of our current link text. If the link text says “Reply” we add a new comment form and change the link text to “Hide Form”. If the opposite is true then we just reverse our actions.

The power over documents we control here is only accessible from the many variables we declared earlier in the script. We could change a few more things about the page when a reply link is clicked, although I’ll leave that for you to customize.

The last and final piece of code will translate our comment into an HTML block and append it into the page. Our first jQuery selector looks for an element tagged to the variable poundcid.

[cc lang=”javascript”]// begin translating our comment
$(poundcid).live(“click”, function() {
var newcomtxt = $(‘textarea#thecomment’).val();
var targetcontainer = “#”+cid;

var newcommhtml = ‘


anonymous posted 1 sec ago

‘ + newcomtxt + ‘





Digg Homescreen capture

This variable was set earlier in our code and targets the save link we generate with each new comment reply field. For this we add another live() click event handler and call another internal function upon saving.

Adding New Threads Dynamically

The variable newcomtxt is used to pull the current value of our text field and store it. targetcontainer is targeting the root thread based on the ID value. We are adding a hash/pound symbol (“#”) beforehand so we can target the variable inside a jQuery call.

newcommhtml is our largest variable and will be appended over and over into our document. This contains all the commenter’s information – username (in this case anonymous), datetime of posting, and avatar. You may notice there is also built-in code so for each new comment you add there will also be a matching “Reply” feature for further threading.

The second-to-last line is where we target and append our new HTML. We first grab our root element and find the first (and only) iteration of the “thread-replies” div.

First we call the hide() function to hide all internal content. This gives the animated effect of a fade-in when each new comment is added. We then append our HTML code from the variable above along with a fadeIn() function call.

computer registration forms

The trigger() function is called on our curroptlink to force a click event. This points towards our current option link, which at the end of adding a comment should be labeled “Hide Form”. This last line of code makes sure to remove our comment field after successfully adding the comment information into our page.

The last bits of code required will close off our 2 initial jQuery selectors. These include our first click event handler along with the DOM.ready() statement. To finish our commands we first increment the comments ID by 1 and return a false Boolean value to stop the page from reloading.

[cc lang=”javascript”] totalcommid++;

return false;


And that’s all we need! The jQuery code may seem a bit intimidating at first glance, especially if you haven’t spent much time in the language. However I can vouch in stating jQuery doesn’t take much time to learn and even newbies to JavaScript will pick up the conventions quickly.

If you have the interest feel free to build around this comment system to include your own server-side functionality. This could include a database system with Ajax calls to permanently store each comment locally with a matching ID.

There are so many things which can be done under the power of jQuery. If you’re interested further try downloading the project demo code and going over a few of the options yourself.

Jake Rocheleau

Jake is a researcher and writer on many design & digital art websites. He frequently writes on topics including UX design, content marketing, and project management. You can find more work on his portfolio and follow his latest tweets @jakerocheleau.