プログラミング

【エンジニア必読書】Web制作者(コーダー)のためのCSS設計の教科書

じょん(@fffff3434)です。

今回は「Web制作者のためのCSS設計の教科書」を読んだアウトプットを本ブログ記事にて吐き出したいと思います。

(自分を含めて)誰かが読み返したときに困らないコードを書かないように、予測しやすく、保守しやすく、再利用しやすく、拡張しやすいCSSを書くためのプロの考え方が丁寧に解説された良本でした。

CSS設計の重要性を理解していなかった

それまでは、Webサイトを作るとしても自分の勉強やポートフォリオのための個人制作が主だったので、CSS設計について深く考えることがありませんでした。

そのため、一時しのぎの自分にしか分からないような実装や、蛇足が多く、理解しやすいとは言えないコードばかり書いていたと思います。

そんな未熟な僕ですが、現在、とあるWeb系企業で「マークアップエンジニア(コーダー)」として働き始めました。目指すはフロントエンドエンジニアとしての高みです。

今後は、個人ではなく、チームでWebサイト(アプリケーション)の開発を行ったり、長期にわたる運用保守を担当することになります。

仕事のできる男になるために、どのようにすれば誰もが理解しやすく、安全なCSSが書けるのかを本書を読んで考えてみました。

CSS設計をする上での大前提

大前提として、後任者(他の開発者)はもちろん、メンテナンスする際など、数日後の自分を困らせないようなコードを書くべきです。

しかし、マウスやスクロールの動きに合わせて動くようなリッチなWebサイトを扱うことが常態化している現在、コードもどんどん複雑化しています。

リッチな表現としては「javaScript」が注目されがちなWeb業界ですが、その背景でCSSとしての設計思想(アーキテクチャ)や開発効率、メンテナンス効率を上げるための設計手法を取り入れるべきです。

より良い設計のゴールとして、Googleのエンジニアであり、数々のツールやドキュメントを残しているウォルトン氏の記事を引用すると、次の4つが挙げられます。

予測しやすい

予測しやすいというのは、期待通りに振る舞うかどうかということです。他のルールが影響して、記述したルール通りの振る舞いや見栄えにならない、または「追加したルールが他のルールに影響を与えることがないようにする」ということです。

再利用しやすい

スタイルがコピペされて膨らみ続けるCSSにならないためにも、再利用しやすいルールを持つことは重要です。あるUIデザインのCSSを一度作れば、再度同じようなUIに遭遇したときに、わざわざ書き直す必要がないようにするのが理想的です。

保守しやすい

新しいルールを追加・更新するときに、既存のルールのリファクタリングを必要としないことが大事です。追加したルールによって、既存のルールを壊すのは避けるべきでしょう。

リファクタリングとは、プログラムの外部から見た動作を変えずに、ソースコードの内部構造を整理すること。

拡張しやすい

自分と自分以外のプロジェクトに関わる開発者にとってメンテナンス・管理しやすいものである必要があります。拡張のしやすさというのは、CSS設計がサイトの規模が大きく複雑になるにつれて、拡張しやすいものになっているかどうかです。

【ウェブカツ】プログラミングを本気で習得して年収UPしたい君にオンライン学習スクール『ウェブカツ』を薦めたい。じょん(@fffff3434)です。 今記事では、Twitterなどで結構話題になっているオンラインプログラミング学習スクール『ウ...

破綻しやすいCSS設計とは

上記4つのゴールを満たすことができるCSSであれば、良い設計だと言えます。ただし、CSSがこれらを満たすには非力で、容易にコードが破綻してしまいます。

HTMLの構造に依存している

classをほとんど使わないシンプルなマークアップや「:first-child」のようなセレクタを使ったりする自体は悪くありませんが、中長期にわたって運用されるプロジェクトにおいては、これらが修正範囲を広げてしまう要因になることが多いのです。

スタイルを取り消している

スタイルの取り消しというのは、一度定着したルールを何らかの理由で「0」や「none」といった値でリセットするようなことを指します。

取り消しをする分、無駄なコードが増えるきっかけにもなるので、一度定義したルールを取り消すのではなく、追加していくようにするべきでしょう。

