Webパーツ辞典

コメントスレッドComment thread

丸いアイコンと名前・日時の下に本文を置き、返信やいいねのボタンを添えたコメントを縦に並べる表示。返信は1段字下げして左の線で親につなぐ。

表示例

コメント 2件

  1. 佐藤 花子

    手順どおりに進めたら動きました。3番目の設定が分かりにくかったです。

    3件
    1. 編集部 投稿者

      ありがとうございます。3番目に図を足しました。

      0件

アイコン: Font Awesome 7 Free(fa-solid / fa-regular)

別名・英語表記

  • コメント一覧
  • 返信スレッド
  • ディスカッション
  • 入れ子のコメント
  • ツリー型コメント
  • スレッド表示
  • Comment thread

実装例

<section class="x-comment-thread" aria-labelledby="x-comment-thread-h">
  <h2 class="x-comment-thread__h" id="x-comment-thread-h">コメント 2件</h2>
  <ol class="x-comment-thread__list" role="list">
    <li>
      <article class="x-comment-thread__c" aria-labelledby="x-comment-thread-a1">
        <div class="x-comment-thread__meta">
          <span class="x-comment-thread__av x-comment-thread__av--a" aria-hidden="true">佐</span>
          <span class="x-comment-thread__name" id="x-comment-thread-a1">佐藤 花子</span>
          <time class="x-comment-thread__time" datetime="2026-09-24T18:30">9月24日 18:30</time>
        </div>
        <p class="x-comment-thread__body">手順どおりに進めたら動きました。3番目の設定が分かりにくかったです。</p>
        <div class="x-comment-thread__act">
          <button class="x-comment-thread__b" type="button" aria-label="佐藤 花子に返信">
            <i class="fa-solid fa-reply" aria-hidden="true"></i>返信
          </button>
          <button class="x-comment-thread__b" type="button" aria-pressed="true">
            <i class="fa-solid fa-heart" aria-hidden="true"></i>いいね
          </button>
          <!-- 数は押すと変わるのでボタンの名前に入れない。状態は aria-pressed だけで伝える -->
          <span class="x-comment-thread__cnt">3件</span>
        </div>
      </article>
      <!-- 返信は親のコメントの li の中に入れ子の ol で置く。字下げと左の線で親子を見せる -->
      <ol class="x-comment-thread__replies" role="list">
        <li>
          <article class="x-comment-thread__c" aria-labelledby="x-comment-thread-a2">
            <div class="x-comment-thread__meta">
              <span class="x-comment-thread__av x-comment-thread__av--b" aria-hidden="true">編</span>
              <span class="x-comment-thread__name" id="x-comment-thread-a2">編集部</span>
              <span class="x-comment-thread__tag">投稿者</span>
              <time class="x-comment-thread__time" datetime="2026-09-25T09:10">9月25日 9:10</time>
            </div>
            <p class="x-comment-thread__body">ありがとうございます。3番目に図を足しました。</p>
            <div class="x-comment-thread__act">
              <button class="x-comment-thread__b" type="button" aria-label="編集部に返信">
                <i class="fa-solid fa-reply" aria-hidden="true"></i>返信
              </button>
              <button class="x-comment-thread__b" type="button" aria-pressed="false">
                <i class="fa-regular fa-heart" aria-hidden="true"></i>いいね
              </button>
              <span class="x-comment-thread__cnt">0件</span>
            </div>
          </article>
        </li>
      </ol>
    </li>
  </ol>
</section>

AIへの指示文

「コメントスレッド(Comment thread)」を実装してください。

## これは何か
丸いアイコンと名前・日時の下に本文を置き、返信やいいねのボタンを添えたコメントを縦に並べる表示。返信は1段字下げして左の線で親につなぐ。

## 使いどころ
- 記事やお知らせの下に、読者のコメントと返信を並べたいとき
- 課題やレビューの指摘ごとに、やり取りを話題単位でまとめて残したいとき

## 実装の要件
- section(見出し「コメント n件」)> ol[role=list] > li > article(アバター・名前・time・本文・操作)+ ol(返信)
- 返信の ol は margin-left と border-left で字下げし、線で親につなぐ
- 操作のボタンは高さ 24px 以上。返信・いいね・通報のように、よく使うものから左に並べる
- 件数が多いときは「返信を n件表示」で折りたたみ、開いたら最初の返信へフォーカスを移す
- その場で会話を続けるチャットはチャットのメッセージ。こちらは記事や話題に付いたコメントを、話題ごとに後から読み返す表示で、新着を自動で読み上げない
- コメントを書き込む欄はテキストエリアで作る。一覧の上か下のどちらかに決めて置き、返信の欄は返信ボタンを押したコメントの直下に開く
- 入れ子は2段までにとどめる。深くすると字下げで本文の幅が潰れ、スマートフォンでは1行に数文字しか入らなくなる
- 日時の書き方をそろえる。「3時間前」のような相対表記にするなら、time 要素の datetime に正確な日時を持たせる
- いいねの数を押すたびに変わるボタンの名前に入れない。名前は「いいね」で固定し、数はボタンの外に置く

