Design a Nested Chat Comments using HTML CSS and JavaScript

Last Updated : 31 Mar, 2026

This article explains how to create a Nested Comments system using JavaScript, similar to the comment sections seen on popular social media platforms. It helps in building interactive and structured discussion threads.

  • Allows users to reply to comments, creating a threaded conversation.
  • Mimics real-world platforms like Facebook, Instagram, and YouTube.
  • Enhances interactivity using JavaScript and dynamic DOM manipulation.

Approach:

  • Create a basic HTML structure with a comment input box and a container to display comments
  • Use JavaScript to capture user input and add new comments dynamically to the DOM
  • Represent each comment as an object (with properties like id, text, parentId, replies)
  • Store comments in a hierarchical (tree-like) structure to support nesting
  • Render comments recursively so that replies appear under their parent comment
  • Add a “Reply” button for each comment to allow nested responses
  • Handle reply submissions by linking them to the correct parent comment using parentId
  • Update the UI dynamically whenever a new comment or reply is added
  • Optionally use local storage to save comments and persist data on page reload
HTML
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" 
          content="width=device-width, 
                   initial-scale=1.0" />
    <link rel="stylesheet" href="styles.css" />
    <title>Nested Comments</title>
</head>

<body>
    <div class="container">
        <div id="comment-container" 
             class="comment-container">
            <div class="all-comment">
                <div class="card">
                    <span class="text">GFG</span>
                    <span id="reply" 
                          class="reply">
                          Add Reply
                      </span>
                </div>
            </div>
        </div>
    </div>
  
    <script src="script.js"></script>
</body>

</html>
CSS
.card {
    height: auto;
    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
    border-radius: 10px;
    padding: 10px;
    background-color: rgb(222, 222, 222);
    margin-top: 10px;
}
.text {
    display: block;
    font-size: 20px;
    font-weight: bold;
}
.reply {
    color: rgb(84, 84, 233);
    cursor: pointer;
    margin-top: 5px;
}
.comment-details {
    margin-left: 4rem;
    display: flex;
    align-items: center;
    margin-top: 10px;
}
.input {
    height: 30px;
    border-radius: 10px;
}
.btn {
    color: white;
    margin-left: 5px;
    background-color: rgb(135, 135, 235);
    border: 0px;
    border-radius: 10px;
    height: 30px;
    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
    cursor: pointer;
}
.all-comment:not(:first-child) {
    margin-left: 4rem;
}
JavaScript
let commentContainer = 
    document.getElementById("comment-container");

function createInputBox() {
    let div = document.createElement("div");

    div.setAttribute("class", "comment-details");

    div.innerHTML += `<input type="text"
                             placeholder="add text here"
                             class="input" />
                      <button class="btn submit">
                           Submit
                      </button>`;
    return div;
}

function addReply(text) {
    let div = document.createElement("div");

    div.setAttribute("class", "all-comment");
    
    div.innerHTML += `<div class="card">
                      <span class="text">
                      ${text}
                      </span>
                      <span id="reply" class="reply">
                      Add Reply
                      </span></div>`;
    return div;
}

commentContainer.addEventListener("click", function (e) {
    let replyClicked =
        e.target.classList.contains("reply");
    let submitClicked =
        e.target.classList.contains("submit");
    let closestCard =
        e.target.closest(".all-comment");

    if (replyClicked) {
        closestCard.appendChild(createInputBox());
    }

    if (submitClicked) {
        const commentDetails =
            e.target.closest(".comment-details");
        if (commentDetails.children[0].value) {
            closestCard.appendChild(
                addReply(commentDetails.children[0].value));
            commentDetails.remove();
        }
    }
});

Output:

Comment