絶対値や「!impratant」を多用している

絶対値ではなく、相対値にすることで、元のフォントサイズが仮に変わっても同じ倍率を保つことができます。レスポンシブデザインにも有効的と言えるでしょう。

また、基本的に「!important」は避けたい記述です。

もしこれが多用されている状態になっているということは、既存のCSSが高い詳細度のセレクタで溢れてどうしようもない状態にあると言えるでしょう。

セレクタをより安全でシンプルなものに

要素セレクタを省略する(短くする)

不要なセレクタを省略することによって、単純な詳細度の問題を解決するためだけでなく、特定の要素への依存を減らすことで、可搬性(移植しやすさ)を高めることにもなります。

セレクタを限定的にする

半角スペースを空けて記述されるのは「子孫セレクタ」で、小要素以下の全ての要素を対象にCSSが適用されます。これに対し、「>」を使ったセレクタでは「子要素」つまり直下の要素のみが対象となります。

IDセレクタよりクラスセレクタを活用する

2カラムだったサイトが3カラムに変更になるなど、サイトの構造を変化させる必要がある場合、ID名を修正する手間などを減らすためにも、あらかじめクラスセレクタでまとめた方が一つの部品として設計をスムーズに進めることができます。

こうした設計がコンポーネント設計などと呼ばれます。

HTMLの構造に極力依存させずにスタイルを作ることによって、冒頭で挙げた4つのゴール「予測」「再利用」「保守」「拡張」しやすいCSSを書くことができます。

コンポーネント設計

コンポーネントとは「部品、成分、何かを構成する要素」などの意味を持つ言葉です。

ちなみに、ソフトウェアの分野では「特定の機能を持ち単体で完結しているが、単体では使用せず(できず)、他のプログラムから呼び出されたり連結されたりして使用されるプログラム部品」を指すことが多いです。

つまり、コンポーネント設計とは、噛み砕いていて言えば、機能や振る舞いなどを明確に分離するための設計です。分離するためには、カプセル化が重要です。

コンポーネント設計における「カプセル化」

カプセル化とは、何らかの構造やデータなどを隠し、外部からは許可された操作のみを受け付け、内部の仕様変更が外部に影響しないようにすることです。

カプセル化することにより、あるコンポーネント(構造)の変更が別のコンポーネントを壊してしまうということを防ぎ、分離が成立します。

その結果、コンポーネントのメンテナンス性が高まり、他のコンポーネントの不要な依存関係をなくすことで、再利用率も高くなります。

テレビなどの複数のボタンが付いたリモコンと、リモコンのボタンそれぞれの機能との関係を例に挙げると分かりやすいでしょうか。あるボタンの機能がアップデートなどにより変化したとしても、他のボタンに影響を及ばさないということです。

CSSにはカプセル化の概念がない

しかし、CSSにはカプセル化の概念が無く、容易にスタイルが予想外に他の要素に影響してしまう、ということがあります。

現状のCSSでは全てがグルーバルなスコープなので、CSSを書く開発者が複数人存在する場合は、各々の意図で書いたルールが汚染を発生させることがあります。

そのため、コンポーネント設計を実現するのが難しいCSSですが、次に紹介するオブジェクト指向CSS=OOCSSをベースにした、多くのCSSにおけるコンポーネント設計のアイデアが存在します。

オブジェクト指向CSS「OOCSS」

コンポーネント設計が難しいCSSに対し、オブジェクト指向プログラミングの概念を取り入れて、その実現に近づけたのがOOCSS(Object Oriented CSS)です。

OOCSSは、多くのCSS設計のアイデアの基礎となっています。

OOCSSのオブジェクトというのは、繰り返されるビジュアルパターンを指し、「1つのまとまったHTNL、CSSないしjavaScriptで書かれた独立したスニペットとして再利用できるもの」であると定義されています。

OOCSSの原則

OOCSSの原則は2つあります。

  • 構造と見た目の分離
  • コンテナとコンテンツを分離

構造と見た目の分離

構造と見た目の分離というのは、コンポーネントの基本構造と、具体的なルールや機能を分離するということです。分離することで修正、拡張がしやすくなります。

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

