【CSS】ゼロ埋めも階層化もCSSだけで!counter でリストに自動で番号(連番)を振る方法

Webサイトで「1. 2. 3.」といった番号付きリストを作る時、<ol> タグのデフォルトスタイルではデザインの自由度が低く、困ったことはありませんか?

そんな時に活躍するのが、CSSの counter-reset と counter-increment を使った「CSSカウンター」という機能です! これを使えば、HTML側に直接数字を書かなくても、CSSの擬似要素(::before)を使って自由に連番を生成・デザインすることができます。

今回は、基本の使い方から、よく使う「01, 02のようなゼロ埋め」「Step 1などの文字追加」「1-1, 1-2などの階層化」まで、コピペで使えるデモをまとめました!

デモ動作

See the Pen CSSカウンターで作る!自動連番リスト by mikanbako (@mikanbako) on CodePen.

全画面でのデモ動作は以下のリンクからご確認下さい!(別タブで開かれます)

実装コード紹介

【HTML】

<div class="l-wrap">
  <h2>CSSカウンター 活用デモ</h2>
  
  <div class="p-demo-box">
    
    <!-- 💡 1. ゼロ埋め(01, 02...) -->
    <section class="p-section">
      <h3>1. ゼロ埋めスタイル(01, 02...)</h3>
      <ul class="c-list-zero">
        <li class="c-list-zero__item">要件定義・デザイン作成</li>
        <li class="c-list-zero__item">HTML/CSS/JSコーディング</li>
        <li class="c-list-zero__item">テスト・公開</li>
      </ul>
    </section>

    <!-- 💡 2. テキスト付き(Step 1, Step 2...) -->
    <section class="p-section">
      <h3>2. カスタムテキスト付き(Step 1, Step 2...)</h3>
      <ul class="c-list-step">
        <li class="c-list-step__item">お問い合わせ</li>
        <li class="c-list-step__item">お見積もりのご提示</li>
        <li class="c-list-step__item">ご契約・制作開始</li>
      </ul>
    </section>

    <!-- 💡 3. 階層化(1-1, 1-2...) -->
    <section class="p-section">
      <h3>3. 階層化(ネスト)スタイル(1-1, 1-2...)</h3>
      <ol class="c-list-nested">
        <li class="c-list-nested__item">はじめに
          <ol class="c-list-nested">
            <li class="c-list-nested__item">ご挨拶</li>
            <li class="c-list-nested__item">本記事の目的
              <ol class="c-list-nested">
                <li class="c-list-nested__item">サンプル</li>
                <li class="c-list-nested__item">Sample</li>
              </ol>
            </li>
          </ol>
        </li>
        <li class="c-list-nested__item">メインコンテンツ
          <ol class="c-list-nested">
            <li class="c-list-nested__item">サンプル</li>
            <li class="c-list-nested__item">Sample</li>
          </ol>
        </li>
      </ol>
    </section>
  </div>
</div>

【CSS】

/* ベース装飾 */
.l-wrap {
  padding: 40px 20px;
  max-width: 700px;
  margin: 0 auto;
  line-height: 1.6;
  color: #3e3e3e;
}

h2 {
  margin-bottom: 30px;
  font-size: 16px;
  color: #1bb4d4;
  text-align: center;
}

