社畜系WEBエンジニアの消耗戦

社畜系WEBエンジニアの消耗戦

修羅の国でせっせと働く社畜系WEBエンジニアのブログ

モダンCSSについての知見をまとめてみる!OOCSS、BEM、ITCSS、PostCSS、CSS in JS、CSS Modules

WEBサービスを作るにあたり、実はCSS周り(マークアップもだけど)の知識が結構衰えている、また、旧石器時代の知識で止まっているという事案に遭遇しました。まぁ旧石器時代CSS知識(一応SCSSくらいは技術としては知っている)でも組めるっちゃあ組めるんですが、せっかくなので勉強していきます。

参考書籍

この記事は、WEB+DB PRESS Vol.93を参考にまとめたものです。内容は基本的に本書籍に準拠します。

WEB+DB PRESS Vol.93|技術評論社

ピュアCSSの問題点

僕が知っている旧石器時代CSSには以下の問題点があります。いや、あるようです(全然意識してなかった)。

  • 抽象化できない
  • 全てがグローバルスコープ
  • デザインの意図とマークアップの意味がミスマッチする可能性が高い

それぞれ簡単にみていきましょう。

抽象化できない

いわゆるハードコーディングを余儀なくされるということ。例えばあっちのclassもこっちのclassも同じ色だとして、それぞれbackground-color: #FFF;とか書かないといけないし、#FFFも一箇所で管理したい。確かにこれはメンテナンス性を考えるとクソだと言える。まぁ旧石器時代はこのクソをクソとして受け入れる必要があったけど、モダンCSSではもちろんそんなことはしない。

全てがグローバルスコープ

