初めに
最近のCSSについての学んだことをまとめます。特にReactにおけるCSSはどうすればいいのかと悩んでいたため、それについての自分の中での結論も記述できたらと思います!
CSSの世界的動向
まず、世界におけるCSSの動向を見てみましょう。2021年におけるstateofcssというサイトをみてみます。
最近の動向としては、CSS Modulesが使われていることが多く、Tailwind CSSが急激に伸びていることがわかります。
stateofcssにも出てきた、プリプロセッサとポストプロセッサについて述べます。
-
プリプロセッサー
独自の言語(メタ言語)で書かれたスタイル構文をCSS構文へと変換してくれる。
例:Sass、Less、Stylus -
ポストプロセッサー
CSS構文を便利なプラグインなどを通してより良いCSSへと変換してくれる。(自動整形やプレフィックス付与など)
例:PostCSS
以下、Reactで利用されてる主要な手法について述べます。
CSS Modules
CSS Modulesについてみます。*.module.cssにスタイルを記述し、コンポーネント内でimportし利用します。
.errorButton {
color: white;
background-color: red;
}
import styles from './Button.module.css'
const Button = () => (
<button className={styles.errorButton}>
Destroy
</button>
)
- メリット
- 直感的で分かりやすい
- コンポーネントレベルでスタイルを適用することができ、名前の衝突なども考える必要がない
- 描画のために読み込むCSSを最小限にしてくれるのでパフォーマンスも○
- Nextjsでも押している
- 利用者も多い
- デメリット
- ファイルを分ける必要がある
- いちいt命名しなくてはならない
- 廃止される可能性が高い
- 実装を行なっているのはwebpackのcss-loaderだが、サポート終了を示唆している
CSS Modulesはメンテナンス段階(修正のみ)ですが、非常に古い技術であり、非常に議論のあるところです。私たちは、すべての開発者が移行できるように、しばらくの間、これらをサポートしますが、新しい機能はありません。
なので、近い将来には、サポートが終了になる可能性があります。
CSS-in-JS
jsに直接CSSを記述できるCSS-in-JSについてみていきます。
styled-components
CSS-in-JSといったらstyled-componentsが挙げられると思います。記述としては以下のようにして記述します。
import styled from "styled-components"
export default function Home() {
//Titleはh1タグ
const Title = styled.h1`
// スタイルを記述
font-size: 1.5em;
text-align: center;
//coler属性は値が渡されれば値に応じて設定
color: ${props => props.color ? props.color : "palevioletred"};
`;
// Wrapperはsectionタグ
const Wrapper= styled.section`
// スタイル
padding: 4em;
background: papayawhip;
`;
return (
<Wrapper>
<Title color="red">Hello!</Title> {/*赤*/}
<Title color="#4169e1">World</Title> {/*青*/}
<Title>styled-components</Title> {/*ピンク*/}
</Wrapper>
);
}
- メリット
- jsファイルにそのまま記述できる
- レンダリング速度が速くなる
- スタイルとロジックを一つのファイルにまとめることができるのでコンポーネント指向に忠実
- エラーが出るため不具合にすぐ気づく
- jsファイルにそのまま記述できる
- デメリット
- コンポーネントなのかスタイルなのかすぐわからない
- 小さいスタイル割り当てもいちいち命名しないといけない
- JSXが大きくなり、可読性が下がりがち
CSSフレームワーク
コンポーネントとスタイルを提供するライブラリについて述べます
tailwind CSS
const App = () => {
return (
<div className="md:flex space-x-4 text-white">
<button className="bg-blue-400">Apply</button>
<button>Cancel</button>
</div>
)}
- メリット
- ユーティリティファーストCSSであり、CSSファイルを新たに作成しなくても良い
- インラインスタイルと違って、擬似クラス、レスポンシブにも対応できる
- jsファイルにそのまま記述できる
- 速度が速くなる
- スタイルとロジックを一つのファイルにまとめることができるのでコンポーネント指向に忠実
- PurgeCSSで使用していない不必要なクラスを消しバンドルサイズを軽量になる
- CSS Modulesにも@applyで組み合わせたり、CSS-in-JSにもtwin.macroと組み合わせることが可能
- 便利なライブラリもある
- デメリット
- 学習コストが少し高い
- 複雑なスタイルはわかりにくい
UIライブラリ
material UI
<Button variant="contained" color="success">
Success
</Button>
- メリット
- CSSを記述しなくても良い
- よく利用されるパターン(モーダル, ボタン, メニュ等)などあらかじめ用意されているので、便利
- スタイルもシンプル
- デメリット
- 書き方が独特で学習コストが高い
- 細かいカスタマイズができない
- ありきたりのデザインとなる
Chakra UI
<Button
size='md'
height='48px'
width='200px'
border='2px'
borderColor='green.500'
>
Button
</Button>
- メリット
- CSSを記述しなくても良い
- よく利用されるパターン(モーダル, ボタン, メニュ等)などあらかじめ用意されているので、便利
- スタイルもシンプル
- デメリット
- 書き方が独特で学習コストが高い
- 細かいカスタマイズができない
- ありきたりのデザインとなる
SCSS x BEM
CSS設計といったら、Sassもあげられると思います。
よくSassであげられる設計手法は、BEMがあります。この2つ組み合わせて記述することで、少し冗長な記述となりますが、名前の衝突を避けるつつ、比較的保守のあるスタイルを記述することができます。
しかし、コンポーネント指向においては、相性がよくないと考えます。コンポーネント指向を利用しない、htmlに直にスタイルを当てるのではあれば、SCSS x BEMはとても良い手法であると思います。しかし、コンポーネント指向では、各部品(小さい単位)ごとにスタイルを閉じて記述するため、名前の衝突は起きにくくなります。
なので、BEMとSCSSでは、かえって冗長な見た目となり、命名する時間、記述する量が増え、余計ない時間を要することになります。
結果、Reactにおいては、あまり利用しない方が良いと考えます。
.article-list {
width: 100%;
&__article-title {
font-size: 20px;
}
}
結局何がいいのか?
僕の見解ですが、Reactにおいてコンポーネント指向で設計する場合(Atomic designなど)であれば、UIライブライを利用(Chakra UIなど)しつつ、Tailwind CSSを利用するのが現状最適かなと考えています。
理由は以下です。
- class名などを命名をしなくて良い
- ベースをライブラリを利用しつつ、細かい調整ができる
- 一つにファイルでスタイルも記述できる
1点めのclass名を考えないくてもよいは、その名の通りです。名前を考えないため、命名規則にかかる手間や時間を省いてスタイルを当てることができます。また、cssとhtmlを結びつけるためのclass名は、コンポーネント指向においては、もはや不要かなとも考えます。1つのファイルでスタイルとタグを実装できることは、コンポーネント指向の真の姿かなとも思います。
2点目も同様にその名の通りです。TailwindCSSはユーティリティとは言っても、細かいpaddingの設定、ホバー時のスタイル、スマホなどのレスポンシブ対応などを記述することができます。
3点目は、CSSファイルを分けなくても良いため、レンダリングの速度も速く、ファイル数も減ります。コンポーネト指向に忠実になるかなと考えております。
最後に
間違っていることがあれば指摘いただければ思います。
参考