Da Vinci Studio Blog

株式会社 Da Vinci Studio は 2023 年 7 月に株式会社 Zaim と統合し、株式会社くふう AI スタジオになりました

【CSSおじさん】CSS設計についての簡単な解説

どうも、Da Vinci Studio(以下DVS)サーバー部としては異端のCSSを愛するおじさんこと千代谷です。

ちょっと前書きが長いのですが、今回は愛するCSSにおける「CSS設計についての概要とDVSがお手伝いしているプロジェクトがどんなCSS設計で作っているのかを一緒に眺めよう!」という趣旨で記事を書こうと思っていました。

ええ、思って「いました」。 何故過去形なのかというと、いざ書いてみると「CSS設計についての概要」とかいう部分で結構な量があったため、泣く泣く分割することになりました…。 そう、つまり今回は「CSSおじさんのCSS設計を解説する回」ですね。 その上、内容が内容のためCSSをある程度書けることが前提になってしまっていますが…まぁCSS設計を読みたい人はそこら辺は大丈夫だと思うので今回は特に気にしない方針とします。

また、さすがにおじさんだけの知識では設計部分の概要を解説するのは難しいため、半田惇志氏の著書「CSS設計完全ガイド」を参考にしています。 今回の内容をさらに詳しく深堀って解説しているので興味がある方は少々お値段はしますが是非一読することをおススメします。

CSS設計って何なんだ…?

前提としてCSSには問題点がある

さてさて、CSS設計とはいったい何なのか。 そのまま読んで字のごとく「CSSを設計すること」ではあるのだが、どうしてそんな必要があるのか。 これは当然の疑問ではありますが、すごく端的に言うと「CSSには問題点があるから」です。

CSSの汚染(カオス化)

1つ目の問題点として、CSSは汚染(カオス化)が容易に起こりえる、ということがあります。 CSSはすべてがグローバルスコープであるため「すべてのスタイリングが干渉し合う可能性がある」という最大の特徴にして最大の短所があります。

少ないページ数のWebサイトであればあまり問題にはならないかもしれないですが、これが100や1000ページ単位のWebサイトになってくると、それらすべてに干渉しないようにCSSを書いていくのはかなり大変です。 トップページのボタンは緑色にしているはずなのに、後から追加した下層ページのボタンの色で上書きされてしまった…という事態が発生するのはかなりストレスですし、頻発するようであれば開発コストも高くなってしまいます。

このため、作成時には意図していない上書きや変更が加えられ、それを解消するためにリファクタリングをしないといけない…という状態を汚染状態と自分は表現しています。

複雑化するWeb開発

もう1つの大きな問題点として、Web開発の複雑化が挙げられます。 CSSは静的なファイルのため基本的にWeb上では変更が不可能です。

しかし、Javascriptによる頻繁な「状態」の変更が起きます。アニメーションや操作による表示の切り替えなどに対応するにはそれぞれ特有のスタイルを追加していかなくてはいけません。 この量が増えてくると、想定外のスタイルの衝突を引き起こし結果として汚染を誘発します。最終的には新しいスタイルを1つ追加するのにもすべてのCSSで問題がないかを考えなくてはいけなくなります。

そう、昨今のWeb開発においてCSSは壊れやす過ぎます。

解決するために生まれたのがCSS設計

上記のように問題点があるにも関わらず、CSSはバージョンを上げても追加するのはスタイルのアップデートだけ…スコープの分離などで汚染の影響を減らせるアップデートは現在策定中のCSS4ですらありません。

では、どうするか?

これを解決するのがCSS設計という考え方です。 いくつか設計手法はありますが、どの手法にも共通する役割は

  • 分離

という点でしょう。 これはそれぞれの設計手法によって「ファイル」「パーツ」「役割の名前」で分けるという考え方が一番しっくり来るかと思います。

CSS設計が目指すゴール

さてさて、そんな汚染を解消するためのCSS設計ですが、最終的にはどんなCSSを目指すべきなのでしょうか。 結論から言ってしまえば、こちらでPhilip Walton氏が提唱した以下の4点を十全に満たすことができたらそれはよいCSSになっていると言っても過言ではないでしょう。

  • 予測できる
    • 「影響範囲が予測できる」「スタイルが期待通りに振る舞う」
  • 再利用できる
    • 「既存パーツを別の場所でも使うことができる」
  • 保守できる
    • 「新しいスタイルを追加・更新した時に既存のスタイルをリファクタリングしなくてもよい」
  • 拡張できる
    • 「1人でもチームでもCSSが問題なく管理できる」

この中でも特に「拡張できる」かどうかは、Webサイトの規模が大きくなってきたりすると自然と携わる人も増えてくるので、もしCSS設計を取り入れるなら早い段階から意識しておいた方がよい部分です。

