超実践! CSS変数の活用方法 第1回 シンプル編:指定した値を活用する
CSS変数を使った実装のアイデアを紹介します。第1回では、CSS変数で指定した値をどんなふうに利用できるのかにフォーカスします。CSS変数を使うと通常はできなかった値の使い回しが可能になることがわかります。
はじめに
CSS変数(CSS Variables)は、CSSプロパティの値を1箇所に予め定義しておける機能です。CSS変数は、CSSカスタムプロパティ、カスケード変数と呼ばれることもあります。
文法は次のようになっています。
CSS変数
:root {
--green: #008b8b;
}上記のCSSの--greenが変数名です。ハイフンを2つ繋げて始めます。大文字と小文字を区別するので、--greenと--Greenは異なる変数になります。CSS変数は通常のCSSと同様に値を継承するので、:root擬似クラスを指定すると、サイト全体で使うことができます。
なお、:rootはHTMLにおいてhtmlを指定したのと同義です。SVGの文脈では:rootはsvgとなります。ですから上記のコードは以下とほとんど同じように機能します。
CSS変数
html {
--green: #008b8b;
}CSS変数に指定した値を使うためには、次のように記述します。
CSS変数を使う
.sample {
color: var( --green );
}あるプロパティの値として、var()として変数名を指定すると、そのCSS変数の値が指定されたことになります。あとはsampleクラスがHTMLなどで指定されると、その要素に通常のCSSの適用ルールに従って適用されます。
これが、CSS変数の基本の基本です。
CSS変数は、今や、すべての主要ブラウザで使えるようになっています。
CSS変数はシンプルに色や大きさ(ピクセル数)などを定義しておくといった使い方はもちろんですが、それ以外にもHTMLからの指定、何らかの計算用途、JSとのやり取りなど、さまざまな応用が可能です。
CSS変数に似た機能はSassにも従来から存在しますが、Sass変数よりもたくさんの機能があります。CSS変数ならではの具体的な活用例を紹介します。
お品書き
以下がこのシリーズで紹介予定の「技」の数々です。なるほど……こうやればいいのか、とさらっと読めるものから、少し頭をひねってパズルのように考えてほしいものまでさまざまです。最後はHTMLとCSSだけでなく、JavaScriptとの連携についても触れたいと思います。
- シンプル編:指定した値を活用する
- 長い値を指定する
- style属性でもメディアクエリーに対応できる
- フォントサイズ
- 画像の大きさ
- style属性でも疑似クラスや疑似要素に対応できる
- ちょっと複雑編:変数を計算して活用する
- 真偽値(boolean)的に利用する
- CSS Animationで、元のtransformを維持する
- 値を複合して利用する
- がんばろうJS編:JavaScriptと連携して活用する
- 値をJavaScriptから入力する
- 値をJavaScriptで取得する
なお、以降紹介するケースのソースコードは、CodeGridのリポジトリにまとまっています。参考にしてください(今回以降のデモは変更される可能性もあります)。
「超実践! CSS変数活用術」シリーズ リポジトリ
長い値を指定する
CSS変数の用途としては、色や文字サイズ、余白量といった、「定数」の宣言がいち早く思い浮かぶのではないでしょうか。
同様の方法で、CSS変数には、長い値を指定しておくのも有効です。
フォントセットの指定
たとえば、font-familyのフォントセット。これは継承値が途切れてしまったときに役立ちます。
font-familyは多くの場合、順序を決めて複数のフォント名を指定するため、長くやや複雑になることがほとんどのはずです。
そして、HTML構造によっては、font-familyの継承が途切れてしまうこともあります。このとき、font-familyを再度設定し直すことになりますが、font-familyの長い値を、毎回同じ順序で管理するには神経を尖らせる必要があります。
長い値でもCSS変数にまとめておけば、もれなく対応ができるはずです。
CSS:フォントセットの指定
:root {
--font-serif: "Noto Sans JP", "Noto Sans", "Source Han Sans JP", "Noto Sans Japanese", "Noto Sans CJK JP", "Hiragino Kaku Gothic ProN", "Hiragino Kaku Gothic Pro", "xYuGothic", Meiryo, sans-serif;
}
html {
font-family: var( --font-serif );
}
.heading {
font-family: "Oswald", sans-serif;
}
/* heading のフォントを上記で書き換えたけれど、局所的に戻したいケース */
.heading .headingLead {
font-family: var( --font-serif );
}HTML
<h2 class="heading">
<span class="headingLead">
新鮮な魚
</span>
Fish
</h2>上記のCSSではheadingクラスで、font-familyの設定を書き換えています。ですが、局所的に、指定してあったfont-familyに戻しています。
もし、CSS変数を使わないと、次のように長い指定を繰り返し書かなければいけません。
CSS:CSS変数を使わない場合
.heading .headingLead {
font-family: "Noto Sans JP", "Noto Sans", "Source Han Sans JP", "Noto Sans Japanese", "Noto Sans CJK JP", "Hiragino Kaku Gothic ProN", "Hiragino Kaku Gothic Pro", "xYuGothic", Meiryo, sans-serif;
}dataURLの値の指定
あるいは、似た例としてdataURIのような、長い値を指定するのにも向いています。これなら、長い値が何度も登場してしまう煩わしさやCSSファイル容量の肥大化をだいぶ軽減できます。
CSS:dataURLの値の指定
:root {
--icon-colored-arrow-right: url( "data:image/svg+xml,%3Csvg height=%22128%22 viewBox=%220 0 128 128%22 width=%22128%22 xmlns=%22http://www.w3.org/2000/svg%22%3E%3Cpath d=%22m4 57.86h44.97v13.25h-44.97z%22 fill=%22%23f14e23%22/%3E%3Cpath d=%22m56.86 25.24v15.29l40.65 23.47-40.65 23.47v15.29l67.14-38.76z%22 fill=%22%23fede00%22/%3E%3Cpath d=%22m26.49 25.98v15l39.86 23.02-39.86 23.02v15l65.84-38.02z%22 fill=%22%232cafe5%22/%3E%3C/svg%3E" );
}
.someButton::after {
content: '';
display: block;
width: 1.4em;
height: 1.4em;
/* 実態文字列の長さを気にせず、変数を複数箇所で使い回せます */
background: var( --icon-colored-arrow-right ) 0 0 / 100% 100%
}注意点は、CSSのurl(…)は、引数部分込みで一つの値だという点です。ですのでurl( var( --src ) )のような使い方はできません。
CSS:無効な指定
:root{
--src: "http:example.com/img.png";
}
.myDiv {
background-image: url( var( --src ) );
}変数にする場合はurl()込みの文字列にする必要があります。
CSS:有効な指定
:root{
--url: url("http:example.com/img.png");
}
.myDiv {
background-image: var( --url );
}一方で、image()という関数 が存在し、これならurl()よりも柔軟に引数を指定することができます。ただし、本稿執筆時点(2023年10月)では、image()に対応しているブラウザはありません。
style属性でもメディアクエリーに対応できる
通常、style属性の中では、メディアクエリーを扱うことができないため「style属性で局所的に文字サイズを上書きしたいけれど、レスポンシブにできない」といった悩みがでてきます。
CSSならこれを解決できます。CSS変数がCSS内にあれば、HTMLのstyle属性からCSS変数の値を指定することができます。もちろん、font-sizeだけでなく、text-alignなどその他のプロパティでも同様のことができます。
予め、2つの変数を用意しておき、それをメディアクエリーに応じて切り替えます。var()の2つ目の引数には、「変数が未定義だった場合」のフォールバック値を指定できます。
フォントサイズを指定
レスポンシブにフォントサイズを変えたいケースを想定して、具体的なコードで説明します。
次の指定では、画面幅が681px以上の場合、--font-size-lに指定されている値が使われ、変数が未指定だったときは、16pxになります。画面幅が680px以下だった場合は、--font-size-sに指定されている値が使われ、未指定のときは、12pxになります。
--font-size-lと--font-size-sは後述のHTMLで指定して、CSSに渡されます。
CSS:メディアクエリーでのCSS変数の利用
@media (min-width: 681px) {
.someText {
font-size: var( --font-size-l, 16px );
}
}
@media (max-width: 680px) {
.someText {
font-size: var( --font-size-s, 12px );
}
}さて、HTMLのstyle属性では、font-sizeプロパティに対して値を直接指定するのではなく、メディアクエリーの閾値ごとに変数を指定していきます。この変数に指定された値が上記のCSSに反映されます。
HTML:CSS変数の指定
<p class="someText" style="--font-size-l: 20px; --font-size-s: 10px;">
変数で指定されたテキスト
</p>以下のデモを別ウインドウで開いて、ブラウザ幅を変えると動作を確認できます。比較のために、次のようなstyle属性の指定のないp要素を配置しています。このp要素にはCSS変数が未指定の場合のフォントサイズが適用されるはずです。
HTML:CSS変数未指定
<p class="someText">
未指定テキスト
</p>デモは別ウインドウで開いて確認してみてください。
動作は次のようになります。
- 画面幅が広いとき(681px以上)
- 未指定テキスト:16px
- 変数で指定されたテキスト:20px
- 画面幅が狭いとき(680px以下)
- 未指定テキスト:12px
- 変数で指定されたテキスト:10px
画像サイズの指定
画像のサイズを指定する場合にもCSS変数はとても役に立ちます。レスポンシブレイアウトで実装をしていると「いろいろなサイズの画像が挿絵として入っているけれど、それぞれの画像の元の大きさの半分のサイズ」で表示したい、という場面はありませんか? CSS変数なら、画像ごとに値を指定できます。
たとえば、レスポンシブレイアウトをしていて、次のような要件があったとします。
- 画面幅が広いとき(681px以上):画像サイズの半分
- 画面幅が狭いとき(680px以下):画像サイズの100%
この場合、HTMLでは、style属性に元の画像サイズをCSS変数で明示しておきます。
HTML:style属性で画像サイズを指定
<div class="image">
<img src="./w600.png" alt="" style="--natural-width: 600px;">
</div>
<div class="image">
<img src="./w400.png" alt="" style="--natural-width: 400px;">
</div>CSS内では、HTMLのstyle属性に指定してある画像の大きさを使って、その半分の値を算出します。CSSの「/2(割る2)」の部分を変えれば、元の大きさに対する好きな拡大率を指定できます。
CSS:CSS変数でサイズを計算
@media (min-width: 681px) {
.image img {
display: block;
width: calc( var( --natural-width ) / 2 );
max-width: 100%;
}
}
@media (max-width: 680px) {
.image img {
width: 100%;
}
}次のデモも別ウインドウで試してみてください。
style属性でも疑似クラスや疑似要素に対応できる
前節と同様に、style属性から:hoverなどの擬似クラス、::beforeなどの疑似要素のスタイルを、CSS変数を経由して、指定することができます。
次のコードのように、予め擬似クラスや疑似要素の中に、CSS変数をセットしておけば、要素自体のstyle属性に適用した値を継承して擬似クラスや疑似要素内に反映できます。
CSS:擬似要素にCSS変数を指定
.someButton::before {
content: var( --content-before );
}上記のCSSに対して、.someButtonのstyle属性に指定されたCSS変数を、その擬似要素で利用しています。
HTML:style要素でCSS変数に値を指定
<p class="someButton" style="--content-before: '☺️';">
テキスト
</p>
<p class="someButton" style="--content-before: '😱';">
テキスト
</p>まとめ
今回は実務でもよく見かける実装に、CSSを活用するならどのように使うことができるか、できるだけ身近なケースになるように紹介しました。シンプル編ということで、ソースコードもあまり複雑ではありませんが、HTMLとCSSが、CSS変数を経由して、どのように関連するのか、値の往来を捉えられるといいと思います。
次回はさらにもう一歩踏み込んで、CSS変数を真偽値的に使ったり、入れ子にして使ったり、ちょっと複雑な使い方を紹介します。