## アクセシビリティの要件
- コメント全体を ol に、1件を li > article にする。article は利用者が投稿したコメントの典型例として HTML の仕様に挙がっている
- 返信は親のコメントの li の中に入れ子の ol で置く。字下げと線だけでなく構造でも親子を伝える(WCAG 2.2 の 1.3.1 情報及び関係性)
- list-style: none にした ol には role="list" を付ける。Safari はそうしないとリストとして読まない
- 投稿日時は time 要素にして datetime 属性を付ける
- 同じ名前の「返信」ボタンが並ぶので、aria-label を「佐藤 花子に返信」のようにして、どのコメントへの返信かを名前に入れる(見えている「返信」を名前に含める)
- いいねは aria-pressed で押した状態を伝える。見た目は色だけでなく、塗りのハートと線のハートのように形でも変える

## 参考にする実装
この形を出発点にして、プロジェクトの命名規則・色・余白に合わせて調整してください。

```html
<section class="x-comment-thread" aria-labelledby="x-comment-thread-h">
  <h2 class="x-comment-thread__h" id="x-comment-thread-h">コメント 2件</h2>
  <ol class="x-comment-thread__list" role="list">
    <li>
      <article class="x-comment-thread__c" aria-labelledby="x-comment-thread-a1">
        <div class="x-comment-thread__meta">
          <span class="x-comment-thread__av x-comment-thread__av--a" aria-hidden="true">佐</span>
          <span class="x-comment-thread__name" id="x-comment-thread-a1">佐藤 花子</span>
          <time class="x-comment-thread__time" datetime="2026-09-24T18:30">9月24日 18:30</time>
        </div>
        <p class="x-comment-thread__body">手順どおりに進めたら動きました。3番目の設定が分かりにくかったです。</p>
        <div class="x-comment-thread__act">
          <button class="x-comment-thread__b" type="button" aria-label="佐藤 花子に返信">
            <i class="fa-solid fa-reply" aria-hidden="true"></i>返信
          </button>
          <button class="x-comment-thread__b" type="button" aria-pressed="true">
            <i class="fa-solid fa-heart" aria-hidden="true"></i>いいね
          </button>
          <!-- 数は押すと変わるのでボタンの名前に入れない。状態は aria-pressed だけで伝える -->
          <span class="x-comment-thread__cnt">3件</span>
        </div>
      </article>
      <!-- 返信は親のコメントの li の中に入れ子の ol で置く。字下げと左の線で親子を見せる -->
      <ol class="x-comment-thread__replies" role="list">
        <li>
          <article class="x-comment-thread__c" aria-labelledby="x-comment-thread-a2">
            <div class="x-comment-thread__meta">
              <span class="x-comment-thread__av x-comment-thread__av--b" aria-hidden="true">編</span>
              <span class="x-comment-thread__name" id="x-comment-thread-a2">編集部</span>
              <span class="x-comment-thread__tag">投稿者</span>
              <time class="x-comment-thread__time" datetime="2026-09-25T09:10">9月25日 9:10</time>
            </div>
            <p class="x-comment-thread__body">ありがとうございます。3番目に図を足しました。</p>
            <div class="x-comment-thread__act">
              <button class="x-comment-thread__b" type="button" aria-label="編集部に返信">
                <i class="fa-solid fa-reply" aria-hidden="true"></i>返信
              </button>
              <button class="x-comment-thread__b" type="button" aria-pressed="false">
                <i class="fa-regular fa-heart" aria-hidden="true"></i>いいね
              </button>
              <span class="x-comment-thread__cnt">0件</span>
            </div>
          </article>
        </li>
      </ol>
    </li>
  </ol>
</section>
```

