Open demo

CSS code

HTML
<div><span class="lbl">Blog comment section with sorting and load more</span>
<section class="bc" data-comments aria-labelledby="bc-h">
  <div class="bc-top">
    <div><h2 class="bc-title" id="bc-h">9 comments</h2><p class="bc-sub">On “A weekend in Ljubljana for €150”</p></div>
    <div class="bc-sort"><label class="bc-sort-l" for="bc-sort">Sort by</label><select class="bc-select" id="bc-sort" data-sort><option value="top">Top</option><option value="new">Newest</option><option value="old">Oldest</option></select></div>
  </div>
  <ol class="bc-list" data-list>
    <li class="bc-item" data-time="2026-10-17T08:12" data-score="41">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Marta Novak">
        <span class="bc-av c1" aria-hidden="true">MN</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Marta Novak</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-17T08:12" title="17 October 2026, 08:12">2 days ago</time></p>
          <p class="bc-text">The tip about the Ljubljanica boat at sunset was worth the read on its own. We paid €12 each and had the river almost to ourselves.</p>
          <p class="bc-foot"><span class="bc-likes">41 likes</span><a class="bc-reply" href="#bc-respond" data-reply-to="Marta Novak">Reply<span class="bc-sr"> to Marta Novak</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-17T09:40" data-score="28">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Ines Moreau">
        <span class="bc-av au" aria-hidden="true">IM</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Ines Moreau</b> <span class="bc-badge">Author</span> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-17T09:40" title="17 October 2026, 09:40">2 days ago</time></p>
          <p class="bc-text">Thanks, Marta. Boat prices went up by a euro this summer, so I have updated the budget table in the post.</p>
          <p class="bc-foot"><span class="bc-likes">28 likes</span><a class="bc-reply" href="#bc-respond" data-reply-to="Ines Moreau">Reply<span class="bc-sr"> to Ines Moreau</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-14T08:55" data-score="22">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Tariq Haddad">
        <span class="bc-av c2" aria-hidden="true">TH</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Tariq Haddad</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-14T08:55" title="14 October 2026, 08:55">5 days ago</time></p>
          <p class="bc-text">Bus 27 from the station to the market is quicker than walking with luggage, and a single fare is only €1.30.</p>
          <p class="bc-foot"><span class="bc-likes">22 likes</span><a class="bc-reply" href="#bc-respond" data-reply-to="Tariq Haddad">Reply<span class="bc-sr"> to Tariq Haddad</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-16T19:22" data-score="19">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Sofia Lindqvist">
        <span class="bc-av c3" aria-hidden="true">SL</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Sofia Lindqvist</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-16T19:22" title="16 October 2026, 19:22">3 days ago</time></p>
          <p class="bc-text">We did the same route in March. Bring layers: the castle hill felt ten degrees colder than the old town.</p>
          <p class="bc-foot"><span class="bc-likes">19 likes</span><a class="bc-reply" href="#bc-respond" data-reply-to="Sofia Lindqvist">Reply<span class="bc-sr"> to Sofia Lindqvist</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-19T07:05" data-score="12">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Daniel Oyelaran">
        <span class="bc-av c4" aria-hidden="true">DO</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Daniel Oyelaran</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-19T07:05" title="19 October 2026, 07:05">5 hours ago</time></p>
          <p class="bc-text">Is the funicular up to the castle included in the city card, or is it a separate ticket?</p>
          <p class="bc-foot"><span class="bc-likes">12 likes</span><a class="bc-reply" href="#bc-respond" data-reply-to="Daniel Oyelaran">Reply<span class="bc-sr"> to Daniel Oyelaran</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-15T14:10" data-score="7">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Rui Almeida">
        <span class="bc-av c5" aria-hidden="true">RA</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Rui Almeida</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-15T14:10" title="15 October 2026, 14:10">4 days ago</time></p>
          <p class="bc-text">Heads up for anyone planning ahead: Hostel Celica is fully booked until December.</p>
          <p class="bc-foot"><span class="bc-likes">7 likes</span><a class="bc-reply" href="#bc-respond" data-reply-to="Rui Almeida">Reply<span class="bc-sr"> to Rui Almeida</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-13T21:03" data-score="5">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Emma Brandt">
        <span class="bc-av c1" aria-hidden="true">EB</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Emma Brandt</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-13T21:03" title="13 October 2026, 21:03">6 days ago</time></p>
          <p class="bc-text">The burek stand by the central market closes at 15:00 on Sundays. Learned that the hungry way.</p>
          <p class="bc-foot"><span class="bc-likes">5 likes</span><a class="bc-reply" href="#bc-respond" data-reply-to="Emma Brandt">Reply<span class="bc-sr"> to Emma Brandt</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-19T10:30" data-score="3">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Grace Whitfield">
        <span class="bc-av c2" aria-hidden="true">GW</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Grace Whitfield</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-19T10:30" title="19 October 2026, 10:30">2 hours ago</time></p>
          <p class="bc-text">Saving this for our anniversary trip in spring. Is Metelkova fine to walk through in the evening?</p>
          <p class="bc-foot"><span class="bc-likes">3 likes</span><a class="bc-reply" href="#bc-respond" data-reply-to="Grace Whitfield">Reply<span class="bc-sr"> to Grace Whitfield</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-19T11:48" data-score="1">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Luca Ferri">
        <span class="bc-av c3" aria-hidden="true">LF</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Luca Ferri</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-19T11:48" title="19 October 2026, 11:48">34 minutes ago</time></p>
          <p class="bc-text">Great write-up. I would add Lake Bled as a day trip: about €7 each way on the bus.</p>
          <p class="bc-foot"><span class="bc-likes">1 like</span><a class="bc-reply" href="#bc-respond" data-reply-to="Luca Ferri">Reply<span class="bc-sr"> to Luca Ferri</span></a></p>
        </div>
      </article>
    </li>
  </ol>
  <div class="bc-more-row"><p class="bc-shown" aria-live="polite" data-shown>Showing 9 of 9 comments</p><button class="bc-more" type="button" data-more data-initial="4" data-step="3">Load more comments</button></div>
  <form class="bc-form" id="bc-respond" data-respond aria-labelledby="bc-respond-h">
    <h3 class="bc-form-t" id="bc-respond-h">Leave a comment</h3>
    <p class="bc-replying" data-replying></p>
    <div class="bc-fields">
      <div class="bc-f full"><label class="bc-label" for="bc-body">Comment</label><textarea class="bc-input bc-area" id="bc-body" rows="4" required></textarea></div>
      <div class="bc-f"><label class="bc-label" for="bc-name">Name</label><input class="bc-input" id="bc-name" autocomplete="name" required></div>
      <div class="bc-f"><label class="bc-label" for="bc-email">Email (not published)</label><input class="bc-input" id="bc-email" type="email" autocomplete="email" required></div>
    </div>
    <div class="bc-form-a"><button class="bc-submit" type="submit">Post comment</button><p class="bc-status" role="status" data-status></p></div>
    <template data-cancel-tpl><button class="bc-cancel" type="button" data-cancel>Cancel reply</button></template>
  </form>
