CSS in JSとは
CSS in JSとは
JavaScriptを用いてCSSを記述するアプローチ。
CSSはコンポーネントに定義され、外部のCSSファイルに依存することなく、コンポーネント単体で独立する。
下記の例はstyled-componentでのstyling。
(引用元:https://styled-components.com)
const Button = styled.a`
display: inline-block;
border-radius: 3px;
padding: 0.5rem 0;
margin: 0.5rem 1rem;
width: 11rem;
background: transparent;
color: white;
border: 2px solid white;
${props => props.primary && css`
background: white;
color: black;
`}
`
render(
<div>
<Button
href="https://github.com/styled-components/styled-components"
target="_blank"
rel="noopener"
primary
>
GitHub
</Button>
<Button as={Link} href="/docs">
Documentation
</Button>
</div>
)
結果が以下のbutton。
代表的な CSS in JS
CSS in JSの何が良いのか
CSS in JSのメリットとされる代表的なものを挙げていく。
- カプセル化
- メンテナンス性
グローバルなCSSを利用している場合、CSSの定義を変更した際にどこへ影響があるか分かりづらいので、セレクト階層や命名規則などCSS設計にてこれに対応する必要がある。
CSS in JSでは、影響がコンポーネントに閉じられるため、細かいCSS設計が不要になる。
- 動的スタイリング
-
ライブラリが提供する各種便利機能
- 自動でベンダープリフィックスを挿入
- Sassのようなネストセレクターも可能
ランタイムにCSSが生成される為、JavaScriptのpropsを利用した動的なスタイリングなど、JavaScriptでの複雑なロジックをもとにstylingが可能になる。
また、ライブラリが提供する便利機能が使えるのでDXが向上する。(これは学習コストも伴うが)
- CSSの静的解析
CSS、Sassでは、クラス名を間違っていたとしても実行するまで気づくことができない。また、未使用のスタイルを静的解析により検出することができない。
CSS in JSは、ESLintやTypeScriptコンパイラといったJavaScript向けの静的解析ツールにより、未使用のCSSを簡単に検出することができるため、バグの発見、修正が楽になる。
- 移植性
スタイルとコンポーネントが同じファイルにあることで、そのコンポーネントを他のプロジェクトで使用することが容易になる。
CSS in JSの何が良くないのか
以下、CSS in JSのデメリットの代表的なものをあげるが、パフォーマンスが一番大きな点になるので、セクションを別に説明する。
-
可読性が悪い
- どれが styled-components かわからなくなる問題
- クラス名が読めない
例:
<li href="/blog/ecl19xgcapo" class="sc-iqseJM jtAoBP">...</li>
- 学習コスト(ライブラリによる)
CSS in JSの記法が独特で、それぞれのライブラリによって記述方法が異なるため、学習コストはある。
パフォーマンス
従来のCSSでは、ウェブページを読み込むと、ブラウザはCSSを読み込んで適用するだけなのでサイトへの負荷が少ない。
一方、CSS in JSでは、JavaScriptで定義されたCSSを解析し、CSSにマッピングされたJSX要素を作成する。
ブラウザはCSSスタイルタグを動的に生成し、それを読み取ってウェブページに適用する。この読み込みと生成にパフォーマンス上の時間がかかる。(二重解析)
- 一度はライブラリによって解析
- 次にスタイルが挿入されるときにブラウザによって解析
サイトの負荷パフォーマンスを気にするならば、ランタイムCSS-in-JSは最適解ではない。
ゼロランタイム CSS in JS
上記の、二重解析によるパフォーマンス時間の損失を改善するための解決策となるのが”ゼロランタイム"。
"ゼロランタイム"とは、CSS-in-JSの構文でスタイルを作成するが、生成されるのは他のCSSプリプロセッサが生成するような.cssファイルであるCSS in JSのこと。
ビルド時にCSS in JSのコードからCSSを抽出し、ブラウザがこれらのスタイルを読み込んでウェブページに適用するので、最終的にスタイルタグを生成する際に通常浪費されるランタイムが節約される。
パフォーマンスが重要な、規模が大きいプロジェクトや複雑なプロジェクトで特に有用である。
コンポーネントがレンダリングされる際に発生する、初期スタイルのinjectionのパフォーマンスの比較
(画像元:https://stitches.dev/docs/benchmarks)
代表的なゼロランタイムCSS in JS
- Linaria
- vanilla-extract
- Stitches(一部ランタイム)
まとめ
(画像元:https://2021.stateofcss.com/en-US/technologies/css-in-js)
The State of CSS 2021: CSS-in-JSでもstyled-componentsがusageでトップをとるなど、現在のCSSで広い使用率を占めているCSS in JS。
パフォーマンスのデメリットを改善した、ゼロランタイムのCSS in JSの台頭など今後も要注目である。
参考資料
- CSS in JSとは何か
- Comparing the top zero-runtime CSS-in-JS libraries - LogRocket Blog
- The Unseen Performance Costs of Modern CSS-in-JS Libraries | CSS-Tricks - CSS-Tricks
This article is also available in English: https://dev.to/takuyakikuchi/what-is-css-in-js-bdg
Discussion