JS使わずCSSだけでmarkdownの見出し要素(h1など)にナンバリングできるんか？

出来たっぽいけど正直よく分かってない

## CSSのカウンタについて

* MDN
  * [counter-reset - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/counter-reset)
      * `counter-reset: hoge`
          * カウンタ`hoge`を0(または指定した値)にする。
  * [counter() - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/counter)
      * `counter-increment: hoge`
          * カウンタ`hoge`を1(または指定した値)増やす。
  * [counter-increment - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/counter-increment)
      *  `counter(hoge)`
          *  カウンタ`hoge`を値として利用する。

リストのネストが分かりやすい。
リストがネストされるたびにカウンタが0に戻る。

```css
ul, ol {
  counter-reset: li-counter;
}

li {
  counter-increment: li-counter;
  list-style-type: none;
}

li:before {
  content: "😺" counter(li-counter) ". ";
  opacity: 0.5;
}
```

```md
- 猫の種類
  - 家猫
    - 短毛種
      - アメリカンショートヘア
      - ブリティッシュショートヘア
      - ロシアンブルー
    - 長毛種
      - ペルシャ
      - メインクーン
        - クラシックタイプ
        - モダンタイプ
      - ラグドール
    - 無毛種
      - スフィンクス
        - 伝統的スフィンクス
        - バンブリーナ（ドワーフスフィンクス）
      - エルフキャット
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18902/d9eed1bf-a33d-ebff-7d54-b49b22ae109a.png)

このカウンタはグローバル変数みたいな扱いで、ページ内の全要素で共用らしい。
多分。いや違う気がしてきた。

### 箇条書きと見出しのナンバリング方法の違い

箇条書きはネストされるから分かりやすい。
ul,olの中にliがいて、ネストされる場合はliの中にさらにul, olが入る。
なので、ul, olでresetしてliでincrementすればいい。

```html
<ul>
    <li>猫の種類
        <ul>
            <li>家猫
                <ul>
                    <li>短毛種
                        <ul>
                            <li>アメリカンショートヘア</li>
                            <li>ブリティッシュショートヘア</li>
                            <li>ロシアンブルー</li>
                        </ul>
                    </li>
                    <li>長毛種
                        <ul>
                            <li>ペルシャ</li>
                            <li>メインクーン<ul>
                                    <li>クラシックタイプ</li>
                                    <li>モダンタイプ</li>
                                </ul>
                            </li>
                            <li>ラグドール</li>
                        </ul>
                    </li>
```

markdown等の見出しにナンバリングすることを考える。
h1, h2, h3は階層構造のように見えるが、ネストされているわけではなくすべてが兄弟要素だ。
なので同じようには書けない。

```md
# でかい見出し
## 次にでかい見出し
### 中くらいの見出し
```

```html
<h1>でかい見出し</h1>
<h2>次にでかい見出し</h2>
<h3>中くらいの見出し</h3>
```

## 見出しでナンバリングするには？

どうすればいいのか？
同じように考えると、見出し要素が来たとき、自分より弱い見出しをリセットすればいい。

h1が来たら、h1未満の要素のカウンタをリセットすればいい。
`counter-reset`は一度に複数のカウンタをリセットできる。
(当たり前だが`counter-reset`を複数書いたら最後のものだけが残るので注意。これで時間溶かした)


だがそれどう書くんだって話で、3時間溶かした末に出来たっぽいやつが以下。

`h1`には`i1`などの名前のカウンタを用意した。見にくいかも。

```css
:has(> h1) {
    counter-reset: i1;
}

h1 {
    counter-increment: i1;
    counter-reset: i2 i3 i4 i5 i6;
    --indent: "# "
}


h2 {
    counter-increment: i2;
    counter-reset: i3 i4 i5 i6;
    --indent: "## "
}

h3 {
    counter-increment: i3;
    counter-reset: i4 i5 i6;
    --indent: "### "
}

h4 {
    counter-increment: i4;
    counter-reset: i5 i6;
    --indent: "#### "
}

h5 {
    counter-increment: i5;
    counter-reset: i6;
    --indent: "##### "
}

h6 {
    counter-increment: i6;
    --indent: "###### "
}

:is(h1, h2, h3, h4, h5, h6):before {
    content: "[" counter(i1) "/" counter(i2) "/" counter(i3) "/" counter(i4) "/" counter(i5) "/" counter(i6) "] " var(--indent) ;
    font-size: 0.8rem;
    display: inline-block;
    font-family: 'Courier New', Courier, monospace;
    opacity: 0.4;
    margin-right: 4px;
}
```

## 試してみる

```md
# 猫の種類
## 家猫
### 短毛種
#### アメリカンショートヘア
#### ブリティッシュショートヘア
#### ロシアンブルー
### 長毛種
#### ペルシャ
#### メインクーン
##### クラシックタイプ
##### モダンタイプ
#### ラグドール
### 無毛種
#### スフィンクス
##### 伝統的スフィンクス
##### バンブリーナ（ドワーフスフィンクス）
#### エルフキャット
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18902/031a8060-807b-6401-88a3-ce357928d021.png)

俺より強いやつが会いに来たらちゃんと0に戻ってるみたい。

## 問題点

ここでは`h1`要素を直接の子に持つ要素、つまり`h1`の直近の親要素のみで`i1`をリセットしてる。
親ごとに見出しのカウントは別々で行いたいから。

```
:has(> h1) {
    counter-reset: i1;
}
```

で、ここで `counter-reset: i1 i2 i3 i4 i5 i6;`みたいに全部リセットするとカウンタがリセットされなくなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18902/e4f373cb-2d07-fecb-b2cf-decd942347cc.png)

たぶんリセットされた時点で別の変数扱いになる・・・？
長毛種のとこでi4が0になってるのに、ペルシャでは4になってるから。
あんまり分かってない。教えてほしい。
cssってJavaScriptと違ってデバッグしにくすぎない・・・？やり方知らないだけか

あと、見出しの並びが邪知暴虐で階層構造になってない場合はちゃんと動かないのかもしれない。
一応色々試しはしたけど他にも何か変な挙動することありそう。

改善点あったり上記問題を解決する方法あれば教えてくれたら助かるます。
眠いので以上です。

## 猫の箇条書き欲しい人用

https://chatgpt.com/share/676edbf3-ca38-800e-bb20-5a64190060cc