```css
/* 貼った先のリセットに頼らないよう、この部品の中だけ border-box にする */
.x-comment-thread,
.x-comment-thread *:not([class*="fa-"]),
.x-comment-thread *:not([class*="fa-"])::before,
.x-comment-thread *:not([class*="fa-"])::after {
  box-sizing: border-box;
  /* 貼った先の既定の書体に引きずられないようにする。書体が変わると
     文字の幅と高さが変わり、枠のサイズまでずれる */
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Noto Sans JP", "Yu Gothic UI", Meiryo, sans-serif;
}

.x-comment-thread {
  width: 330px;
  max-width: 100%;
  padding: 12px;
  border: 1px solid #e3e6ea;
  border-radius: 10px;
  background: #fff;
  color: #1b2028;
}
.x-comment-thread__h {
  margin: 0 0 8px;
  font-size: 13px;
  font-weight: 700;
}
.x-comment-thread__list,
.x-comment-thread__replies {
  margin: 0;
  padding: 0;
  list-style: none;
}
/* 返信は字下げし、左の線で「どのコメントへの返信か」を見せる */
.x-comment-thread__replies {
  margin: 8px 0 0 15px;
  padding-left: 12px;
  border-left: 2px solid #cfd4dc;
}
.x-comment-thread__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}
.x-comment-thread__av {
  display: grid;
  place-items: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font-size: 12px;
  font-weight: 700;
}
.x-comment-thread__av--a {
  background: #dbeafe;
  color: #1e40af;
}
.x-comment-thread__av--b {
  background: #dcfce7;
  color: #166534;
}
.x-comment-thread__name {
  font-size: 12px;
  font-weight: 700;
}
.x-comment-thread__tag {
  padding: 1px 6px;
  border: 1px solid #7f8a99;
  border-radius: 999px;
  color: #3f4855;
  font-size: 10px;
}
.x-comment-thread__time {
  color: #5b6472;
  font-size: 11px;
}
.x-comment-thread__body {
  margin: 4px 0 0 34px;
  font-size: 12.5px;
  line-height: 1.6;
  overflow-wrap: anywhere;
}
.x-comment-thread__act {
  display: flex;
  gap: 4px;
  margin: 2px 0 0 28px;
}
.x-comment-thread__b {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 24px;
  padding: 0 6px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: #4b5563;
  font-size: 11px;
  cursor: pointer;
}
.x-comment-thread__b:hover {
  background: #f1f3f6;
}
/* 押した状態はハートの塗りと色の両方で示す(押す前は線だけのハート) */
.x-comment-thread__b[aria-pressed="true"] {
  color: #b91c1c;
  font-weight: 700;
}
.x-comment-thread__cnt {
  align-self: center;
  color: #4b5563;
  font-size: 11px;
}
.x-comment-thread__b:focus-visible {
  outline: 2px solid #1d4ed8;
  outline-offset: 1px;
}
```

## 出力の約束
- HTML と CSS を分けて出す。JavaScript が要るときは素の JavaScript で書き、UIフレームワークは使わない。
- 参考実装がアイコンに Font Awesome のクラスを使っている場合は、プロジェクトで使っているアイコンかインライン SVG に置き換えてよい。
- 上のアクセシビリティ要件を満たす。満たせない箇所があるときは、理由を添えて先に知らせる。
- 色・角丸・余白は既存のデザイントークンがあればそれを使う。無ければ CSS 変数として切り出す。

使いどころ

  • 記事やお知らせの下に、読者のコメントと返信を並べたいとき
  • 課題やレビューの指摘ごとに、やり取りを話題単位でまとめて残したいとき

注意点

  • その場で会話を続けるチャットはチャットのメッセージ。こちらは記事や話題に付いたコメントを、話題ごとに後から読み返す表示で、新着を自動で読み上げない
  • コメントを書き込む欄はテキストエリアで作る。一覧の上か下のどちらかに決めて置き、返信の欄は返信ボタンを押したコメントの直下に開く
  • 入れ子は2段までにとどめる。深くすると字下げで本文の幅が潰れ、スマートフォンでは1行に数文字しか入らなくなる
  • 日時の書き方をそろえる。「3時間前」のような相対表記にするなら、time 要素の datetime に正確な日時を持たせる
  • いいねの数を押すたびに変わるボタンの名前に入れない。名前は「いいね」で固定し、数はボタンの外に置く

アクセシビリティの要点

  • コメント全体を ol に、1件を li > article にする。article は利用者が投稿したコメントの典型例として HTML の仕様に挙がっている
  • 返信は親のコメントの li の中に入れ子の ol で置く。字下げと線だけでなく構造でも親子を伝える(WCAG 2.2 の 1.3.1 情報及び関係性)
  • list-style: none にした ol には role="list" を付ける。Safari はそうしないとリストとして読まない
  • 投稿日時は time 要素にして datetime 属性を付ける
  • 同じ名前の「返信」ボタンが並ぶので、aria-label を「佐藤 花子に返信」のようにして、どのコメントへの返信かを名前に入れる(見えている「返信」を名前に含める)
  • いいねは aria-pressed で押した状態を伝える。見た目は色だけでなく、塗りのハートと線のハートのように形でも変える

関連するパーツ