ネギ鍋のイラスト

アップグレードされた CSS の `attr()` 関数を使う

`attr()` 関数は HTML の属性を読み取り、それを CSS で利用できるようにする関数です。従来までは `content` プロパティのみで使用できましたが、CSS Values and Units Module Level 5 ではこの制限が見直され、`attr()` 関数がカスタムプロパティを含む任意の CSS プロパティで使用できるようになりました。

attr() 関数は HTML の属性を読み取り、それを CSS で利用できるようにする関数です。よくある使われ方として data-* 属性の値を読み取りその値をコンテンツに表示するというものです。

<ul>
  <li data-fruit="🍎">Apple</li>
  <li data-fruit="🍌">Banana</li>
  <li data-fruit="🍊">Orange</li>
</ul>
 
<style>
  li::before {
    content: attr(data-fruit);
  }
</style>

attr() 属性のもっと複雑な使用例も思いつきそうなのですが、attr() 属性は content プロパティのみで使用できるという制限がありました。しかし、CSS Values and Units Module Level 5 ではこの制限が見直され、attr() 関数がカスタムプロパティを含む任意の CSS プロパティで使用できるようになりました。また、値を <string> 型以外にも解析可能です。この機能は Chrome v133 以降で利用可能です。

この記事では新しい attr() 関数の使い方を紹介します。

動的にカラーを指定する

記事のリストがあって、記事のカテゴリごとに文字色やボーダーの色を変えたい、みたいな状況だったします。素朴に書くと以下のように記事のカテゴリごとに CSS の class を指定することになります。

<div class="entry categoryLife">
  <!-- ... -->
</div>
 
<div class="entry categoryTech">
  <!-- ... -->
</div>
 
<div class="entry categoryFood">
  <!-- ... -->
</div>
.entry {
  /* ... */
}
 
.categoryLife {
  color: red;
  border-color: red;
}
 
.categoryTech {
  color: blue;
  border-color: blue;
}
 
.categoryFood {
  color: green;
  border-color: green;
}

この方法はカテゴリが増えるたびに CSS を追加しなければならないので、管理が面倒です。代わりに attr() 関数を使った方法を試してみましょう。

先ほどの例で className にカテゴリ名を指定する代わりに、data-color 属性にカラーコードを指定します。

<div class="entry" data-color="red">
  <!-- ... -->
</div>
 
<div class="entry" data-color="blue">
  <!-- ... -->
</div>
 
<div class="entry" data-color="green">
  <!-- ... -->
</div>

CSS 側では attr() 関数を使用して data-color の値を読み取ります。このとき attr() で取得した値が <string> 型ではなく <color> 型として解釈されるように attr() 関数に属性の型(type(<color>))を指定します。また 2 つ目の引数にはフォールバック値を指定します。

.entry {
  color: attr(data-color type(<color>), black);
  border: 1px solid attr(data-color type(<color>), black)
}

これによりカテゴリごとに CSS を追加する必要がなくなり、.entry クラスだけを管理すればよくなります。

とはいえ CSS のカスタムプロパティを style 属性に指定すれば今までも同じようなことができました。

<div class="entry" style="--color: red">
  <!-- ... -->
</div>
  
<div class="entry" style="--color: blue">
  <!-- ... -->
</div>
 
<div class="entry" style="--color: green">
  <!-- ... -->
</div>
.entry {
  color: var(--color, black);
  border: 1px solid var(--color, black);
}

それぞれの方法に一長一短があると思いますが、attr() 属性を使用する方法はスコープがより限られているという点で利点があると言えます。attr() 属性はその要素のみの属性を読み取るため、親要素の data-* 属性を誤って読み取る心配がありません。

グリッドレイアウトで使用する

グリッドレイアウトにおいてそれぞれのセルの幅を個別の要素で指定する場合には grid-columngrid-row プロパティを使用します。grid-columngrid-row プロパティに span <integer> を指定することでセルの幅を指定できますが、使いたいセルの幅ごとに CSS を追加するのは不便です。

セルの幅を data-colspan 属性で指定し、attr() 関数を使用してその値を読み取るようにすれば、簡単にセルの幅を指定できます。

<div class="grid">
  <div class="cell" data-colspan="2">2</div>
  <div class="cell" data-colspan="3">3</div>
  <div class="cell" data-colspan="1">1</div>
  <div class="cell" data-colspan="4">4</div>
 
  <div class="cell" data-colspan="5">5</div>
  <div class="cell" data-colspan="5">5</div>
</div>
.grid {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
}
 
.cell {
  grid-column: span attr(data-colspan type(<integer>), 1);
}

その他にも grid-template-area プロパティで使用する名前を attr() 関数で指定する方法も便利です。grid-area プロパティに指定する方は <custom-ident> 型です。

<div class="grid">
  <header data-name="head">ヘッダー</header>
  <nav data-name="nav">ナビゲーション</nav>
  <main data-name="main">メイン領域</main>
  <footer data-name="foot">フッター</footer>
</div>
.grid {
  display: grid;
  width: 100%;
  height: 250px;
  grid-template-areas:
    "head head"
    "nav  main"
    ".  foot";
  grid-template-rows: 50px 1fr 30px;
  grid-template-columns: 150px 1fr;
  
  & > * {
    grid-area: attr(data-name type(<custom-ident>), auto);
    border: 1px solid #bbb;
  }
}

まとめ

  • CSS Values and Units Module Level 5 では attr() 関数がカスタムプロパティを含む任意の CSS プロパティで使用できるようになる。Chrome v133 以降で利用可能
  • 新しい attr() 関数では <string> 型以外にも <color>, <integer>, <custom-ident> などのさまざまな型を解析可能
  • attr() 関数の 2 つ目の引数にはフォールバック値を指定できる

参考

記事の理解度チェック

以下の問題に答えて、記事の理解を深めましょう。

CSS の `attr()` 関数で `data-color` 属性を `<color>` 型に解析する記述方法として正しいものはどれか

  • attr(data-color type(<color>), black)

    正解!

  • attr(data-color type(color), black)

    もう一度考えてみましょう

  • attr(data-color, color, black)

    もう一度考えてみましょう

  • attr(data-color, type<color>, black)

    もう一度考えてみましょう


Contributors

> GitHub で修正を提案する
この記事をシェアする
はてなブックマークに追加

関連記事