コンテナとコンテンツの分離というのは、場所に依存しないセレクタを書くということです。場所に依存しないことによって、大きな修正を省けることもあります。

このように場所に依存したセレクタではなく、コンポーネントを拡張していくアプローチの設計など、OOCSSをより実践的に扱うためのガイドラインの1つが「SMACSS」です。

CSS設計における「SMACSS(スマックス)」

SMACSSとは「CSSをより体系立て、より構造化させることで制作とメンテナンスをより容易に行うテクニック」と公式サイトでは述べられております。

そのSMACSSのポイントの1つは、あるパターンを抽出しやすくするための『カテゴリ』を用意している点です。

例えば、散らかったものを片付けるためには、何かしらのカテゴリに分類したケースを用意して、条件に合うものをそのケースに入れていくほうが容易で早いはずです。

ページに存在する多くのパターンをどのくらいの粒度で抽出するのか、SMACSSが提案する緩いカテゴリを軸に実践してみることで、コンポーネント設計の糸口が見えるはず。

SMACSSで提案しているのは、次のカテゴリです。

  • Base
  • Layout
  • Module
  • State
  • Thema

SMACSSにおける「Base」

Baseは、ブラウザ及びプロジェクトにおける、各要素のデフォルトのスタイルを定義します。近年のCSS開発では、rest.cssなど、要素のスタイルを初期化するライブラリを採用することが増えていますが、それらは「Baseカテゴリ」に分類できます。

他には、bodyに定義するであろう全体の背景やフォントファミリー、リンクの色といったものなどを含めます。基本的にこのカテゴリで定義したものは、よほどの理由がない限り、書き換えることはありません

逆に言えば、書き換えるようなことが起きてしまうと、既存の要素全てに影響を与えてしまうため、あまり多くのスタイル、特にwidthやmargin、paddingといったスタイルを要素そのものに持たせないようにしましょう。

SMACSSにおけるLayout

Layoutに属するのは、それまでの慣習的に言えばIDを用いて定義されるようなヘッダー、フッター、コンテンツエリア、サイドバーというような、構成の大枠(sectionなど)を作る要素へのルールです。

命名規則としては、クラス名の頭に、Layout、もしくはその頭文字の「l」などの接頭辞をつけることをSMACSSでは推奨されています。

SMACSSにおけるModule

ページを構成するほぼすべてがModuleのカテゴリに属すると考えていいでしょう。

例えば、ボタンであったり、見出しやリンクであったり、あらゆるところで再利用できるオブジェクトです。StateとThemeはここでは説明を省略します。詳しくは本書にて……

CSSの命令規則

他の言語であれば、スコープによってカプセル化をすることで汚染を防げますが、CSSでは全てがグローバルなスコープにあります。

そのために命名された名前があまりに抽象的であれば、数日後にコードを書き加えるときに問題が発生してしまうときがあります。

そのためにも、クラス名が冗長になることを恐れずに、クラス名を見て、どのコンポーネントの拡張かが分かるように命名すれば、スタイルの競合や汚染のリスクを減らせるはず。

その命名規則について、さらに深掘りをしていく中で、新たに広まったのは「BEM」や「FLOCSS」というアプローチです。

CSS設計における「BEM(ベム)」

BEM(ベム)は、近年のCSS設計において、多くの開発者が取り入れているアイデアになります。CSS設計の最も難しいとも言える命名規則において、独特なアプローチによって問題を解決しています。

BEMとは、Block、Element、Modifierの略で、ページを構成する要素をこの3つに分類して考えます。

BEMそのものは、複雑で巨大なサービスを効率よく開発・メンテナンスをするための大きなシステムなのですが、このBEMの持つ特徴的な命名規則がCSSの命名規則のアイデアとして、多くのプロジェクトやフレームワークで採用されています。

Blockは、SMACSSの解説に用いたアラートメッセージのパターンでいうところの.alertが該当します。以下に続くElementやModifierは、このBlockを基点にして、命名されます。

続きは本書にて……

最終的には、壊れない完璧な設計を求めるのではなく「壊れたときに勇気を持って修復できる設計」ができるエンジニアを目指していきたいです。