.p-demo-box {
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.p-section {
  padding: 30px;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 4px 15px rgb(0 0 0 / 5%);
}

h3 {
  padding-bottom: 10px;
  margin-bottom: 20px;
  font-size: 18px;
  font-weight: bold;
  border-bottom: 2px solid #eee;
}

/* =========================================
   💡 1. ゼロ埋めスタイル
========================================= */
.c-list-zero {
  list-style: none; /* デフォルトの点を消す */

  /* 親要素でカウンターを初期化(名前は任意でOK) */
  counter-reset: zero-counter;
}

.c-list-zero__item {
  position: relative;
  padding-left: 40px;
  margin-bottom: 15px;
  font-size: 16px;

  /* 各li要素でカウンターを1ずつ増やす */
  counter-increment: zero-counter;
}

.c-list-zero__item::before {
  position: absolute;
  top: 0;
  left: 0;
  font-size: 18px;
  font-weight: bold;
  color: #1bb4d4;

  /* decimal-leading-zero を指定してゼロ埋め! */
  content: counter(zero-counter, decimal-leading-zero);
}

/* =========================================
   💡 2. カスタムテキスト付き(Step 1など)
========================================= */
.c-list-step {
  list-style: none;
  counter-reset: step-counter; /* カウンター初期化 */
}

.c-list-step__item {
  position: relative;
  padding-left: 70px; /* Stepの文字が入る分、余白を広めに */
  margin-bottom: 15px;
  font-size: 16px;
  counter-increment: step-counter; /* カウンター増加 */
}

.c-list-step__item::before {
  position: absolute;
  top: 0;
  left: 0;
  padding: 2px 8px;
  font-size: 14px;
  font-weight: bold;
  color: #fff;

  /* 文字列とカウンターを組み合わせる! */
  content: "Step " counter(step-counter);
  background: #e83e8c;
  border-radius: 4px;
}

/* =========================================
   💡 3. 階層化(ネスト)スタイル
========================================= */
.c-list-nested {
  padding-left: 20px; /* 階層ごとのインデント */
  list-style: none;
  counter-reset: nested-counter; /* カウンター初期化 */
}

.c-list-nested__item {
  position: relative;
  margin-bottom: 8px;
  font-size: 16px;
  counter-increment: nested-counter; /* カウンター増加 */
}

.c-list-nested__item::before {
  margin-right: 8px;
  font-size: 16px;
  font-weight: bold;
  color: #28a745;

  /* counters関数を使うと、親の番号を引き継いで区切り文字を指定できる! */
  content: counters(nested-counter, "-");
}

コードの解説・仕組み

CSSカウンターの基本ルール

CSSカウンターを機能させるには、以下の3つのステップが必須です。これさえ覚えておけば迷いません!

  • counter-reset: 名前;
    親要素(ul や ol)に指定して、カウンターを「0」にリセットします。
  • counter-increment: 名前;
    子要素(li)に指定して、カウンターを「1」ずつ増やします。
  • content: counter(名前);
    子要素の擬似要素(::before)に指定して、画面に数字を出力します。
/* =========================================
   💡 基本ステップ
========================================= */
ul,
ol {
  ...

  counter-reset: test-counter; /* カウンター初期化 */
}

li {
  ...

  counter-increment: test-counter; /* カウンター増加 */
}

li::before {
  ...

  /* カウンターを出力 */
  content: counter(test-counter);
}

便利な応用テクニック

ゼロ埋め
content: counter(名前, decimal-leading-zero); と第2引数を指定するだけで、01, 02… と自動でゼロ埋めしてくれます。

/* =========================================
   💡 1. ゼロ埋めスタイル
========================================= */
.c-list-zero__item::before {
  ...

  /* decimal-leading-zero を指定してゼロ埋め! */
  content: counter(zero-counter, decimal-leading-zero);
}

階層化
親の番号を引き継いで「1-1」「1-2」のようにしたい時は、counter() ではなく複数形の counters(名前, "区切り文字") を使うと実装できます!

/* =========================================
   💡 3. 階層化(ネスト)スタイル
========================================= */
.c-list-nested__item::before {
  ...

  /* counters関数を使うと、親の番号を引き継いで区切り文字を指定できる! */
  content: counters(nested-counter, "-");
}

補足:公式ドキュメント

・MDN: counter()
・MDN: counters()

まとめ

今回はCSSの counter-reset を使った、リストの自動採番テクニックをご紹介しました。

手動でHTMLに数字を書き込んでしまうと、後から項目が追加・削除された時にすべての数字を修正しなければならず、保守性が非常に悪くなってしまいます。

CSSカウンターを使えば、ブラウザが自動で番号を計算してくれるため、メンテナンスしやすいコードを書くことができます。ぜひこのテクニックをマスターしてご自身のWeb制作に利用してみてください!

Prev
Next