CSSを扱いし者たちに課せられた永遠の呪縛。
「CSS簡単でしょ」と思ってる人のコードが混じる恐ろしさ。。。
2016年、全てのCSSの戦友たちに言っておきたいことがある。
今回、それらを3つのポイントに分けてお届けします。
この記事は CSS Advent Calendar 2016 の10日目の記事です。
1.本当に怖いぞ - グローバルCSS
時は200X
かつてCSSは様々なファイルに分かれておりました。
Common.css、Layout.css、Top.css、Info.css、Shop.css・・・
ページやモジュールごとにcssを分割し、必要に応じて読み込んでいた時代です。
この時代はCSSがいくらユルユルな仕様とはいえ、まだ平和でした。
つまり、読み込んだCSSファイル同士の関係さえ知っていればよいのでした。
201X 前期 (2010〜2013年ぐらい)
CSSを1ファイルにまとめて読み込みを短くするようになりました。
全てのCSSは1つにまとめられ、いよいよCSSのグローバル仕様が猛威を振るいます。
すなわち、数百、数千におよぶグローバル変数。
コード量にして数千、数万行におよぶCSSを、被らずに適用しないといけなくなりました。
CSS1行変えてあり得る影響範囲は「全ページ」。
CSSに変更加えたら本来なら全ページテストし直さないといけないのです。
しかしそんなこと現実的ではありません。
私たちにはCSS設計が必要でした。
そこで最もシンプルかつ強力だったのがBEMです。
BEMはCSSを知らぬ者に「なにあのclass命名規則キモイ」とののしられました(要出典)。
しかし一方でCSSのエキスパートたちにはBEMの素晴らしさが理解され、広まりました。
201X 中期 (2013〜2016年ぐらい)
GoogleがWeb Componentsの概念を提唱し、FacebookがReactの発表をしました。
それによりCSSもよりコンポーネント指向で作ろうという動きが強まります。
そしてOOCSSやBEMなどをベースにコンポーネントを意識して作る動きがありました。
しかしどれも根本的(CSSの仕様的)にコンポーネントとは言い難いものがありました(私の主観です)。
そんな中、颯爽と登場したのがCSS Modulesです。
CSS Modulesは、CSSの問題を解決する素晴らしいソリューションです。
BEMをベースとした全てのCSS設計を凌駕します(私の主観です)。
一旦、これでCSSの問題は解決できるようになったと思います。
とはいえ、すべてのプロジェクトでCSS Modulesが採用できるわけではありません。
多くの現場ではやはり BEM + SASS + gulp で開発しているのが現状です。
2.更なる追い打ち - コード分割
201X 後期 (2016年ぐらい)
201X前期にCSSは1つになりましたが、今度は大きいので分割しようという動きがあります。
各ページで必要なCSSを必要なだけ読み込むよう、CSSを適切な単位にファイル分割するということです。
CSS Modulesを選択する人たちにとって、この対応はあまり難しいことではありません。
CSS Modulesを使うにはWebpackが必要ですが、このコード分割もWebpackならできるからです。
しかしそうでない人たちの場合はどうでしょうか。
BEM + SASS + gulpで開発している人たちの常識はCSSを1つすることでした。
そのため、多くの場合はファイル分割できるように作られていないと思います(要出典)。
かといって全ての現場でWebpackを導入できるわけでもありません。
ならば自ら音頭をとってWebpackを導入しようとするも、とっつきにくさに挫折する人も多くいると思います(私も最初は挫折しました)。
これからはコード分割も考えて設計する必要がある、そういう現場もあると思います。
もし、CSS Modules + Webpackが採用できない現場だった場合、以下の設計を参考にしてみてください。
MOCSSであれば、Packageという形で既に分割されています。
そのためページごとに適切なサイズのCSSを吐き出せる設計になっています。
HTTP/1.1ではPackage単位でファイルをbundleし、HTTP/2に移行するときはPackageごとにファイルを出力するという対応が可能になるでしょう。
3.宿命の汚染 - スタイルの継承
ここまで、本当に怖いグローバル変数のお話をしてきました。
そしてCSS ModulesによってCSSのグローバル問題はほぼ解消されました。
そしてコード分割はCSS Modules + WebpackならWebpackで行うことができます。
もしWebpackが採用できない場合はMOCSSを参考にコード分割を前提に設計することができます。
しかし、CSS Modulesでも解決できない問題がまだ1つ残っています。
それが「スタイルの継承」です。
スタイルの継承とは、親で指定した要素が、子要素に影響するスタイルです。
一番よく使うのはこんなこんなコードでしょうか
body {
font-size: 14px;
}
CSSには、font-size
のように子要素に指定していないにも関わらず、子要素に影響を与えるスタイルがあります。
このスタイルの継承は便利である一方で、コンポーネント指向を邪魔する厄介者でもあります。
主にfont関連のスタイルが継承しますが、コンポーネントで作っていくと継承の影響を受けたくないケースも多々発生します。
この問題は、子コンポーネント側で継承の影響を受けたくないスタイルを子コンポーネントできちんとスタイル指定しておくしか術がありません。
この問題はうっかり落とし穴にハマる可能性もあるので注意しましょう、としか言えないのですが、CSS設計する場合はスタイルの継承は必ず考慮しておきましょう。
また、スタイルの継承を起こすプロパティは以下を参考にするといいでしょう。
http://www.tagindex.com/stylesheet/properties/index.html
最後に
今回の話に関連する記事を フロントエンドエンジニア Advent Calendar に投稿しました。
理解しておきたいコンポーネント指向
http://qiita.com/mki_skt/items/723dc53ad584b3457ea7
またMOCSSについて少し触れましたが、MOCSSが良いと感じたら 「いいね」 お願いします。
CSS設計 MOCSSの紹介と解説
http://qiita.com/nabepon/items/672b40647acc38dc97bb
以上です。
残り少ない2016年、よろしくお願いします!
参考
https://en.bem.info/methodology/history/#going-open-source-2010
https://github.com/gruntjs/grunt/commit/0493335ea6fe2e17cbe236b253139a06eabcbbdd
https://www.smashingmagazine.com/2012/04/a-new-front-end-methodology-bem/
https://github.com/gulpjs/gulp/commit/2357a4334051a6d1733037406ab7538255030d0b
http://www.webcomponentsshift.com/
https://facebook.github.io/react/blog/2013/06/05/why-react.html
https://speakerdeck.com/vjeux/react-css-in-js
https://github.com/css-modules/css-modules/commit/2a437a82bda687507310ec3033fabd1aeeb87e1b