これはいわゆるレガシーコード的な、オブジェクト指向が台頭する以前に書かれていたような、関数一つ一つがクソでかかったり、そもそも関数化すらされていないような、そういうニュアンスだと捉えてもらっていい。個人的にはここにはあまり問題点は感じていないが、この問題点もモダンCSSなら(ry

デザインの意図とマークアップの意味がミスマッチする可能性が高い

デザイナーとコーダーが分かれていることによって、例えば同じ赤文字の要素でもその意図の違いが伝わらないまま同じclass当てて組むということが、往々にして有り得る。これだと後に「こっちの要素はやっぱもっと濃い赤でー」みたいな変更が入った際、思わぬバグを生み出してしまう可能性をはらんでいる。ま、僕は自分でデザインして自分で組む、かつ、基本的にはBootstrap準拠で書くからここは問題にはならないけどね!

CSSのコーディング規約

PHPならPSRがデファクトとして使われているが、調べた限りではCSS界隈ではこれ!というのはなさそう(あったら教えて)。であれば、ということではないが、IT界の神、Google様を参考にするのがいちばんよかろう。

Google HTML/CSS Style Guide まとめ - Qiita

id名、class名は意味のある名前にする

要素を特定できるような名前にする。リーダブルコード的な教えですね。.hogeみたいなclass名は論外だし、.redみたいな要素の特定が出来ないようなものもNGで、.danger的なのがベスト。

要素セレクタとid/classセレクタは併用しない

li.errorのようなのはNG。これだとHTMLが変わった時に対応できなくなる。HTMLタグを使って実装するのは控えてclassなり当てろってこと。はい、当てます。

プロパティ宣言の順序はアルファベット順

見通しが良くなるように、アルファベット順。書く側としては地味に面倒くさい。

CSSの設計指針

前述の規約等を駆使しても、なんらかのルールに則って書かないと、必ず設計は破綻してしまう。僕はすぐに破綻する。業務で取り扱うような複数人が携わるプロジェクトならなおさらだ。

OOCSS(オブジェクト指向CSS

OOCSSには、「構造と見た目の分離」、「コンテンツとコンテナの分離」の大原則がある。またBootstrap等のCSSフレームワークもこのOOCSSに基づいて実装されている。なので、用語自体は知らなくても、目にしたことはあるはずだ。

構造と見た目の分離

要素の構造、要素の見た目、それぞれのルールセットを作って管理しようというアプローチ。.buttonに構造、.button--dangerに見た目を定義し、使用する際はマルチクラスで使う。まさにBootstrapでよく見る形。

コンテンツとコンテナの分離

CSSセレクタはHTMLの構造に依存すべきではない、ということ。基本的にはCSSセレクタはHTMLのタグ直接の指定はせずに、classを付与してclass名で管理しましょうということ。これならば、仮にHTMLの構造が変わっても保守性の高いCSSになる。前述のGoogleのStyle Guideと同じかな。

BEM(Block、Element、Modifier)

Blockはその名の通り要素ブロックで、ElementはそのBlock一つ一つを構成する要素。ModifierはBlockやElementの状態といったところ。ナビゲーションバーで考えると、ナビゲーションバー全体がBlock、一つ一つのリンクがElement、アクティブになっているElementをModifierで管理、といったイメージ。これもBootstrapを見たことあれば、なんとなく掴めていると思う。これには命名規則があって、MindBEMdingという規約に従って、Block__Element--Modifierという命名で使われるのが一般的だ(※本家の命名規則は違うみたいだけど、今後未来永劫使うことはないと思うので無視)。

ITCSS(CSSの詳細度を管理)

詳細度っていうのは、「どれだけその要素を詳しく指定しているか」ってこと。

CSS Specificity Graph Generator - by Jonas Ohlsson

こちらのサイトで詳細度を計算してグラフ化してくれる。凸凹はだめで、ゆるやかな右肩上がりになっているのが理想型のようだ。

ITCSSのスタイル分割

Setting、Generic、Base、Objects、Components、Trumpの7つに分類し、徐々に詳細度が上がっていくように設計、実装するのが理想形。ただ、実際に本当にここまできっちりやる必要があるのかは個人的には疑問で、ある程度、ざっくりとした感覚値で書いていっても、さほど問題は起きないように思う。

スタイルガイド

WEBアプリで使われているUIパーツのドキュメントのこと。BootstrapのドキュメントとかPureCSSのドキュメントをイメージしてもらえばいいと思う。

スタイルガイドジェネレータ

もちろんこんなもんを一から手作業で作ってたら確実に死ねるので、ジェネレータを使って作っていくのが一般的。いくつかあるみたいだけど、Hologramってのが紹介されていたので、とりあえずこれ使っとけばいいんじゃないかな。

実際の使い方は自分のプロジェクトに導入する時に改めて説明したいと思います。

PostCSS

今、PostCSSってのがアツいらしい。いや、もうSassで手一杯なんですけど。まぁそれはいいとして、PostCSSはCSSパースしてAST(抽象構文木)を作って、プラグインでいい感じにして文字列を出力してくれるものです。

まぁプラグインで好きなのサクサク入れられるし自分好みにカスタマイズしやすいってのは確かに利用価値はあるのかもしれないけど、僕個人としてはまだSassでいいかなぁ。

カスタムプロパティ

CSSのプロパティの値を変数化できる仕組み。ピュアCSSで変数化できるのは魅力的だけど、Sassで困らない。

CSS in JS

JavascriptのオブジェクトとしてCSSを書くやり方。Reactなんかでよく見る形ですね。これって前社内勉強会でもちょっと話題にあげたことがあるんですが、この手法って高速化の面からみてどうなんだろうか。結局その時はキャッシュの面から見てもCSSCSSとして書いた方がいいんでない?って結論に至ったんだけど、、詳しい人教えて!

とは言っても、一元管理できるっていう視点で言えば、好きです。ただ、再利用性がなぁ。。

CSS Modules

CSS in JSと同じような考え方だけど、こちらはCSSCSSファイルとして書く。んでこれをReactとかから読み込む。デフォルトでローカルスコープになる。上記と比較すると、キャッシュの面からもこちらの方が利用価値が高いように思える。気のせいだろうか。

ただ一つ言えることは、CSS in JSもCSS Modulesも、ReactとかVueと併用することで利用価値を発揮するもののように思える。なので、React使ったSPAじゃなくって旧来型のSSRなんかを作るんであれば、別にSassでもいいんじゃないかなぁ。

ダンCSSを学んだ結果の僕の利用技術

結果、Sassでいいんじゃないかと思った。Laravelデフォだし。普通にSSRのWEBアプリ作る目的なので、OOCSSとかBEMあたりをしっかりしておけば問題ないかなと。確かにPostCSSとかCSS Modulesは気になる技術ではあるけれども、そこに手をだす必要性は無いのかなというのが正直な感想。

もろちん余裕があれば移行するけど、ひとまず、設計指針とStyle Guideを守ってSassで作っていきます。

CSSよりLaravelの方使いこなしたい!

ではよきモダンCSSライフを。