</section></div>

<div><span class="lbl">Comments closed notice</span>
<section class="bc-closed" aria-labelledby="bc-closed-h">
  <span class="bc-closed-i" aria-hidden="true"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></svg></span>
  <div class="bc-closed-t"><h2 class="bc-form-t" id="bc-closed-h">Comments are closed</h2><p class="bc-sub">This post is more than 90 days old, so new comments are switched off. The 214 earlier comments stay up as an archive.</p></div>
  <a class="bc-more" href="#">Read the 2026 update</a>
</section></div>
CSS
/* Blog comment section: a count heading, a sort select, comments with <time> timestamps and an Author badge, Load more with a live "Showing n of n" line, and a reply form. */
.bc{--bc-accent:#9a3412;--bc-accent-dark:#7c2d12;--bc-soft:#fbf1e8;--bc-ink:#231a14;--bc-muted:#5f5249;--bc-line:#ece4dc;--bc-field:#8d7f74;padding:28px 32px;border:1px solid var(--bc-line);border-radius:16px;background:#fff;color:var(--bc-ink);font-size:.95rem;line-height:1.6;box-shadow:0 18px 40px -30px rgba(35,26,20,.35)}
.bc-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
:where(.bc,.bc-closed) :is(button,input,textarea,select){font:inherit;color:inherit}
.bc [hidden]{display:none!important}
.bc :where(ol){list-style:none}
.bc :where(h2,h3,p,ol){margin:0}
.bc-top{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:12px;padding-bottom:16px;border-bottom:1px solid var(--bc-line)}
.bc-title{font-family:Georgia,"Times New Roman",serif;font-size:1.6rem;font-weight:700;line-height:1.2;letter-spacing:-.01em}
.bc-sub{margin-top:4px;color:var(--bc-muted);font-size:.86rem}
.bc-sort{display:flex;align-items:center;gap:8px;color:var(--bc-muted);font-size:.84rem;font-weight:600}
.bc-list{margin:0;padding:0}
.bc-item{border-bottom:1px solid var(--bc-line)}
.bc-c{display:flex;gap:14px;padding:20px 0;border-radius:8px}
.bc-c:focus-visible{outline:2px solid var(--bc-accent);outline-offset:2px}
.bc-av{flex:none;display:grid;place-items:center;width:40px;height:40px;border-radius:50%;font-size:.78rem;font-weight:700}
.bc .c1{background:#fed7aa;color:#7c2d12}
.bc .c2{background:#bfdbfe;color:#1e3a8a}
.bc .c3{background:#bbf7d0;color:#14532d}
.bc .c4{background:#e9d5ff;color:#581c87}
.bc .c5{background:#fecaca;color:#7f1d1d}
.bc .au{background:#9a3412;color:#ffffff}
.bc-main{flex:1;min-width:0}
.bc-meta{display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px;font-size:.86rem}
.bc-name{font-weight:700}
.bc-dot,.bc-time,.bc-likes{color:var(--bc-muted)}
.bc-text{margin-top:4px;text-wrap:pretty}
.bc-foot{display:flex;flex-wrap:wrap;align-items:center;gap:16px;margin-top:8px;font-size:.84rem}
.bc-reply{border-radius:2px;color:var(--bc-accent);font-weight:700;text-decoration:underline;text-decoration-color:transparent;text-underline-offset:3px}
.bc-reply:hover{color:var(--bc-accent);text-decoration-color:currentColor}
.bc-more-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding-top:20px}
.bc-shown{color:var(--bc-muted);font-size:.86rem}
.bc-form{margin-top:28px;padding:20px;border-radius:12px;background:var(--bc-soft)}
.bc-form-t{font-family:Georgia,"Times New Roman",serif;font-size:1.2rem;font-weight:700;line-height:1.3}
.bc-replying{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:6px;color:var(--bc-muted);font-size:.86rem}
.bc-replying:empty{display:none}
.bc-f{display:flex;flex-direction:column;gap:6px}
.bc-label{font-size:.84rem;font-weight:600}
.bc-form-a{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin-top:14px}
.bc-status{color:#166534;font-size:.86rem;font-weight:600}
.bc-closed{--bc-accent:#9a3412;--bc-accent-dark:#7c2d12;--bc-soft:#fbf1e8;--bc-ink:#231a14;--bc-muted:#5f5249;--bc-line:#ece4dc;--bc-field:#8d7f74;display:flex;flex-wrap:wrap;align-items:center;gap:16px;padding:20px 24px;border:1px solid var(--bc-line);border-radius:16px;background:#fff;color:var(--bc-ink);font-size:.95rem;line-height:1.6}
.bc-closed :where(h2,p){margin:0}
.bc-closed-i{flex:none;display:grid;place-items:center;width:44px;height:44px;border-radius:50%;background:var(--bc-soft);color:var(--bc-accent)}
.bc-closed-t{flex:1;min-width:220px}
.bc-select{min-height:36px;padding:4px 32px 4px 14px;border:1.5px solid var(--bc-field);border-radius:999px;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23231a14' stroke-width='2' d='m3 6 5 5 5-5'/%3E%3C/svg%3E") no-repeat right 12px center/12px;color:var(--bc-ink);font-weight:600;cursor:pointer;appearance:none}
.bc-badge{padding:2px 8px;border-radius:999px;background:var(--bc-accent);color:#fff;font-size:.68rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase}
.bc-more{display:inline-flex;align-items:center;min-height:40px;padding:0 18px;border:1.5px solid var(--bc-ink);border-radius:999px;background:none;color:var(--bc-ink);font-weight:700;text-decoration:none;cursor:pointer;transition:background-color .15s,color .15s}
.bc-more:hover{background:var(--bc-ink);color:#fff}
.bc-fields{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:14px}
.bc-f.full{grid-column:1/-1}
.bc-input{width:100%;padding:10px 12px;border:1.5px solid var(--bc-field);border-radius:10px;background:#fff;color:var(--bc-ink)}
.bc-area{min-height:110px;resize:vertical}
.bc :is(.bc-input,.bc-select):focus{border-color:var(--bc-accent);outline:2px solid transparent;box-shadow:0 0 0 3px rgba(154,52,18,.2)}
.bc-submit{display:inline-flex;align-items:center;min-height:40px;padding:0 20px;border:0;border-radius:999px;background:var(--bc-accent);color:#fff;font-weight:700;cursor:pointer}
.bc-submit:hover{background:var(--bc-accent-dark)}
.bc-cancel{padding:0;border:0;border-radius:2px;background:none;color:var(--bc-accent);font-weight:700;text-decoration:underline;text-underline-offset:2px;cursor:pointer}
:is(.bc,.bc-closed) :is(.bc-reply,.bc-more,.bc-submit,.bc-cancel):focus-visible{outline:2px solid var(--bc-accent);outline-offset:2px}
@media (max-width:640px){.bc{padding:22px 18px}}
@media (max-width:575.98px){.bc-fields{grid-template-columns:1fr}}
@media (prefers-reduced-motion:reduce){.bc-more{transition:none}}
JavaScript
/* Blog comments: sort (Top, Newest, Oldest), Load more that moves focus to the first new comment and updates a polite
   "Showing n of n" line, and Reply links that address the form. Without JavaScript every comment is shown. */
document.querySelectorAll('[data-comments]').forEach(function (sec) {
  var list = sec.querySelector('[data-list]'), items = Array.from(list.children), more = sec.querySelector('[data-more]');
  var shown = sec.querySelector('[data-shown]'), sort = sec.querySelector('[data-sort]'), form = sec.querySelector('[data-respond]');
  var visible = +more.dataset.initial, step = +more.dataset.step;
  function render(focusAt) {
    items.forEach(function (li, i) { li.hidden = i >= visible; });
    shown.textContent = 'Showing ' + Math.min(visible, items.length) + ' of ' + items.length + ' comments';
    more.hidden = visible >= items.length;
    if (focusAt != null && items[focusAt]) items[focusAt].querySelector('article').focus();
  }
  more.addEventListener('click', function () { var first = visible; visible += step; render(first); });
  sort.addEventListener('change', function () {
    var by = sort.value;
    items.sort(function (a, b) {
      if (by === 'top') return b.dataset.score - a.dataset.score;
      return by === 'new' ? b.dataset.time.localeCompare(a.dataset.time) : a.dataset.time.localeCompare(b.dataset.time);
    });
    items.forEach(function (li) { list.appendChild(li); });
    render();
  });
  var note = form.querySelector('[data-replying]'), body = form.querySelector('textarea'), status = form.querySelector('[data-status]');
  sec.addEventListener('click', function (e) {
    var link = e.target.closest('[data-reply-to]');
    if (link) {
      e.preventDefault();
      note.textContent = 'Replying to ' + link.dataset.replyTo + '.';
      note.appendChild(form.querySelector('[data-cancel-tpl]').content.cloneNode(true));
      body.focus();
    } else if (e.target.closest('[data-cancel]')) { note.textContent = ''; body.focus(); }
  });
  form.addEventListener('submit', function (e) {
    e.preventDefault();
    status.textContent = 'Thanks. Your comment will appear after review.';
    form.reset(); note.textContent = '';
  });
  render();
});

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Blog comment section with sorting and load more</span>
<section class="card bc" data-comments aria-labelledby="bc-h">
  <div class="bc-top">
    <div><h2 class="bc-title" id="bc-h">9 comments</h2><p class="bc-sub">On “A weekend in Ljubljana for €150”</p></div>
    <div class="bc-sort"><label class="form-label bc-sort-l" for="bc-sort">Sort by</label><select class="form-select bc-select" id="bc-sort" data-sort><option value="top">Top</option><option value="new">Newest</option><option value="old">Oldest</option></select></div>
  </div>
  <ol class="list-unstyled bc-list" data-list>
    <li class="bc-item" data-time="2026-10-17T08:12" data-score="41">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Marta Novak">
        <span class="bc-av c1" aria-hidden="true">MN</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Marta Novak</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-17T08:12" title="17 October 2026, 08:12">2 days ago</time></p>
          <p class="bc-text">The tip about the Ljubljanica boat at sunset was worth the read on its own. We paid €12 each and had the river almost to ourselves.</p>
          <p class="bc-foot"><span class="bc-likes">41 likes</span><a class="link-underline-opacity-0 bc-reply" href="#bc-respond" data-reply-to="Marta Novak">Reply<span class="visually-hidden"> to Marta Novak</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-17T09:40" data-score="28">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Ines Moreau">
        <span class="bc-av au" aria-hidden="true">IM</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Ines Moreau</b> <span class="badge bc-badge">Author</span> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-17T09:40" title="17 October 2026, 09:40">2 days ago</time></p>
          <p class="bc-text">Thanks, Marta. Boat prices went up by a euro this summer, so I have updated the budget table in the post.</p>
          <p class="bc-foot"><span class="bc-likes">28 likes</span><a class="link-underline-opacity-0 bc-reply" href="#bc-respond" data-reply-to="Ines Moreau">Reply<span class="visually-hidden"> to Ines Moreau</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-14T08:55" data-score="22">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Tariq Haddad">
        <span class="bc-av c2" aria-hidden="true">TH</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Tariq Haddad</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-14T08:55" title="14 October 2026, 08:55">5 days ago</time></p>
          <p class="bc-text">Bus 27 from the station to the market is quicker than walking with luggage, and a single fare is only €1.30.</p>
          <p class="bc-foot"><span class="bc-likes">22 likes</span><a class="link-underline-opacity-0 bc-reply" href="#bc-respond" data-reply-to="Tariq Haddad">Reply<span class="visually-hidden"> to Tariq Haddad</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-16T19:22" data-score="19">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Sofia Lindqvist">
        <span class="bc-av c3" aria-hidden="true">SL</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Sofia Lindqvist</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-16T19:22" title="16 October 2026, 19:22">3 days ago</time></p>
          <p class="bc-text">We did the same route in March. Bring layers: the castle hill felt ten degrees colder than the old town.</p>
          <p class="bc-foot"><span class="bc-likes">19 likes</span><a class="link-underline-opacity-0 bc-reply" href="#bc-respond" data-reply-to="Sofia Lindqvist">Reply<span class="visually-hidden"> to Sofia Lindqvist</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-19T07:05" data-score="12">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Daniel Oyelaran">
        <span class="bc-av c4" aria-hidden="true">DO</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Daniel Oyelaran</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-19T07:05" title="19 October 2026, 07:05">5 hours ago</time></p>
          <p class="bc-text">Is the funicular up to the castle included in the city card, or is it a separate ticket?</p>
          <p class="bc-foot"><span class="bc-likes">12 likes</span><a class="link-underline-opacity-0 bc-reply" href="#bc-respond" data-reply-to="Daniel Oyelaran">Reply<span class="visually-hidden"> to Daniel Oyelaran</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-15T14:10" data-score="7">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Rui Almeida">
        <span class="bc-av c5" aria-hidden="true">RA</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Rui Almeida</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-15T14:10" title="15 October 2026, 14:10">4 days ago</time></p>
          <p class="bc-text">Heads up for anyone planning ahead: Hostel Celica is fully booked until December.</p>
          <p class="bc-foot"><span class="bc-likes">7 likes</span><a class="link-underline-opacity-0 bc-reply" href="#bc-respond" data-reply-to="Rui Almeida">Reply<span class="visually-hidden"> to Rui Almeida</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-13T21:03" data-score="5">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Emma Brandt">
        <span class="bc-av c1" aria-hidden="true">EB</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Emma Brandt</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-13T21:03" title="13 October 2026, 21:03">6 days ago</time></p>
          <p class="bc-text">The burek stand by the central market closes at 15:00 on Sundays. Learned that the hungry way.</p>
          <p class="bc-foot"><span class="bc-likes">5 likes</span><a class="link-underline-opacity-0 bc-reply" href="#bc-respond" data-reply-to="Emma Brandt">Reply<span class="visually-hidden"> to Emma Brandt</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-19T10:30" data-score="3">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Grace Whitfield">
        <span class="bc-av c2" aria-hidden="true">GW</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Grace Whitfield</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-19T10:30" title="19 October 2026, 10:30">2 hours ago</time></p>
          <p class="bc-text">Saving this for our anniversary trip in spring. Is Metelkova fine to walk through in the evening?</p>
          <p class="bc-foot"><span class="bc-likes">3 likes</span><a class="link-underline-opacity-0 bc-reply" href="#bc-respond" data-reply-to="Grace Whitfield">Reply<span class="visually-hidden"> to Grace Whitfield</span></a></p>
        </div>
      </article>
    </li>
    <li class="bc-item" data-time="2026-10-19T11:48" data-score="1">
      <article class="bc-c" tabindex="-1" aria-label="Comment by Luca Ferri">
        <span class="bc-av c3" aria-hidden="true">LF</span>
        <div class="bc-main">
          <p class="bc-meta"><b class="bc-name">Luca Ferri</b> <span class="bc-dot" aria-hidden="true">·</span> <time class="bc-time" datetime="2026-10-19T11:48" title="19 October 2026, 11:48">34 minutes ago</time></p>
          <p class="bc-text">Great write-up. I would add Lake Bled as a day trip: about €7 each way on the bus.</p>
          <p class="bc-foot"><span class="bc-likes">1 like</span><a class="link-underline-opacity-0 bc-reply" href="#bc-respond" data-reply-to="Luca Ferri">Reply<span class="visually-hidden"> to Luca Ferri</span></a></p>
        </div>
      </article>
    </li>
  </ol>
  <div class="bc-more-row"><p class="bc-shown" aria-live="polite" data-shown>Showing 9 of 9 comments</p><button class="btn bc-more" type="button" data-more data-initial="4" data-step="3">Load more comments</button></div>
  <form class="bc-form" id="bc-respond" data-respond aria-labelledby="bc-respond-h">
    <h3 class="bc-form-t" id="bc-respond-h">Leave a comment</h3>
    <p class="bc-replying" data-replying></p>
    <div class="row g-3 bc-fields">
      <div class="col-12 bc-f"><label class="form-label bc-label" for="bc-body">Comment</label><textarea class="form-control bc-input bc-area" id="bc-body" rows="4" required></textarea></div>
      <div class="col-sm-6 bc-f"><label class="form-label bc-label" for="bc-name">Name</label><input class="form-control bc-input" id="bc-name" autocomplete="name" required></div>
      <div class="col-sm-6 bc-f"><label class="form-label bc-label" for="bc-email">Email (not published)</label><input class="form-control bc-input" id="bc-email" type="email" autocomplete="email" required></div>
    </div>
    <div class="bc-form-a"><button class="btn bc-submit" type="submit">Post comment</button><p class="bc-status" role="status" data-status></p></div>
    <template data-cancel-tpl><button class="btn btn-link bc-cancel" type="button" data-cancel>Cancel reply</button></template>
  </form>
</section></div>

<div><span class="lbl">Comments closed notice</span>
<section class="card bc-closed" aria-labelledby="bc-closed-h">
  <span class="bc-closed-i" aria-hidden="true"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></svg></span>
  <div class="bc-closed-t"><h2 class="bc-form-t" id="bc-closed-h">Comments are closed</h2><p class="bc-sub">This post is more than 90 days old, so new comments are switched off. The 214 earlier comments stay up as an archive.</p></div>
  <a class="btn bc-more" href="#">Read the 2026 update</a>
</section></div>
CSS
/* Blog comment section on Bootstrap: a .card with a .form-select sort, .badge, .btn Load more, .form-control fields and .row grid.
   Comments use <time> timestamps; Load more updates a live "Showing n of n" line. */
.bc{--bc-accent:#9a3412;--bc-accent-dark:#7c2d12;--bc-soft:#fbf1e8;--bc-ink:#231a14;--bc-muted:#5f5249;--bc-line:#ece4dc;--bc-field:#8d7f74;--bs-card-border-color:var(--bc-line);--bs-card-border-radius:16px;--bs-card-color:var(--bc-ink);padding:28px 32px;font-size:.95rem;line-height:1.6;box-shadow:0 18px 40px -30px rgba(35,26,20,.35)}
.bc :where(h2,h3,p,ol){margin:0}
.bc-top{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:12px;padding-bottom:16px;border-bottom:1px solid var(--bc-line)}
.bc-title{font-family:Georgia,"Times New Roman",serif;font-size:1.6rem;font-weight:700;line-height:1.2;letter-spacing:-.01em}
.bc-sub{margin-top:4px;color:var(--bc-muted);font-size:.86rem}
.bc-sort{display:flex;align-items:center;gap:8px;color:var(--bc-muted);font-size:.84rem;font-weight:600}
.bc-list{margin:0;padding:0}
.bc-item{border-bottom:1px solid var(--bc-line)}
.bc-c{display:flex;gap:14px;padding:20px 0;border-radius:8px}
.bc-c:focus-visible{outline:2px solid var(--bc-accent);outline-offset:2px}
.bc-av{flex:none;display:grid;place-items:center;width:40px;height:40px;border-radius:50%;font-size:.78rem;font-weight:700}
.bc .c1{background:#fed7aa;color:#7c2d12}
.bc .c2{background:#bfdbfe;color:#1e3a8a}
.bc .c3{background:#bbf7d0;color:#14532d}
.bc .c4{background:#e9d5ff;color:#581c87}
.bc .c5{background:#fecaca;color:#7f1d1d}
.bc .au{background:#9a3412;color:#ffffff}
.bc-main{flex:1;min-width:0}
.bc-meta{display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px;font-size:.86rem}
.bc-name{font-weight:700}
.bc-dot,.bc-time,.bc-likes{color:var(--bc-muted)}
.bc-text{margin-top:4px;text-wrap:pretty}
.bc-foot{display:flex;flex-wrap:wrap;align-items:center;gap:16px;margin-top:8px;font-size:.84rem}
.bc-reply{border-radius:2px;color:var(--bc-accent);font-weight:700;text-decoration:underline;text-decoration-color:transparent;text-underline-offset:3px}
.bc-reply:hover{color:var(--bc-accent);text-decoration-color:currentColor}
.bc-more-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding-top:20px}
.bc-shown{color:var(--bc-muted);font-size:.86rem}
.bc-form{margin-top:28px;padding:20px;border-radius:12px;background:var(--bc-soft)}
.bc-form-t{font-family:Georgia,"Times New Roman",serif;font-size:1.2rem;font-weight:700;line-height:1.3}
.bc-replying{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:6px;color:var(--bc-muted);font-size:.86rem}
.bc-replying:empty{display:none}
.bc-f{display:flex;flex-direction:column;gap:6px}
.bc-label{font-size:.84rem;font-weight:600}
.bc-form-a{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin-top:14px}
.bc-status{color:#166534;font-size:.86rem;font-weight:600}
.bc-closed{--bc-accent:#9a3412;--bc-accent-dark:#7c2d12;--bc-soft:#fbf1e8;--bc-ink:#231a14;--bc-muted:#5f5249;--bc-line:#ece4dc;--bc-field:#8d7f74;display:flex;flex-wrap:wrap;align-items:center;gap:16px;padding:20px 24px;border:1px solid var(--bc-line);border-radius:16px;background:#fff;color:var(--bc-ink);font-size:.95rem;line-height:1.6}
.bc-closed :where(h2,p){margin:0}
.bc-closed-i{flex:none;display:grid;place-items:center;width:44px;height:44px;border-radius:50%;background:var(--bc-soft);color:var(--bc-accent)}
.bc-closed-t{flex:1;min-width:220px}
.bc .form-label{margin:0}
.bc-select{--bs-form-select-bg-img:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23231a14' stroke-width='2' d='m3 6 5 5 5-5'/%3E%3C/svg%3E");width:auto;min-height:36px;padding:4px 32px 4px 14px;border:1.5px solid var(--bc-field);border-radius:999px;background-position:right 12px center;background-size:12px;color:var(--bc-ink);font-size:inherit;font-weight:600;cursor:pointer}
.bc-badge{--bs-badge-padding-x:8px;--bs-badge-padding-y:3px;--bs-badge-font-size:.68rem;--bs-badge-border-radius:999px;background:var(--bc-accent);letter-spacing:.06em;text-transform:uppercase}
.bc .btn{--bs-btn-focus-box-shadow:none;--bs-btn-font-weight:700;--bs-btn-font-size:.95rem;--bs-btn-padding-y:0;--bs-btn-border-radius:999px;display:inline-flex;align-items:center;min-height:40px}
.bc-more{--bs-btn-padding-x:18px;--bs-btn-color:var(--bc-ink);--bs-btn-border-color:var(--bc-ink);--bs-btn-border-width:1.5px;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:var(--bc-ink);--bs-btn-hover-border-color:var(--bc-ink);--bs-btn-active-color:#fff;--bs-btn-active-bg:var(--bc-ink);--bs-btn-focus-box-shadow:none;--bs-btn-font-weight:700;--bs-btn-padding-y:0;--bs-btn-border-radius:999px;display:inline-flex;align-items:center;min-height:40px}
.bc-fields{margin-top:2px}
.bc-input{padding:10px 12px;border:1.5px solid var(--bc-field);border-radius:10px;color:var(--bc-ink);font-size:inherit}
.bc-area{min-height:110px}
.bc :is(.bc-input,.bc-select):focus{border-color:var(--bc-accent);box-shadow:0 0 0 3px rgba(154,52,18,.2)}
.bc-submit{--bs-btn-padding-x:20px;--bs-btn-color:#fff;--bs-btn-bg:var(--bc-accent);--bs-btn-hover-color:#fff;--bs-btn-hover-bg:var(--bc-accent-dark);--bs-btn-active-color:#fff;--bs-btn-active-bg:var(--bc-accent-dark)}
.bc .bc-cancel{--bs-btn-color:var(--bc-accent);--bs-btn-hover-color:var(--bc-accent-dark);--bs-btn-padding-x:0;--bs-btn-border-width:0;--bs-btn-font-size:.86rem;min-height:0;text-underline-offset:2px}
.bc-closed{--bs-card-border-color:var(--bc-line);--bs-card-border-radius:16px;flex-direction:row}
:is(.bc,.bc-closed) :is(.bc-reply,.btn):focus-visible{outline:2px solid var(--bc-accent);outline-offset:2px}
@media (max-width:640px){.bc{padding:22px 18px}}
@media (prefers-reduced-motion:reduce){.bc .btn,.bc-closed .btn{transition:none}}
JavaScript
/* Blog comments: sort (Top, Newest, Oldest), Load more that moves focus to the first new comment and updates a polite
   "Showing n of n" line, and Reply links that address the form. Without JavaScript every comment is shown. */
document.querySelectorAll('[data-comments]').forEach(function (sec) {
  var list = sec.querySelector('[data-list]'), items = Array.from(list.children), more = sec.querySelector('[data-more]');
  var shown = sec.querySelector('[data-shown]'), sort = sec.querySelector('[data-sort]'), form = sec.querySelector('[data-respond]');
  var visible = +more.dataset.initial, step = +more.dataset.step;
  function render(focusAt) {
    items.forEach(function (li, i) { li.hidden = i >= visible; });
    shown.textContent = 'Showing ' + Math.min(visible, items.length) + ' of ' + items.length + ' comments';
    more.hidden = visible >= items.length;
    if (focusAt != null && items[focusAt]) items[focusAt].querySelector('article').focus();
  }
  more.addEventListener('click', function () { var first = visible; visible += step; render(first); });
  sort.addEventListener('change', function () {
    var by = sort.value;
    items.sort(function (a, b) {
      if (by === 'top') return b.dataset.score - a.dataset.score;
      return by === 'new' ? b.dataset.time.localeCompare(a.dataset.time) : a.dataset.time.localeCompare(b.dataset.time);
    });
    items.forEach(function (li) { list.appendChild(li); });
    render();
  });
  var note = form.querySelector('[data-replying]'), body = form.querySelector('textarea'), status = form.querySelector('[data-status]');
  sec.addEventListener('click', function (e) {
    var link = e.target.closest('[data-reply-to]');
    if (link) {
      e.preventDefault();
      note.textContent = 'Replying to ' + link.dataset.replyTo + '.';
      note.appendChild(form.querySelector('[data-cancel-tpl]').content.cloneNode(true));
      body.focus();
    } else if (e.target.closest('[data-cancel]')) { note.textContent = ''; body.focus(); }
  });
  form.addEventListener('submit', function (e) {
    e.preventDefault();
    status.textContent = 'Thanks. Your comment will appear after review.';
    form.reset(); note.textContent = '';
  });
  render();
});

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#5f5249] uppercase">Blog comment section with sorting and load more</span>
<section class="rounded-2xl border border-bc-line bg-white px-8 py-7 text-[.95rem] leading-[1.6] text-bc-ink shadow-[0_18px_40px_-30px_rgba(35,26,20,.35)] max-sm:px-[18px] max-sm:py-[22px]" data-comments aria-labelledby="bc-h">
  <div class="flex flex-wrap items-end justify-between gap-3 border-b border-bc-line pb-4">
    <div><h2 class="font-[Georgia,'Times_New_Roman',serif] text-[1.6rem] leading-[1.2] font-bold tracking-[-.01em]" id="bc-h">9 comments</h2><p class="mt-1 text-[.86rem] text-bc-muted">On “A weekend in Ljubljana for €150”</p></div>
    <div class="flex items-center gap-2 text-[.84rem] font-semibold text-bc-muted"><label class="" for="bc-sort">Sort by</label><select class="min-h-9 cursor-pointer appearance-none rounded-full border-[1.5px] border-[#8d7f74] bg-white bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%3E%3Cpath%20fill=%22none%22%20stroke=%22%23231a14%22%20stroke-width=%222%22%20d=%22m3%206%205%205%205-5%22/%3E%3C/svg%3E')] bg-[length:12px] bg-[right_12px_center] bg-no-repeat py-1 pr-8 pl-3.5 font-semibold text-bc-ink focus:border-bc-accent focus:shadow-[0_0_0_3px_rgba(154,52,18,.2)] focus:outline-2 focus:outline-transparent" id="bc-sort" data-sort><option value="top">Top</option><option value="new">Newest</option><option value="old">Oldest</option></select></div>
  </div>
  <ol class="" data-list>
    <li class="border-b border-bc-line" data-time="2026-10-17T08:12" data-score="41">
      <article class="flex gap-3.5 rounded-lg py-5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" tabindex="-1" aria-label="Comment by Marta Novak">
        <span class="grid size-10 flex-none place-items-center rounded-full text-[.78rem] font-bold bg-[#fed7aa] text-[#7c2d12]" aria-hidden="true">MN</span>
        <div class="min-w-0 flex-1">
          <p class="flex flex-wrap items-center gap-x-2 gap-y-1 text-[.86rem]"><b class="font-bold">Marta Novak</b> <span class="text-bc-muted" aria-hidden="true">·</span> <time class="text-bc-muted" datetime="2026-10-17T08:12" title="17 October 2026, 08:12">2 days ago</time></p>
          <p class="mt-1 text-pretty">The tip about the Ljubljanica boat at sunset was worth the read on its own. We paid €12 each and had the river almost to ourselves.</p>
          <p class="mt-2 flex flex-wrap items-center gap-4 text-[.84rem]"><span class="text-bc-muted">41 likes</span><a class="rounded-sm font-bold text-bc-accent underline decoration-transparent underline-offset-[3px] hover:decoration-current focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" href="#bc-respond" data-reply-to="Marta Novak">Reply<span class="sr-only"> to Marta Novak</span></a></p>
        </div>
      </article>
    </li>
    <li class="border-b border-bc-line" data-time="2026-10-17T09:40" data-score="28">
      <article class="flex gap-3.5 rounded-lg py-5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" tabindex="-1" aria-label="Comment by Ines Moreau">
        <span class="grid size-10 flex-none place-items-center rounded-full text-[.78rem] font-bold bg-[#9a3412] text-[#ffffff]" aria-hidden="true">IM</span>
        <div class="min-w-0 flex-1">
          <p class="flex flex-wrap items-center gap-x-2 gap-y-1 text-[.86rem]"><b class="font-bold">Ines Moreau</b> <span class="rounded-full bg-bc-accent px-2 py-0.5 text-[.68rem] font-bold tracking-[.06em] text-white uppercase">Author</span> <span class="text-bc-muted" aria-hidden="true">·</span> <time class="text-bc-muted" datetime="2026-10-17T09:40" title="17 October 2026, 09:40">2 days ago</time></p>
          <p class="mt-1 text-pretty">Thanks, Marta. Boat prices went up by a euro this summer, so I have updated the budget table in the post.</p>
          <p class="mt-2 flex flex-wrap items-center gap-4 text-[.84rem]"><span class="text-bc-muted">28 likes</span><a class="rounded-sm font-bold text-bc-accent underline decoration-transparent underline-offset-[3px] hover:decoration-current focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" href="#bc-respond" data-reply-to="Ines Moreau">Reply<span class="sr-only"> to Ines Moreau</span></a></p>
        </div>
      </article>
    </li>
    <li class="border-b border-bc-line" data-time="2026-10-14T08:55" data-score="22">
      <article class="flex gap-3.5 rounded-lg py-5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" tabindex="-1" aria-label="Comment by Tariq Haddad">
        <span class="grid size-10 flex-none place-items-center rounded-full text-[.78rem] font-bold bg-[#bfdbfe] text-[#1e3a8a]" aria-hidden="true">TH</span>
        <div class="min-w-0 flex-1">
          <p class="flex flex-wrap items-center gap-x-2 gap-y-1 text-[.86rem]"><b class="font-bold">Tariq Haddad</b> <span class="text-bc-muted" aria-hidden="true">·</span> <time class="text-bc-muted" datetime="2026-10-14T08:55" title="14 October 2026, 08:55">5 days ago</time></p>
          <p class="mt-1 text-pretty">Bus 27 from the station to the market is quicker than walking with luggage, and a single fare is only €1.30.</p>
          <p class="mt-2 flex flex-wrap items-center gap-4 text-[.84rem]"><span class="text-bc-muted">22 likes</span><a class="rounded-sm font-bold text-bc-accent underline decoration-transparent underline-offset-[3px] hover:decoration-current focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" href="#bc-respond" data-reply-to="Tariq Haddad">Reply<span class="sr-only"> to Tariq Haddad</span></a></p>
        </div>
      </article>
    </li>
    <li class="border-b border-bc-line" data-time="2026-10-16T19:22" data-score="19">
      <article class="flex gap-3.5 rounded-lg py-5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" tabindex="-1" aria-label="Comment by Sofia Lindqvist">
        <span class="grid size-10 flex-none place-items-center rounded-full text-[.78rem] font-bold bg-[#bbf7d0] text-[#14532d]" aria-hidden="true">SL</span>
        <div class="min-w-0 flex-1">
          <p class="flex flex-wrap items-center gap-x-2 gap-y-1 text-[.86rem]"><b class="font-bold">Sofia Lindqvist</b> <span class="text-bc-muted" aria-hidden="true">·</span> <time class="text-bc-muted" datetime="2026-10-16T19:22" title="16 October 2026, 19:22">3 days ago</time></p>
          <p class="mt-1 text-pretty">We did the same route in March. Bring layers: the castle hill felt ten degrees colder than the old town.</p>
          <p class="mt-2 flex flex-wrap items-center gap-4 text-[.84rem]"><span class="text-bc-muted">19 likes</span><a class="rounded-sm font-bold text-bc-accent underline decoration-transparent underline-offset-[3px] hover:decoration-current focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" href="#bc-respond" data-reply-to="Sofia Lindqvist">Reply<span class="sr-only"> to Sofia Lindqvist</span></a></p>
        </div>
      </article>
    </li>
    <li class="border-b border-bc-line" data-time="2026-10-19T07:05" data-score="12">
      <article class="flex gap-3.5 rounded-lg py-5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" tabindex="-1" aria-label="Comment by Daniel Oyelaran">
        <span class="grid size-10 flex-none place-items-center rounded-full text-[.78rem] font-bold bg-[#e9d5ff] text-[#581c87]" aria-hidden="true">DO</span>
        <div class="min-w-0 flex-1">
          <p class="flex flex-wrap items-center gap-x-2 gap-y-1 text-[.86rem]"><b class="font-bold">Daniel Oyelaran</b> <span class="text-bc-muted" aria-hidden="true">·</span> <time class="text-bc-muted" datetime="2026-10-19T07:05" title="19 October 2026, 07:05">5 hours ago</time></p>
          <p class="mt-1 text-pretty">Is the funicular up to the castle included in the city card, or is it a separate ticket?</p>
          <p class="mt-2 flex flex-wrap items-center gap-4 text-[.84rem]"><span class="text-bc-muted">12 likes</span><a class="rounded-sm font-bold text-bc-accent underline decoration-transparent underline-offset-[3px] hover:decoration-current focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" href="#bc-respond" data-reply-to="Daniel Oyelaran">Reply<span class="sr-only"> to Daniel Oyelaran</span></a></p>
        </div>
      </article>
    </li>
    <li class="border-b border-bc-line" data-time="2026-10-15T14:10" data-score="7">
      <article class="flex gap-3.5 rounded-lg py-5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" tabindex="-1" aria-label="Comment by Rui Almeida">
        <span class="grid size-10 flex-none place-items-center rounded-full text-[.78rem] font-bold bg-[#fecaca] text-[#7f1d1d]" aria-hidden="true">RA</span>
        <div class="min-w-0 flex-1">
          <p class="flex flex-wrap items-center gap-x-2 gap-y-1 text-[.86rem]"><b class="font-bold">Rui Almeida</b> <span class="text-bc-muted" aria-hidden="true">·</span> <time class="text-bc-muted" datetime="2026-10-15T14:10" title="15 October 2026, 14:10">4 days ago</time></p>
          <p class="mt-1 text-pretty">Heads up for anyone planning ahead: Hostel Celica is fully booked until December.</p>
          <p class="mt-2 flex flex-wrap items-center gap-4 text-[.84rem]"><span class="text-bc-muted">7 likes</span><a class="rounded-sm font-bold text-bc-accent underline decoration-transparent underline-offset-[3px] hover:decoration-current focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" href="#bc-respond" data-reply-to="Rui Almeida">Reply<span class="sr-only"> to Rui Almeida</span></a></p>
        </div>
      </article>
    </li>
    <li class="border-b border-bc-line" data-time="2026-10-13T21:03" data-score="5">
      <article class="flex gap-3.5 rounded-lg py-5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" tabindex="-1" aria-label="Comment by Emma Brandt">
        <span class="grid size-10 flex-none place-items-center rounded-full text-[.78rem] font-bold bg-[#fed7aa] text-[#7c2d12]" aria-hidden="true">EB</span>
        <div class="min-w-0 flex-1">
          <p class="flex flex-wrap items-center gap-x-2 gap-y-1 text-[.86rem]"><b class="font-bold">Emma Brandt</b> <span class="text-bc-muted" aria-hidden="true">·</span> <time class="text-bc-muted" datetime="2026-10-13T21:03" title="13 October 2026, 21:03">6 days ago</time></p>
          <p class="mt-1 text-pretty">The burek stand by the central market closes at 15:00 on Sundays. Learned that the hungry way.</p>
          <p class="mt-2 flex flex-wrap items-center gap-4 text-[.84rem]"><span class="text-bc-muted">5 likes</span><a class="rounded-sm font-bold text-bc-accent underline decoration-transparent underline-offset-[3px] hover:decoration-current focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" href="#bc-respond" data-reply-to="Emma Brandt">Reply<span class="sr-only"> to Emma Brandt</span></a></p>
        </div>
      </article>
    </li>
    <li class="border-b border-bc-line" data-time="2026-10-19T10:30" data-score="3">
      <article class="flex gap-3.5 rounded-lg py-5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" tabindex="-1" aria-label="Comment by Grace Whitfield">
        <span class="grid size-10 flex-none place-items-center rounded-full text-[.78rem] font-bold bg-[#bfdbfe] text-[#1e3a8a]" aria-hidden="true">GW</span>
        <div class="min-w-0 flex-1">
          <p class="flex flex-wrap items-center gap-x-2 gap-y-1 text-[.86rem]"><b class="font-bold">Grace Whitfield</b> <span class="text-bc-muted" aria-hidden="true">·</span> <time class="text-bc-muted" datetime="2026-10-19T10:30" title="19 October 2026, 10:30">2 hours ago</time></p>
          <p class="mt-1 text-pretty">Saving this for our anniversary trip in spring. Is Metelkova fine to walk through in the evening?</p>
          <p class="mt-2 flex flex-wrap items-center gap-4 text-[.84rem]"><span class="text-bc-muted">3 likes</span><a class="rounded-sm font-bold text-bc-accent underline decoration-transparent underline-offset-[3px] hover:decoration-current focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" href="#bc-respond" data-reply-to="Grace Whitfield">Reply<span class="sr-only"> to Grace Whitfield</span></a></p>
        </div>
      </article>
    </li>
    <li class="border-b border-bc-line" data-time="2026-10-19T11:48" data-score="1">
      <article class="flex gap-3.5 rounded-lg py-5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" tabindex="-1" aria-label="Comment by Luca Ferri">
        <span class="grid size-10 flex-none place-items-center rounded-full text-[.78rem] font-bold bg-[#bbf7d0] text-[#14532d]" aria-hidden="true">LF</span>
        <div class="min-w-0 flex-1">
          <p class="flex flex-wrap items-center gap-x-2 gap-y-1 text-[.86rem]"><b class="font-bold">Luca Ferri</b> <span class="text-bc-muted" aria-hidden="true">·</span> <time class="text-bc-muted" datetime="2026-10-19T11:48" title="19 October 2026, 11:48">34 minutes ago</time></p>
          <p class="mt-1 text-pretty">Great write-up. I would add Lake Bled as a day trip: about €7 each way on the bus.</p>
          <p class="mt-2 flex flex-wrap items-center gap-4 text-[.84rem]"><span class="text-bc-muted">1 like</span><a class="rounded-sm font-bold text-bc-accent underline decoration-transparent underline-offset-[3px] hover:decoration-current focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" href="#bc-respond" data-reply-to="Luca Ferri">Reply<span class="sr-only"> to Luca Ferri</span></a></p>
        </div>
      </article>
    </li>
  </ol>
  <div class="flex flex-wrap items-center justify-between gap-3 pt-5"><p class="text-[.86rem] text-bc-muted" aria-live="polite" data-shown>Showing 9 of 9 comments</p><button class="inline-flex min-h-10 cursor-pointer items-center rounded-full border-[1.5px] border-bc-ink px-[18px] font-bold text-bc-ink transition-colors duration-150 hover:bg-bc-ink hover:text-white motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" type="button" data-more data-initial="4" data-step="3">Load more comments</button></div>
  <form class="mt-7 rounded-xl bg-bc-soft p-5" id="bc-respond" data-respond aria-labelledby="bc-respond-h">
    <h3 class="font-[Georgia,'Times_New_Roman',serif] text-[1.2rem] leading-[1.3] font-bold" id="bc-respond-h">Leave a comment</h3>
    <p class="mt-1.5 flex flex-wrap items-center gap-2 text-[.86rem] text-bc-muted empty:hidden" data-replying></p>
    <div class="mt-3.5 grid grid-cols-[1fr_1fr] gap-3 max-[576px]:grid-cols-1">
      <div class="col-span-full flex flex-col gap-1.5"><label class="text-[.84rem] font-semibold" for="bc-body">Comment</label><textarea class="min-h-[110px] w-full resize-y rounded-[10px] border-[1.5px] border-[#8d7f74] bg-white px-3 py-2.5 text-bc-ink focus:border-bc-accent focus:shadow-[0_0_0_3px_rgba(154,52,18,.2)] focus:outline-2 focus:outline-transparent" id="bc-body" rows="4" required></textarea></div>
      <div class="flex flex-col gap-1.5"><label class="text-[.84rem] font-semibold" for="bc-name">Name</label><input class="w-full rounded-[10px] border-[1.5px] border-[#8d7f74] bg-white px-3 py-2.5 text-bc-ink focus:border-bc-accent focus:shadow-[0_0_0_3px_rgba(154,52,18,.2)] focus:outline-2 focus:outline-transparent" id="bc-name" autocomplete="name" required></div>
      <div class="flex flex-col gap-1.5"><label class="text-[.84rem] font-semibold" for="bc-email">Email (not published)</label><input class="w-full rounded-[10px] border-[1.5px] border-[#8d7f74] bg-white px-3 py-2.5 text-bc-ink focus:border-bc-accent focus:shadow-[0_0_0_3px_rgba(154,52,18,.2)] focus:outline-2 focus:outline-transparent" id="bc-email" type="email" autocomplete="email" required></div>
    </div>
    <div class="mt-3.5 flex flex-wrap items-center gap-3"><button class="inline-flex min-h-10 cursor-pointer items-center rounded-full bg-bc-accent px-5 font-bold text-white hover:bg-bc-accent-dark focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" type="submit">Post comment</button><p class="text-[.86rem] font-semibold text-[#166534]" role="status" data-status></p></div>
    <template data-cancel-tpl><button class="cursor-pointer rounded-sm font-bold text-bc-accent underline underline-offset-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" type="button" data-cancel>Cancel reply</button></template>
  </form>
</section></div>

<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#5f5249] uppercase">Comments closed notice</span>
<section class="flex flex-wrap items-center gap-4 rounded-2xl border border-bc-line bg-white px-6 py-5 text-[.95rem] leading-[1.6] text-bc-ink" aria-labelledby="bc-closed-h">
  <span class="grid size-11 flex-none place-items-center rounded-full bg-bc-soft text-bc-accent" aria-hidden="true"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></svg></span>
  <div class="min-w-[220px] flex-1"><h2 class="font-[Georgia,'Times_New_Roman',serif] text-[1.2rem] leading-[1.3] font-bold" id="bc-closed-h">Comments are closed</h2><p class="mt-1 text-[.86rem] text-bc-muted">This post is more than 90 days old, so new comments are switched off. The 214 earlier comments stay up as an archive.</p></div>
  <a class="inline-flex min-h-10 cursor-pointer items-center rounded-full border-[1.5px] border-bc-ink px-[18px] font-bold text-bc-ink transition-colors duration-150 hover:bg-bc-ink hover:text-white motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-bc-accent" href="#">Read the 2026 update</a>
</section></div>
CSS
/* Palette as theme colours; everything else is utilities in the markup (empty:hidden, focus-visible:, motion-reduce:). */
@theme {
  --color-bc-accent:#9a3412; --color-bc-accent-dark:#7c2d12; --color-bc-soft:#fbf1e8; --color-bc-ink:#231a14;
  --color-bc-muted:#5f5249; --color-bc-line:#ece4dc;
}
JavaScript
/* Blog comments: sort (Top, Newest, Oldest), Load more that moves focus to the first new comment and updates a polite
   "Showing n of n" line, and Reply links that address the form. Without JavaScript every comment is shown. */
document.querySelectorAll('[data-comments]').forEach(function (sec) {
  var list = sec.querySelector('[data-list]'), items = Array.from(list.children), more = sec.querySelector('[data-more]');
  var shown = sec.querySelector('[data-shown]'), sort = sec.querySelector('[data-sort]'), form = sec.querySelector('[data-respond]');
  var visible = +more.dataset.initial, step = +more.dataset.step;
  function render(focusAt) {
    items.forEach(function (li, i) { li.hidden = i >= visible; });
    shown.textContent = 'Showing ' + Math.min(visible, items.length) + ' of ' + items.length + ' comments';
    more.hidden = visible >= items.length;
    if (focusAt != null && items[focusAt]) items[focusAt].querySelector('article').focus();
  }
  more.addEventListener('click', function () { var first = visible; visible += step; render(first); });
  sort.addEventListener('change', function () {
    var by = sort.value;
    items.sort(function (a, b) {
      if (by === 'top') return b.dataset.score - a.dataset.score;
      return by === 'new' ? b.dataset.time.localeCompare(a.dataset.time) : a.dataset.time.localeCompare(b.dataset.time);
    });
    items.forEach(function (li) { list.appendChild(li); });
    render();
  });
  var note = form.querySelector('[data-replying]'), body = form.querySelector('textarea'), status = form.querySelector('[data-status]');
  sec.addEventListener('click', function (e) {
    var link = e.target.closest('[data-reply-to]');
    if (link) {
      e.preventDefault();
      note.textContent = 'Replying to ' + link.dataset.replyTo + '.';
      note.appendChild(form.querySelector('[data-cancel-tpl]').content.cloneNode(true));
      body.focus();
    } else if (e.target.closest('[data-cancel]')) { note.textContent = ''; body.focus(); }
  });
  form.addEventListener('submit', function (e) {
    e.preventDefault();
    status.textContent = 'Thanks. Your comment will appear after review.';
    form.reset(); note.textContent = '';
  });
  render();
});

About this set

A complete comment section for the end of a blog post, plus a notice for posts where comments are closed. The section opens with a serif count heading, the post it belongs to and a Sort by select with Top, Newest and Oldest. Each comment has an initials avatar, the name, an Author badge on replies from the writer, a relative time inside a time element with a machine-readable datetime and the full date as a tooltip, the like count and a Reply link. The first four comments are shown; Load more comments reveals three more at a time, moves focus to the first new one and updates a polite Showing 7 of 9 comments line, and the button disappears when everything is visible. Reply links jump to the Leave a comment form below and add a Replying to note with a Cancel reply button. Sorting reorders the whole list and keeps the number shown. Without JavaScript every comment is visible and the links still reach the form. The comments closed notice uses a lock icon, a short reason and a link to a follow-up post.

What’s included

  • Count heading and a Sort by select for Top, Newest and Oldest
  • Author badge and time elements with datetime and full-date titles
  • Load more with focus moved to the first new comment
  • A polite "Showing n of n comments" line
  • Reply links that address the comment form, and a comments closed notice

Accessibility

The section is named by its heading, the sort select has a visible label, and each comment is an article named after its author. Load more moves focus to the first revealed comment and the count line is a polite live region. Reply links include the author's name in visually hidden text, form fields have visible labels, and links, buttons and fields have visible focus styles.

Customise it

Change --bc-accent, --bc-soft and --bc-line on .bc, and data-initial and data-step on the Load more button. Bootstrap uses the same variables with .form-select, .badge and .btn; in Tailwind edit the --color-bc-* theme colours.