CSSだけでスクリーンサイズやフォントサイズを取得、CSSの三角関数tan(atan2())はcalc()ではできない計算もできる
Post on:2023年10月24日
CSSで便利な機能の1つがcalc()
、ページのレイアウト、要素やフォントのサイズ設定に活躍します。特に異なる単位で加算減算(calc(1rem + 1px)
)できることが便利ですが、乗算除算(calc(1rem / 1px)
はできません。
そこでCSSの三角関数です。すべてのブラウザにサポートされているatan2()
を使用すれば、異なる単位で計算ができます。tan(atan2())
を使用して、スクリーンサイズやフォントサイズを取得するテクニックを紹介します。
CSS Type Casting to Numeric: tan(atan2()) Scalars
br Jane Ori (@Jane0ri)
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
現在のブラウザに実装されているCSSでは、<length>
型を除算することはできません。たとえば、calc(100vw / 5px)
は機能しません。しかし、仕様には記載されているので、いずれは機能するようになるでしょう。
現在のところ、単位が混合している場合に除算などで数値を生成する方法はありません。ただし、技術的にはatan2()
という例外が1つあります。
atan2()
は、2つのカンマ区切りの値の逆正接を返す三角関数です。2つの値(実質的にはスロープ、駆け上がる、yをxで割った値、atan2(height, width)
)を受け取り、スロープの下から上への角度を返します。
以下、ファイトクラブのガソリンと冷凍オレンジジュース風に。
じゃぁ、知ってるか?
tan(atan2(height, width))
は2つの次元間の数値<number>
だ。
いや、知らなかった。本当に?
ああ。単純な三角関数を使用して、あらゆる種類の次元をスケールできる。
そうなの?
本気になればな。
tan()
をはじめ、CSSの三角関数について詳しくは、下記をご覧ください。
tan(atan2())は単なる数値である
きれいなグラフ、マップ、幾何学アートなど、通常のトリガーに飛び込む必要はありません。
基本的に、tan(atan2())
は2次元間の単なる数値です。
この記事では、数値に型キャストする手段としてのアイデンティティスケールに焦点を当てますが、これを使用して任意の2つの次元を比較する方法はたくさんあります。
CSSでスクリーンサイズを取得
多くの人が望むことの1つは、スクリーンのアスペクト比を見つけたり、ビューポートのピクセル幅(または高さ)を数値で取得することでしょう。
私は先日The CPU Hack(翻訳記事)を使用したバイナリ検索で100%のCSSでスクリーンサイズを取得しましたが、tan(atan2())
を使用した方がずっと簡単で速いことに気がつきました。
100vw
のピクセル値はいくつ?
と同じくらい簡単なはずです。
1 2 3 |
:root { --px-width: tan(atan2(100vw, 1px)); } |
しかし、atan2
は現在ブラウザで非常にバグが多いです(vwとpxを混ぜて機能することを意図しています)。
この場合、Chromeは100
を返しますが、望ましいことではありません。
Firefoxは単位が混合されていると失敗するため、0
を返します。両方がvw
あるいはpx
の場合であれば、正しく100
を返します。
Safariは任意のY
および任意のX
に対してtan(atan2(Y, X))
から常に0
を返します(calc()でラップしない限り)。
したがって現在のところ、最初にNNNpx
として100vw
が必要になります。これはCSSでは簡単なことで、カスタムプロパティに設定し、--100vw: 100vw
のような値にすれば自動的に行われます。
1 2 3 4 5 |
@property --100vw { syntax: "<length>"; initial-value: 0px; inherits: false; } |
これでChromeも期待どおりに動作します。
1 2 3 4 |
:root { --100vw: 100vw; --px-width: tan(atan2(var(--100vw), 1px)); } |
--px-width
はスクリーンの幅で、通常は整数です。
実際の動作はデモページでご覧ください。
幅だけでなく、100vh
で高さも取得しています。
See the Pen
CSS-Only, super easy screensize numeric pixel value width/height vars by coliss (@coliss)
on CodePen.
CSSでフォントサイズとかも取得
同じアイデアで、コンテナのクエリ単位、混合単位を含むサイズ計算、rem
のpx
サイズなどに使用できます。長さを登録し、その値を設定し、tan(atan2())
で数値をpx
に変換するだけです。
See the Pen
CSS-Only: get numeric px value of current font-size by coliss (@coliss)
on CodePen.
Easy peasy! とっても簡単ですね、超便利になる可能性があります。
<time>
でも機能します。
1 2 3 4 5 6 |
:root::after { --ms: tan(atan2(12s + 1ms, 1ms)); counter-reset: val var(--ms); content: "Numeric ms value of 12s + 1ms is: " counter(val); /* counter prints 12001 */ } |
これはすべて、数値型キャストのID数値であり、計算を組み合わせるさまざまな方法を考えるのは楽しいですが、tan(atan2())
にはさらに素晴らしい機能があります(それは未来の記事で)。
追記: 三角関数を学び直す必要があるか
tan()
を使用するために三角関数を知っている必要はありませんが、プライベートでいくつか質問がありました。
tan( angle )
は角度を取得し、「隣接する角度に対向する角度」つまり高さを直角三角形の幅で割った値に等しい結果を生成する関数です。
参考: Wikipedia
atan( ratio )
は高さを幅で割った値を角度で返す関数で、tan()
の逆関数です。
atan2( Y, X )
はatan()
をブログラミング言語に適応させたもので、高さ(Y)と幅(X)を分割する代わりに別々の引数として受け取り、atan
と同じものを返します。
つまり、この方法はほとんどの世界ではある種おろかなこと(おそらく誰もすぐに指摘しなかった理由もここにあります)です。calc()
ではまだ実行できない除算の代わりに2つの三角関数を使用しているからです。
atan2( Height, Width )
= 上図のangle
:tan( angle )
= 上図のHeight / Width
:tan( atan2( Height, Width ) )
=Height / Width
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@property --MyFullInlineSize { syntax: "<length>"; initial-value: 0px; inherits: false; } @property --MyEm { syntax: "<length>"; initial-value: 0px; inherits: false; } div.in-a-container { --MyFullInlineSize: 100cqi; --MyEm: 1em; --MyNumEmsWide: tan(atan2( var(--MyFullInlineSize), var(--MyEm) )); --MyNumPxWide: tan(atan2( var(--MyFullInlineSize), 1px )); } |
終わりに
もしこの記事が役立った、興味深いと思われる場合は、Web上で私をフォローすることを検討してみてください。
sponsors