0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Last updated at Posted at 2024-12-27

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

CSSのカウンタについて

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

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

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

li:before {
  content: "😺" counter(li-counter) ". ";
  opacity: 0.5;
}
- 猫の種類
  - 家猫
    - 短毛種
      - アメリカンショートヘア
      - ブリティッシュショートヘア
      - ロシアンブルー
    - 長毛種
      - ペルシャ
      - メインクーン
        - クラシックタイプ
        - モダンタイプ
      - ラグドール
    - 無毛種
      - スフィンクス
        - 伝統的スフィンクス
        - バンブリーナ(ドワーフスフィンクス)
      - エルフキャット

image.png

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

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

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

<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は階層構造のように見えるが、ネストされているわけではなくすべてが兄弟要素だ。
なので同じようには書けない。

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

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

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

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

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

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

: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;
}

試してみる

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

image.png

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

問題点

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

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

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

image.png

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

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

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

猫の箇条書き欲しい人用

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?