CSS Values and Units Module Level 5 に追加された random() 関数が面白そう

CSS Values and Units Module Level 5 の Editor's Draft を眺めていて気になった、ランダムな値を生成するための random() と random-item() 関数について簡単に紹介してみます。

昨日、CSS Values and Units Module Level 5 (Editor's Draft) が更新されたのに気がついたんですけども、今ってどんな内容になってんの...... と思いつつなんとなく眺めてたら、ランダムな値を生成するための random()random-item() 関数ってのが入ってました。

Editor's Draft (編集者草案) ってのは、W3C の仕様策定プロセスにおいてはまだ非公式、非承認のドキュメントですから、あまりここに書いてある内容を Web 標準仕様になるとか、ブラウザの実装が進む前提で話しても仕方ないんですが、ちょっと面白そうなので簡単に触れてみたいと思います。

例えばランダムに背景画像を変えたいな、とか、装飾に使っているアクセントカラーをランダムに出し分けたりしたいんだけど、といったニーズに CSS だけで対応することができるかもしれません。

random() 関数

定義としては下記のような感じなので、

<random()> = random( <random-caching-options>? , <calc-sum>, <calc-sum>, [by <calc-sum>]? )

random() 関数には、下記の値が引数として指定できることになります。

  • <random-caching-options>: 任意 (--foo のような値か、per-element キーワードが指定可能)
  • <calc-sum>: 最小値と最大値の 2 つが必須
  • by <calc-sum>: 任意

例えば、

random(100px, 300px)

と書いた場合 (<random-caching-options>by <calc-sum> の指定はなし)、100px 以上、300px 以下のランダムな値が返されます。つまり、234.5px とか 155px とか。

さすがにランダムすぎだろそれ、って場合は、by <calc-sum> を指定することで、段階を指定できます。例えば、

random(100px, 300px, by 50px)

と書けば、100px 以上、300px 以下で、かつ 50px 刻みのランダムな値が返されます。つまり、100px150px200px250px300px のどれかってことになりますね。

注意しないといけないのは、

random(50px, 180deg)

のように、データ型の異なる <calc-sum> の組み合わせは妥当じゃないってことです。

一方で、下記のように単位は異なっても、最終的に同じデータ型に解決されるなら (下記の場合だと、最終的に <length> 解決可能)、妥当な引数になります。

random(50px, 100%, by 1em)

<random-caching-options>

ちょっと複雑になるんですが、<random-caching-options> を使用することで、ランダムな値を複数の要素内で一致させたり、別々にしたり、みたいなことができます。

例えば下記のような指定をした場合、

.random-square {
  width: random(100px, 500px);
  height: random(100px, 500px);
}

.random-square にマッチする要素はすべて、100px 以上、500px 以下からランダムに抽出された同じ値が widthheight にセットされ、同じサイズの正方形になります。

一方で、下記のように、片方のプロパティにだけ <random-caching-options> (例として --x) を指定すると、この 2 つは random-caching key (ランダムキャッシュ Key) が異なると判断され、値の範囲は同じながら、widthheight には別々の値が返され、.random-square にマッチする要素はそのランダムなサイズで一致することになります。

.random-square {
  width: random(100px, 500px);
  height: random(--x, 100px, 500px);
}

これは、下記のように、片方にだけ by <calc-sum> を指定した場合でも同じです。

.random-square {
  width: random(100px, 500px);
  height: random(100px, 500px, by 50px);
}

要するに、まったく同じ引数に解決される random() 関数が同一の宣言ブロック内にあれば、ランダムキャッシュ Key が同じものとして扱われると。

なので、下記のように、引数の単位は違っても、最終的な計算後に値に解決される (下記の例で言えば、10em = 160px だし、20em = 320px なので) 場合は、ランダムキャッシュ Key が同じものとして扱われます。

.random-square {
  font-size: 16px;
  width: random(160px, 320px);
  height: random(10em, 20em);
}

per-element キーワード

ここまでの例だと、.random-square にマッチする要素はすべて同じサイズになったわけですけども、いや、それぞれ別々のサイズにしたいよ、ってこともあると思います。その場合は、per-element キーワードで実現できます。

前述したとおり、下記のような指定は、.random-square にマッチする要素を、サイズは毎回ランダムながら、すべて同じサイズの正方形にします。

.random-square {
  width: random(100px, 500px);
  height: random(100px, 500px);
}

これを、.random-square にマッチする要素だとしても、それぞれを異なるサイズの正方形にしたいという場合は、

.random-square {
  width: random(per-element, 100px, 500px);
  height: random(per-element, 100px, 500px);
}

上記のように指定することで、各要素がバラバラのサイズの正方形になります。

random-item() 関数

続けて、random-item() 関数を見てみましょう。

定義としては下記のような感じなので、

<random-item()> = random-item( <random-caching-options> ';' <declaration-value>? [ ';' <declaration-value>? ]* )

random-item() 関数には、下記の値が引数として指定できることになります。

  • <random-caching-options>: 必須 (random() 関数と同じ)
  • <declaration-value>: 1 つ以上必須

例えば、下記のように記述すれば、.random-bg にマッチする要素は、個別に、background-color: red; / background-color: green; / background-color: blue; いずれかが適用されることになります。

.random-bg {
  background-color: random-item(per-element; red; green; blue);
}

異なる例として、例えば下記のように記述した場合は、

.random-bg-border {
  background-color: random-item(--foo; red; green; blue);
  border-color: random-item(--foo; green; blue; red);
  border-width: 2px;
  border-style: solid;
}

background-color: red;border-color: green; の組み合わせ
background-color: green;border-color: blue; の組み合わせ
background-color: blue;border-color: red; の組み合わせ

という 3 パターンのうちの 1 パターンが、.random-bg-border にマッチする要素に適用されることになります。

この時、引数の数が異なる場合、例えば下記のように記述すると、

.random-bg-border {
  background-color: random-item(--foo; red; green; blue);
  border-color: random-item(--foo; green; blue; red; pink);
  border-width: 2px;
  border-style: solid;
}

背景色 3 色と、ボーダー色 4 色から考えられるすべての組み合わせ、つまり、12 通りの組み合わせのどれかが、.random-bg-border にマッチする要素に適用されることになります。


さて、簡単に触れるつもりが書いていたら長くなってしまいました。冒頭にも書いたとおり、この仕様はそのまま Web 標準として策定や実装が進んでいくような状態のものではありませんので、こういう案も出てるんだな、くらいで楽しんでいただけるとよいと思います。

記事をここまで御覧頂きありがとうございます。
この記事が気に入ったらサポートしてみませんか?