:has()を使って親要素内に存在する子要素を数えるCSSのサンプル

Ads

Result

かなり世間から遅れていて今更感ありますが目を惹かれたサンプルを見かけたので:has()を試してみようと思います。

What’s Missing From CSS?でも結果として出ていましたが、:has()はずっとCSSに求められていた機能でしたのでやっと来たかという思いの方も多そうですね。

タイトル通り、上記サンプルは親要素内に存在する子要素を数え、それに応じてスタイルを変更するサンプルです。

表示されるテキストの変化はdata属性で実装されています。数字のカウンターはcounter-incrementcontent: counter(count);が使われています。

css

.list {
  --color: black;
  
  color: var(--color);
}

ul {
  border: 3px solid var(--color);
  padding: 0;
  color: #000;
  list-style: none;
  counter-reset: count;
}

li {
  counter-increment: count;
  margin: 0;
  padding: 0.5rem 0.5rem 0.2rem 4.5ch;
  height: 1.8rem;
  position: relative;
}

li::before {
  content: counter(count);
  display: inline-block;
  background: #000;
  color: #fff;
  padding: 0.5rem;
  margin-right: 1rem;
  width: 4ch;
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  box-sizing: border-box;
  }

.list:focus-within {
  --color: rgb(11, 103, 162);
}

.list::before {
  content: attr(data-default);
}

.list:focus-within::before {
  content: attr(data-empty-focus);
}

.list:has(li:nth-child(2)) {
  --color: rebeccapurple;
}

.list:has(li:nth-child(3)) {
  --color: rgb(255, 111, 0);
}

.list:has(li:nth-child(4) > :first-child) {
  --color: rgb(203, 157, 0);
}

.list:has(li:nth-child(4)) {
  --color: rgb(76, 113, 32);
}

.list:has(li:nth-child(5)) {
  --color: red;
}

.list:has(li:nth-child(2))::before {
  content: attr(data-great-choice)
}

.list:has(li:nth-child(3) > :first-child)::before,
.list:has(li:nth-child(3))::before{
    content: attr(data-half);
}

.list:has(li:nth-child(4):last-child)::before {
    content: attr(data-done);
}

.list:has(li:nth-child(4) > :first-child)::before {
    content: attr(data-one-more);
}

.list:has(li:nth-child(5))::before {
    content: attr(data-too-much);
}

.list:has(li:nth-child(5))::before {
    content: attr(data-too-much);
}

.list:has(li:nth-child(5) > :first-child)::before {
    content: attr(data-almost-too-much);
}

説明は特に不要かと思います。子の数に応じてスタイルを変更しているのが分かります。

下記に開設記事にもリンクしているので分からない方はご確認下さい。

Ads

html

<div class="list"
     data-default="任意のキーワードを入力してエンターを押して追加します。追加できるのは4つまでです。"
     data-great-choice="素晴らしい!次はどんなキーワードですか?"
     data-empty-focus="最初のキーワードを入力中"
     data-half="良いですね!残りは2つです。"
     data-one-more="では、最後のキーワードです!"
     data-done="完璧です!言う事はありません。これ以上はダメですよ。"
     data-almost-too-much="ダメって言いましたよね?"
     data-too-much="追加するの?マジあり得ない。"
>
  
  <ul contenteditable>
    <li></li>
  </ul>
  
</div>

can i use

:has()疑似クラスのブラウザ対応状況です。

正直、以前ならまだかな、という感想を持ったと思いますが、Firefoxのシェア率を見ると「まぁいいか」と思う方も少なくないかもしれません。

個人的には頑張って欲しいのですが、現状はWebkitが1強、特にChrome系が強すぎて厳しいですね。

via

Parents counting children in CSS