今さらながらCSS設計について学んだので自分なりにまとめてみました。
内容としてはどうしてCSS設計が必要になったのか、それを踏まえてどんなCSS設計が考えられたのか過去から今の流れを書いています。
CSSとは何か
HTMLで文章を作成したとしても、見出しやカラーなどの表示がなければ読みにくいですし、ユーザーは飽きてしまいます。
そうならないためにも装飾を使って、オリジナルなサイトを作成するためにCSSが使われています。
そもそもCSSは必要なのか?
CSSが普及される前までは、WEBページの背景や文字の色などデザインもHTMLで行なっていました。
しかし、HTMLは情報構造を定義するもので、デザインを定義すると言う使い方は間違っています。
そこでCSSが注目され、情報構造とデザインを切り離して記述できるようにするために必要になりました。
CSSのデメリットとは何?
CSSのデメリットとしてあげられるのは、2点あります。
- WEBページの表示が崩れる原因になる
- サイトデザインの属人化に繋がる
1.WEBページの表示が崩れる原因になる
CSSで定義しブラウザに表示されます。そのブラウザ自身がCSSの進化に追いついていない場合は、意図したデザインと異なった表示結果になってしまいます。
CSSで新しい技術を使用する際は、各ブラウザが対応しているのか必ずチェックする必要があります。
こちらのサイトで各ブラウザの対応状況について調べることができます。
https://caniuse.com/
2.サイトデザインの属人化に繋がる
CSSは比較的扱いやすい言語です。
メリットでもありますが、デメリットでもあります。誰にでも扱えると言うことは何も考えず記述をしていくと作成した人だけしか把握できないCSS構造になってしまうことが多々あるからです。
このCSS何のために記述されているのか、またどのHTMLから呼びさられているのか分からない状態では保守性にかけます。
事業が大きくなればなるほど、触れる人間が触れるためCSSの保守性も視野に入れてコーディングする必要があります。
CSS設計が生まれた背景
なぜCSS設計が生まれたのか自分の中では大きく2点あると思っています。
- CSSの特徴はグローバルでありカスケードであること。
サイトに携わる人たちが、好きなように書いているとグローバルでありカスケードであることが原因で、CSSでの上書き合戦が始まったりいつの間にか変更した点とは違う部分に影響が出てしまい破綻(炎上)することも多々ありる
2.サイトを携わる人が増えかつ、ルールが設けられていないこと。
サイトに携わる人間が増え、何も考えず記述していると同じようなコードが複数存在していたり、使用していないコードがあったりすると、とても見辛く保守がしにくくなる。
これら2点の問題を解決するためにCSS設計が必要と考えられました。
CSS設計とは
CSS設計とは先ほどの問題を解決するためのCSSの記述ルールです。
そして良いCSSにすることができます。良いCSSよく知られているのは以下の4つです。
・予測しやすい
・再利用しやすい
・保守しやすい
・拡張しやすい
予測しやすい
これは文字通りでそのクラスがどのような挙動をするのか予測しやすいことです。
再利用しやすい
運営をしていると似たようなコードを書く必要があります。その際に同じようなコードを作成するのではなくコンポーネント管理をしてコードの記述を最低限にしようということ。
保守しやすい
こちらも運営をしていると新しいコードを書かなくてはならないことがあります。
その時にコードの記入や修正が容易にできるような状態を作っておくということ
拡張しやすい
すでに存在するコードをさらに拡張したい時に誰でも容易に管理ができる状態を維持すること。
これは上記3つができていないと難しいかなと思います。
以上がCSS設計の考え方になり様々な設計方法が考えられています。
順に紹介していきます。
OOCSS
OOCSSとはObject Oriented CSSの略で、オブジェクト指向のCSSと呼ばれています。
この考え方はこれから紹介するSMACSSなど基礎とされています。
OOCSSの考え方は大きく2点あります
- 入れ物とコンテンツ中身を切り分ける
- 構造と見た目を切り分ける
入れ物とコンテンツ中身を切り分ける
従来は複数のページに同じようなスタイルが存在していても別々としてコードを作成されていました。
しかしそれではページが増えるごとにコードが増えていくのでどこでも使用できる汎用的なパーツを作るという考えです。
そうなることで場所の依存も避けられます。
構造と見た目を切り分ける
また同じボタンだけど色が違うと言った場合に、形は.btnに記述し、.btn-blueや.btn-redのようなクラスにbackground-colorを記述する考えです。
例:<div class=“btn btn-red”>
.btn{
width:200px;
height:50px;
}
.btn-red{
background-color:red;
}
この設計方法で、コード量が削減されますし、別の場所でも.btn-redを使用すれば背景を赤色に変えられ汎用的にすることができます。
しかし、仮にクラスを改修しようとすれば影響はかなり大きいですし、共通化することでどこにどのスタイルが当たるのかCSSの見通しが悪くなります。さらにマルチクラスのためHTMLのコードも見づらくなるなと感じました。
SMACSS
SMACSSはOOCSSを基礎として作られたcss設計手法です。
OOCSSは共有パーツをどんどん追加することで見通しが悪くなることがありましたが、SMACSSはそれが改善されています。
SMACSSは、5つのカテゴリに分けられ目的が分けられているためメンテナンスが高いです。
CSSの役割5つに分けられる
- ベース
- レイアウト
- モジュール
- ステート(状態)
- テーマ
ベース
全ての基盤となる部分です。
要素セレクタや属性セレクタ、擬似セレクタなどが対象になります。
reset.cssなどもここに含まれる。
レイアウト
レイアウトとはページ内のセクションやエリアなどが対象になります。
例えばsidemenuやmainやgridなど大きな枠組みが対象です。
クラス名の付け方は、l-sidemenu, l-main, l-grid
もしくはlayut-sidemenu, layut-main, layut-grid
です。
モジュール
モジュールはボタンやフォームなど部品が対象になります。
モジュールにはl-
などの規則はありませんし、クラスをつける必要はありません。
h1などの要素に対してスタイルを当てることも可能です
ただし要素に対し当ててしまうと目的がわかりづらくなるので、クラスを利用するのがいいでしょう。
ステート
モジュールやレイアウトの状態が対象になります。
javaScriptなどで、tabを選択している状態やアコーディオンを開いてる状態などに使われます。
クラスの付け方は.is-active, is-error
です。
テーマ
テーマは必須で使われるものではないですが、サイト全体のトーン統一などに使用されます。
例えば色やフォントなどが対象です。
場合によってはtheme-
をつけます。
簡潔にまとめましたが、こちらの記事が詳しく書かれていますので興味があればご覧ください
このようにOOCSSではどこにどのスタイルが当たっているのかわかりづらかったですが、テーマごとに命名規則も加えることでどこが役割を持っていてどのファイルを改修すればいいのか見通しがよくなります。(メンテナンスと予測)
またテーマごとに分けていることから、CSSの再利用性も高まると思います。
一方で、HTMLに依存しすぎているサイトではなかなか生かしづらく、途中からSMACSSに変えたりSMACSSから乗り換えようと思うととても難しいかなと感じます。
また、決まりがしっかりと決められている分、導入する際の学習コストも高いですし、理解をしていないと簡単に破綻する可能性があるのは大変です。
BEM
BEMはOOCSSやSMACSSと考え方が違います。
OOCSSやSMACSSはディレクトリ構造で分けましたが、BEMの場合は命名規則でCSS設計を行います。
CSS設計として利用率も一番高いです。
BEMは、Block, Element, Modiferの頭文字をとっており、Block__Element—Modiferと独特なクラス名を使用します。
このクラス名のおかげでサイト構造が大体わかるのでとても良いと思っています。
Block
ブロックはナビゲーションやヘッダー、フッター など大きなセクションが対象です。
例えばヘッダーメニューの全体がBlockです。
Element
エレメントはブロックの中身です。
ヘッダーメニューの1つ1つの要素です。
`
- HOME
- ACCESS
- CONTACT
Modifer
Modiferは、その要素の状態が対象になります。
SMACSSでいうステートと一緒だと思ってもらっていいと思います。
このようにBlock, Element, Modifeの命名規則のみでCSS設計を行うため非常にわかりやすいです。
学習コストも低く理解しやすいため、複数人で作業を行っても破綻がしにくいと感じました。
またBlockのクラス名で役割がわかるためサイト内の構造がわかりやすいのもメリットだと思います。
一方でBEMの命名規則は冗長になりやすく、汎用的なクラス名をつけようとするとかなり難しいです。
また汎用的を意識しすぎると、他のBlockと被ってしまうと意味がないので意識しないといけないのでネックです。
OOCSSやSMACSSは前時代?
今回はOOCSSとSMACSS、BEMについてお話しましたが、これ以外にもあります。
しかしOOCSSやSMACSSなどの役割で分ける方法は前時代の話だと感じています。
なぜかというと今までお話したCSS設計はグローバルでありカスケーティングが問題でそれをコンポーネント単位で解決しようとしていたのがOOCSSやSMACSSだからです。
今やReactやVueのようなコンポーネントを前提としたものが利用され、CSS ModuleのようなCSSの影響範囲をコンポーネント単位に閉じ込めてることが当たり前となっている以上OOCSSやSMACSSを利用する必要はないと思いました。(コンポーネント設計前提です)
自分が考える現代の解決方法はCSS in JSやCSS Module、scoped CSS(Vue.js)、BEMかなと考えています。
ここからは自分がVue.jsを利用しているので、scoped CSSとCSS Moduleについて話します。(Vue CLI利用前提)
なおscopedCSSとCSS Moduleに対して詳しい話はしません。こちらの方がわかりやすくまとめてくださっているので参照ください。https://qiita.com/mascii/items/3202b9e18fd4a7366ac1
scoped CSS
.vueファイルのstyleタグにscopedを追加することで利用することができます。
Scoped CSSの大きなメリット
- 手軽に導入できる
- 普段通りのコーディングを行える
自分がとてもいいなと思ったのは、デザイナーである僕でも普通に利用ができることです。
会社の体制によってはデザイナーがコーディングをする場合でも普段と同じコーディング方法で問題がないので気軽に導入できる点は最大のメリットだと思います。
ただし、scopedCSSを利用することで衝突が完全に防げたわけではありません。
子コンポーネントのルート要素に対しては、親のデータ属性がついてしまうためクラス名が同じだと衝突が起きてしまいますし、グローバルに定義されたセレクタが適用されるのでクラス名にルールを設ける必要はあります。
CSS Module
.vueファイルのstyleタグにmoduleを追加することで利用することができます。
CSS Moduleの大きなメリット
- BEMのような命名規則が不要
- クラスの衝突がない
CSS Moduleはコンポーネント名とランダムな記号を追加してくれます。
デメリットとしては、HTMLの記述が少し書きづらいことです。
<div :class=“$style.title”>
のようにクラスを付与するタグ全てに$styleをつけないといけないのめんどくさい・・・。
ただしCSSの記述は今まで通りなので学習コストは低いと思います。
まとめ
Vue CLIで利用するのであれば、CSS Moduleが良いと思います。
子コンポーネントのルート要素に親のデータ属性がついてしまうのは気持ち悪いですし、それに伴ってクラス名を気にする必要があるのであれば、CSS Moduleを使えばいいと思います。
個人的にCSSの問題点をうまく解決しているのはCSS Moduleだと思っています。
ただし、BEMのような考え方がすでにチームに根付いているのであれば、CSS Moduleも使う必要もないと思います。
BEMのような命名規則で解決できのであれば一番いいかなと思います。
その理由としては、今後フレームワークを変えたりした場合に汎用性が高いと思っているからです。CSS Moduleやscoped CSSが使えるかなんてわからなけど、BEMの考え方はHTMLとCSSが存在し続ける限り使える設計方法だと思います。
長期的な運営を考えるのであればBEMをオススメしたい。
しかし、BEMを全員に理解してもらうのが難しかったり、BEMで課題を解決できないフェーズなのであれば違うCSS設計の導入を考えるべきだと思っています。