では、上記を加味した上でメジャーな設計手法について少し触れて行ってみましょう。

メジャーなCSS設計手法

今回紹介するCSSの設計手法はOOCSS, SMACSS, BEMの3つですが、これら3種類以外にもMCSS, SUIT CSSなどの設計手法が開発され使用されています。また、中には日本人が設計したFLOCSSやPRECSSなど設計手法もありその種類は思った以上に多岐に渡ります。

ではどれを使うのが一番いいのだろうか? これに関しては明確な答えは出せないと思っています。なぜならWeb開発の規模やその性質(アプリなのかECなのか、コーポレートページなのかなど)によって選択する設計手法は変わると自分は考えています。

とは言え、どの手法も以下の特性を1つ以上は内包しています。案件毎に適切な設計を選んでいければベストですね(自分でも難しいですが…)

  • 要素に応じてCSSを分類分けする(header, footerなどの役割や特性毎に分類されている)
  • HTMLの要素がスタイルに絡まない
  • 各スタイルの影響範囲が限定的
  • 各スタイルの依存度が低い(#mainに依存していないなど。ネストすると依存度が上がる)
  • 詳細度が高くない
  • class名から影響範囲が想像できる
  • class名から見た目、機能、役割が想像できる
  • 拡張しやすい

これを踏まえた上で今回はOOCSS, SMACSS, BEMの3種類の設計手法を見ていきましょう。

OOCSS

OOCSSの基本 特徴:おもちゃのブロックのように自由に組み合わせが可能なモジュールの集まりを作ろう

OOCSSは上記画像のように「構造」と「見た目」で分けるCSS設計です。 画像のボタンAを作るときには

  • 構造情報
    • width(横幅)
    • height(縦幅)
    • padding(コンテンツの内部余白)
    • margin(コンテンツの外部余白)
  • 見た目情報
    • color(色)
    • font(文字)
    • background(背景)
    • box-shadow(影)

の2つの情報の組み合わせで作られるためclassも2つ合わせています。 また、これらのスタイルは自由に組み合わせられる再利用性を担保するためコンテナ部分とコンテンツ部分は明確に分離させる必要があります。 (#main .btnのようにネストしてしまうと特徴である自由に組み合わせることができなくなってしまうのでなるべくパーツ毎の区分けでclassを作っていくのがポイントです)

OOCSSは全てのCSS設計の基礎になったといっても過言ではない、設計手法です。 そのため、存在しているルールも簡素なものしかないためこちらの設計手法を実開発案件で採用するのは現実的ではない可能性が高いです。 とは言え、その考え方は他の設計手法の基礎になっている部分もあるため気が向いたら要点は押さえておくと幸せになれます。

SMACSS

SMACSSの基本 特徴:スタイル群を5つのカテゴリに分類しよう

SMACSSはCSSを役割に応じて以下の5つのカテゴリに分類分けしているCSS設計です。 ※( )の中はおじさんがその分類に定義できると考えている属性種別です

  • ベース(HTML)
  • レイアウト(id, class)
  • モジュール(class)
  • ステート(class)
  • テーマ(id, class)

役割に応じているため実はCSSの分割がしやすく、役割ごとにCSSを分割して管理をしたい場合などにはとても重宝します。 また後述のBEMと違ってclass名の命名ルールも緩く、とりあえず導入してみたいという場合には結構おススメできます。

次はそれぞれの役割を簡単に見ていきましょう。

ベース

ベースでは標準のスタイルを定義しています。 主に以下のようなHTMLに依存するような要素をここに分類します。

  • body
  • a > img
  • a:hover

またリセットCSSなどもベースのルールとしてここに含みます。

レイアウト

レイアウトではヘッダーやメインエリア、サイドバー、フッターなどのWebの大枠を構成する要素を定義します。 これらの要素は基本的には1つのページ内で1回しか利用されないことが多いため例外的にidセレクタの利用も許容されています(とは言え、基本はclassで作る方が取り回しがしやすくて便利ではあります)

モジュール

モジュールはレイアウトの中に配置される要素が定義されます。 「ボタン」「見出し」「ナビゲーション」などがここに分類されます。

おじさん所感ですが、SMACSSで作る場合はこのモジュールがもっとも肥大化します。 そのため、他の分類と比べて汚染の可能性が高いです。

ステート

ステートは状態変化に関する要素を定義します。 エラー時のカラー変化やアクティブ時の要素の変化などのCSSが分類されます。

注意点としては、影響範囲の広いclass名にすると後々汚染の原因になってきますので要注意です。 (is-activeとかすると後々アクティブ要素が増えた時とかに別名にせざるを得ないため、それなら最初から is-active-〇〇とかのようにしたほうがよい)

昨今だと一番モジュールの次に使用用途が多い分類かもしれないですね。

テーマ

テーマはWebサイト全体の配色(メインカラー)などサイトイメージを扱う要素を定義します。 例えばbodyにテーマclassを付けるとサイト全体の色が変わる、などの時に使用されます。

上記4つで設定されたあらゆる要素が上書きの対象となりますが、最近はあまり見なくなっているのでここに当てはまるケースも少なくなってきているかもしれません。 ダークモードとライトモードの切り替えなどがここでできると素敵ですね。

BEM

BEMの基本 特徴:厳格で強力なルールを元に汚染を最小限にしよう

こちらはCSS設計手法ではかなり有名ではないでしょうか? 上記の2つの手法とは異なり、BEMはかなり独自のルールがあり、その特性を3つ挙げるなら

  • class名から要素をとても想像しやすい
  • class名がとても長くなる
  • ほぼすべてがシングルクラス(.block .item{}のようにネストしないclass名の付け方)

と自分は考えます。 とは言え、それはおじさんが見た印象に強い部分であって、BEM自体の特徴はとても厳格なルールが定められていることです。これにより汚染を防いでいるとも言えます。

また、あまりにも厳格なルールのため、残念ながらこの記事内だけで簡潔に説明しきることは無理です。なのでここではかいつまんで説明していきます。

BEMの基本はすべてのモジュールを「Block」「Element」「Modifier」という3つに分類します。 それぞれ少しだけ詳しく見てみましょう。

Block

Blockのイメージ Blockはとても簡単に言うと「どこでも使いまわせるパーツ」のことです。 このどこでも使いまわせるようにするためにpaddingやmarginなどの余白やpositionなどの位置をここで指定してはいけないという縛りがあります。

Element

Elementのイメージ Elementは「Blockを構成し、Blockの外では独立して使用できないもの」、もう少し簡単に言うと「Blockのオプション要素」とも言えます。 また、ルールとしてどのBlockに所属しているオプション要素なのかを明確にするためにBlockのclass名を継承して命名します。 とは言え、画像のようにそこまでBlockと大きな役割の差はありませんのでElementを使うかBlockを使うかはその時々で合う方を選択する形でもよいと思います。 (次のModifierまで絡むとclass名がすごく長くなるので…)

Modifier

Modifierのイメージ Modifierは「BlockもしくはElementの見た目や状態、振る舞いを定義するもの」とされています。 また、これもElenemtと同じく、あくまでBlockやElementの補完なのでなくてもよいものです。 しかし、画像のように状態変更が起こる場合などではElementではなくこちらで定義していく方が汚染のリスクが低いです。 こちらもElementと同じくBlock, Elementのclass名を継承します。

Mix

Mixのイメージ おっと、こいつはなんなんだ?と思うかもしれません。確かにこれを加えるとBEMではなくBEMMとかにしないとおかしくなりますからね。ですのでこのMixはカテゴリというより考え方やテクニックに近いものだと考えてください。 先ほどBlockの説明で「どこでも使いまわせるようにするためにpaddingやmarginなどの余白やpositionなどの位置をここで指定してはいけない」と書きましたが、Web開発の場合で余白や位置調整が必要なシーンは多々あります。そのため、それら余白などの情報を補助する目的でこのMixという考え方が多く使われます。 Mixは画像の通り「1つのDOMに複数のBEMclassが付与されている」形のことを指します。 この形にすることでメインで使用しているBlockのclassのmarginやpaddingを設定を分けることができ、再利用性を担保したままより自由なコンテンツの組み合わせを実現することが可能となっています。

BEMは、ルールの厳格さやカバー範囲の広さなどで初回で導入するにはハードルが高いと言えます。 しかしながら、しっかりとルールを守って導入できた場合は汚染しにくさ、高い保守性などリターンもすごく大きいためカッチリとしたルールで長く使うサイトを開発したい、という場合には是非公式ドキュメントを読んでみて導入を検討してみてください。

今回の〆

さて、ここまでCSS設計のおおまかな概要と主な設計手法について触れてきましたが、どうだったでしょうか。 この時点でこの文量なのでここにさらにDVSが関わっているサイトのCSS設計紹介を加えるとちょっと気軽には読めなくなってしまうのではないでしょうか。

なので次回のCSSおじさんの回では、今回の内容を元に各Webサービスがどんな設計手法をとっているのかを見ていきたいと思います。

また、もし今回の記事でCSSに興味が出た方はDa Vinci Studioでおじさんと一緒に働く仲間を絶賛募集中です。 興味のある方は こちらrecruit@da-vinci-studio.net までご連絡ください。 是非おじさんとCSSについて語り合いましょう!

それでは、またの機会に。