📘

【CSS】calc(infinity / infinity)は何になるか?

2024/02/07に公開2

先日、次の記事を読んでinfinityの計算について興味を持ちました。

https://zenn.dev/crayfisher_zari/articles/d98a0aef6326a8

なお、infinityの値が2147483647ではありません。calc(infinity - 2147483647)の結果も2147483647と同じなります。

infinityが実行環境における「可能な最大値」となることは知っていましたが、infinityを含む計算がどのような結果になるのかは理解していませんでした。そこでz-indexプロパティを用いて、infinityに関する計算の検証および調査を行ったので、まとめたいと思います。

infinityが絡む計算

今回検証した限りでは、infinityが絡む計算は次の3パターンにわけられます。

以降ではJavaScriptのWindow.getComputedStyle()を使用しつつ、それぞれのz-indexの値を確認していこうと思います。

結果がinfinityとなる計算

±infinityは、直接キーワードを指定する以外にも、calc()関数の計算結果として算出されることがあります。

これは、次のような計算が該当します。

  • 任意の値に±infinityを何かしらの値に加算または減算する
  • 任意の値を±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)など
結果がinfinityとなる計算
z-index: calc(1 / 0);
z-index: calc(-1 / 0);
z-index: pow(0, -1);

結果が0となる計算

任意の値を±infinityで除算すると、0になります。

結果が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(何)になる」が正解ですね。

結果がNaNとなる計算
z-index: calc(infinity / infinity);
z-index: calc(0 * infinity);
z-index: calc(-infinity + infinity);
z-index: calc(infinity - infinity);

また、本記事の内容(infinity)とは直接関係ないですが、以下のような操作でもNaNの結果を得ることができます。

  • 00で割る
  • 数学関数の特定の引数の組み合わせは、NaNを生成するように定義されている
    • たとえばlog(-1, -1)など
  • 少なくとも1つ以上のNaNを引数に渡す
結果がNaNとなる計算
z-index: calc(0 / 0);
z-index: log(-1, -1);
z-index: calc(NaN + 1);

https://www.w3.org/TR/css-values-4/#calc-ieee

NaN does not escape a top-level calculation; it’s censored into a zero value

ただし、上記に書かれているようにNaNとなった場合は、値が最終的に0に置き換えられます

以下の例で、z-indexに値がない場合はautoになっていることからも、NaN0に置き換えられていることがわかります。

おわりに

infinityが絡む計算について、z-indexプロパティを用いて検証および調査を行いました。基本的にCSSの数学関数は、IEEE-754と呼ばれる規格に基づいたもののようで、この辺に明るい方は理解しやすいかもしれません。

実際にCSSでinfinityを使うユースケースは少ないかもしれませんが、calc()関数を使う際には、infinityが絡む計算についても理解しておくと、想定外の挙動を避けることができるかと思います。本記事の内容が少しでもお役に立てれば幸いです。

参考

https://www.w3.org/TR/css-values-4/#calc-error-constants
https://developer.mozilla.org/en-US/docs/Web/CSS/calc-constant

Discussion

nanto_vinanto_vi

z-indexプロパティだと値が整数値に丸められるため、小数値を扱えるプロパティ(例えばline-height)を使ったほうが計算結果を確認しやすいです。

const div = document.createElement('div');
div.style.lineHeight = 'calc(1 / 0)';
console.log(div.style.lineHeight); // calc(infinity)
div.style.lineHeight = 'calc(0 / 0)';
console.log(div.style.lineHeight); // calc(NaN)