【CSS】calc(infinity / infinity)は何になるか?
先日、次の記事を読んでinfinityの計算について興味を持ちました。
なお、infinityの値が2147483647ではありません。calc(infinity - 2147483647)の結果も2147483647と同じなります。
infinityが実行環境における「可能な最大値」となることは知っていましたが、infinityを含む計算がどのような結果になるのかは理解していませんでした。そこでz-indexプロパティを用いて、infinityに関する計算の検証および調査を行ったので、まとめたいと思います。
infinityが絡む計算
今回検証した限りでは、infinityが絡む計算は次の3パターンにわけられます。
以降ではJavaScriptのWindow.getComputedStyle()を使用しつつ、それぞれのz-indexの値を確認していこうと思います。
結果がinfinityとなる計算
±infinityは、直接キーワードを指定する以外にも、calc()関数の計算結果として算出されることがあります。
これは、次のような計算が該当します。
- 任意の値に
±infinityを何かしらの値に加算または減算する - 任意の値を
±infinityで乗算する
z-index: calc(1 + infinity);
z-index: calc(1 - infinity);
z-index: calc(1 * infinity);
z-index: calc(1 * -infinity);
また、計算過程でinfinityキーワードを直接使用せずに、infinityの結果を得ることがあります。
- 任意の値を
0で割る - 数学関数の特定の引数の組み合わせは、
infinityとなるように定義されている- たとえば、
pow(0, -1)など
- たとえば、
z-index: calc(1 / 0);
z-index: calc(-1 / 0);
z-index: pow(0, -1);
結果が0となる計算
任意の値を±infinityで除算すると、0になります。
z-index: calc(1 / infinity)
z-index: calc(1 / -infinity);
結果がNaNとなる計算
NaNは明確に定義された値を持たない、特定の演算結果を表します。
次のような計算を行うことで、NaNとなります。
-
±infinityを±infinityで割る -
0を±infinityで乗算する -
+infinityを-infinityに加算する - 同じ符号の2つの
infinityを減算する
ちなみにタイトルのcalc(infinity / infinity)は「NaN(何)になる」が正解ですね。
z-index: calc(infinity / infinity);
z-index: calc(0 * infinity);
z-index: calc(-infinity + infinity);
z-index: calc(infinity - infinity);
また、本記事の内容(infinity)とは直接関係ないですが、以下のような操作でもNaNの結果を得ることができます。
-
0を0で割る - 数学関数の特定の引数の組み合わせは、
NaNを生成するように定義されている- たとえば
log(-1, -1)など
- たとえば
- 少なくとも1つ以上の
NaNを引数に渡す
z-index: calc(0 / 0);
z-index: log(-1, -1);
z-index: calc(NaN + 1);
NaN does not escape a top-level calculation; it’s censored into a zero value
ただし、上記に書かれているようにNaNとなった場合は、値が最終的に0に置き換えられます。
以下の例で、z-indexに値がない場合はautoになっていることからも、NaNが0に置き換えられていることがわかります。
おわりに
infinityが絡む計算について、z-indexプロパティを用いて検証および調査を行いました。基本的にCSSの数学関数は、IEEE-754と呼ばれる規格に基づいたもののようで、この辺に明るい方は理解しやすいかもしれません。
実際にCSSでinfinityを使うユースケースは少ないかもしれませんが、calc()関数を使う際には、infinityが絡む計算についても理解しておくと、想定外の挙動を避けることができるかと思います。本記事の内容が少しでもお役に立てれば幸いです。
参考
Discussion
タイトルの伏線回収が秀逸✨
z-indexプロパティだと値が整数値に丸められるため、小数値を扱えるプロパティ(例えばline-height)を使ったほうが計算結果を確認しやすいです。CSSの世界では、どのプロパティであっても数値の変域が2の32乗に収まるように設計されているのだと思います。
実際に
z-indexの最小値が-2147483648で最大値が2147483647であり、その変域は4294967296であり、これは二進法で32ビット(4バイト)に相当します。これは整ったビット列です。また、負数のほうが1つ大きいのは、2の補数表現によってビット列の先頭に
1がつくものを負数として扱っているからだと思われます。稚拙な考察を申し上げてすみません。
コメントありがとうございます。
この部分ですかね?それはおっしゃる通りだと思います。
この記事を書いた時の記憶が曖昧なので、誤っていたら申し訳ないですが、補足しておくと自分の認識は以下です。
CSSの仕様としては最大値は制限されおらず、最大値
2147483647(2^31 - 1) はブラウザ側の実装依存の値である。実際古いSafariは16777271としてた時期があるようです(参考)。「可能な最大値」という表現にしていたのは一応上記を考慮していたから、だったと思います。