Skip to content

Comment Section with Reply Form

Bootstrap 5 comment section with threaded replies, collapsible reply forms, like buttons, a new comment form and live comment count.

Live preview

Open in new tab

Code

A Bootstrap 5 comment section with threaded replies, like buttons, collapsible reply boxes and a form for new comments. Use it under blog posts, documentation pages, changelogs or any article that invites discussion.

How it works

The root is section.cm-comments, centered in a .cm-wrap that is 760px wide at most. At the top, .cm-new-form holds the "Post comment" textarea next to the current user's avatar. Below it, ol.cm-list contains one li.cm-item per thread. Each article.cm-comment has an initials avatar (.cm-avatar), a .cm-meta row with name, optional .cm-tag and a time element, the .cm-text paragraph and a .cm-actions row. Replies live in a nested ol.cm-replies, which draws a thread line on its left edge once it has children.

The Reply button uses Bootstrap's own collapse through data-bs-toggle="collapse" and aria-controls, so it opens the matching .collapse panel with a .cm-reply-form. The script listens for shown.bs.collapse to focus the textarea, closes the panel with Cancel or Escape and returns focus to the Reply button. On submit, both form types run checkValidity(); empty or whitespace-only text shows the Bootstrap invalid-feedback message. Valid text is cloned into the template.cm-template markup after a short simulated delay, appended to the thread or to .cm-list, and the .cm-count badge is recounted. A single delegated click listener on the root toggles every .cm-like button, including ones added later.

Customization

  • --cm-accent, --cm-accent-hover and --cm-accent-rgb in .cm-comments: change the berry color of buttons, likes, tags and focus rings.
  • --cm-bg, --cm-card, --cm-line and --cm-muted in .cm-comments: adjust the cream background, card surface, borders and secondary text.
  • --cm-avatar-size in .cm-comments: make the avatars larger or smaller; replies use a smaller size set in .cm-replies .cm-avatar.
  • .cm-avatar--a to .cm-avatar--d: change the avatar colors, or replace the initials with an img from your user data.
  • max-width: 760px in .cm-wrap: widen the thread for full-width layouts.
  • maxlength on the textareas: set the maximum comment and reply length.
  • The window.setTimeout call in handleForm() in script.js: replace it with a fetch() that saves the comment and returns the real author and time.

Accessibility

Each comment is an article labelled by its author heading, and threads use ordered lists so screen readers announce their size. The Reply button exposes aria-expanded and aria-controls through Bootstrap's collapse. Like buttons are toggle buttons with aria-pressed and hidden "likes" text after the number. Every textarea has a visually hidden label, gets aria-invalid when empty on submit and receives focus. New posts are announced through the .cm-status live region. The like pop, new comment fade and collapse transition are disabled with prefers-reduced-motion: reduce.

Usage notes

Requires Bootstrap 5 with its JavaScript bundle and Bootstrap Icons. Every collapse panel needs a unique id that matches data-bs-target on its button. Always sanitize comments on the server; the script inserts text with textContent, never as HTML.

Requirements

Add these to your page (already included in the download):

  • <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
  • <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
  • <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
Comment Section with Reply Form – Bootstrap 5 comments component screenshot
Comment Section with Reply Form · Bootstrap 5 Comments

More Comments

Comment Thread – Tailwind CSS comments preview

Comment Thread

Nested Tailwind CSS comment thread with threaded replies, like toggles, inline reply forms and a new comment form, built with accessible vanilla JavaScript.