Guide

意図しない影響や不具合を発生させず、より良くコードを管理するためのガイドです。

REMMに限定されないTIPSも含め、様々な考え方を掲載しています。

CSS設計パターンガイド

「REMM」は、「BEM」のように使う、「OOCSS」のように使う、または混在させるなどの様々な設計パターンに対応できます。

これは、同じ記法でありながらも、サイトの特性(オフィシャル系、ポータル系、ブログ系、サービス系、管理画面系 etc.)に応じて設計を切り替えやすくなっていることを意味します。

反面、事前の方針決定がないまま分業すると、アプローチがバラバラになる可能性があります。

以下は、こういった状況を防ぐための使い方(CSS設計パターンやコーディングアプローチ)のガイドです。

A見出しやボタンなどの小さな部品をそのまま再利用する

見出しやリンクボタンなどの小さな部品を、そのまま再利用・配置して完成させるパターンです。

このアプローチが向いていると考えられるのは、システム管理画面、ドキュメントサイトやブログ、ポータル系、ニュースサイトなど、部品の形状やカラーや用法が統一されているようなサイト(言い換えるとシステマチックなサイト)です。

小さな部品の例としては以下のようなものです。

`heading`(見出し)

														

見出しテキスト

`link_btn`(ボタン形状のリンク)

こういった部品は、粒度の大きな部品の内部に配置することが多くなります。
あらかじめ配置した親要素からの影響を受けにくいようにしたい場合は、以下のように内部の要素を「Element」化します。

内部を「Element」化することで、事前に影響分離を試みた`heading`

														

見出しテキスト

内部を「Element」化することで、事前に影響分離を試みた`link_btn`

上記のように記述していれば、他の大きな部品の中に配置したときに、その部品の内部に同じ.icon.textといった名前を持つ部品があったとしても、命名が重複しないため影響を受けにくくなります。

バリエーションや変化版については、以下のような記述方法を採択できます。

`heading`の変化版を「Modify」で作成

														

見出しテキスト

上記の変化版・バリエーションの内部を、変化版に対して「Element」化すると以下のようになります。

作成した「Modify」の内部部品を「Element」化

														

見出しテキスト

同じ単語でも、マルチクラスで拡張したい場合は以下のようになります。

`heading`を「Modifier」で拡張

														

見出しテキスト

内部部品の.iconをマルチクラスで拡張したい場合は以下のようになります。

`heading`の内部部品を「Modifier」で拡張

														

見出しテキスト

他にもパターンは考えられますが、制作物の特性や種別に応じてアプローチを切り替えることができます。

B中粒度のブロック単位で仕上げる

ヘッダーやフッター、ナビゲーション、新着情報やコンテンツ表示など、制作者が定めた範囲の領域(ブロック)に名前を与え、その粒度で「Roots」による一元管理で影響を閉じるアプローチです。

以下のものは、「Roots」の名前と汎用的な単語のみで影響を閉じようとしたものです。

`gnav`

														
`card`

														

上記のような場合でも、「予約語のように扱う」のアプローチをおこなった場合は、内部に何かしらの要素がネストされても問題は起こりにくいといえます。

命名によって影響をあらかじめ回避したい場合は、以下のように内部部品を「Element」化します。

内部を「Element」化することで、事前に影響分離を試みた`gnav`

														
内部を「Element」化することで、事前に影響分離を試みた`card`

														

変化版、バリエーションが必要なときには、以下のように拡張できます。

`card`の変化版を「Modify」で作成

														

作成した「Modify」の内部部品を「Element」化

														

`card`を「Modifier」で拡張

														

`card`内部を「Element」化した上で、「Modifier」で拡張

														

コンテンツ表示など、内部に様々な部品が必要な場合

部品として区切った範囲が「コンテンツの1ブロック分」などの場合、内部の構成部品は多種多様となります。
たとえば、専用の見出し、リスト、画像、テーブル、テキスト、それらを分離してまとめるための領域や構造体などです。

内部に配置するこういった部品すべてを「Roots」の専用部品として命名すると以下のようになります。

すべてを「Roots」に所属させた`photo_gallery`

																	
																

この状態であれば、変更が必要になったとしても、CSSの特定が容易になります。
(※Sassで&記法によるセレクタ記述をしていない限り、修正や改修の際には、ブラウザのインスペクタ機能(要素検証)で要素名を調べる→エディタで全検索→ピンポイントでヒット といった使用感になるでしょう)

反面、たとえば.photo_gallery--title(コンテンツの見出し部分)が、異なる他の部品の見出し部分と同一デザインであった場合、要素の名前が異なるために同じCSSプロパティを記述することになります。

この例においては、Sassの@mixin@extendを使っていれば編集は容易になります。

レギュレーションによる禁止などで、@mixin@extendを利用できない場合には、異なる部品の該当箇所すべて(※10個の部品があるなら、10箇所)に同じCSSプロパティを記述することになります。

内部に別の中粒度部品を設置する場合

.photo_galleryの例で、.photo_gallery--bodyの内部に「写真一覧」の部品を配置する場合を例に説明します。

このとき、採択できるのは大きく分けて2パターンです。

ひとつは、.photo_galleryに所属する部品として作成する場合。
もうひとつは、別の中粒度部品として作成してネストする場合です。

結論から言えば、どちらでも問題はなく、どのように管理したいかで決められます。

以下は、写真一覧のブロックに異なる「Roots」の部品をネストしたパターンです。

異なる「Roots」の`image_list`をネストした場合

																	
																

上記の場合、.image_listを別の場所でも再利用するためのこのようにしているのかもしれません。

以下は、.photo_galleryの内部部品として設置した場合の例です。

`photo_gallery`の内部部品として設置した場合

																	
																

写真を配置するためのコンテナを.photo_gallery--image_listとし、さらにその内部は命名が冗長になるのを避けるために、「予約語のように扱う」のアプローチを採択しているような例です。

写真一覧はここでしか使わないと確定しているため、親の内部部品として影響を閉じているのかもしれません。

C中粒度で影響を閉じながらも、小さな部品を再利用する

「(B)中粒度のブロック単位で仕上げるアプローチ」と、「(A)小さな部品をそのまま再利用する」を併用したパターンです。

以下は、中粒度の部品に「Roots」の異なる小さな部品を配置しています。

中粒度の部品(.photo_gallery)は、「(B)中粒度のブロック単位で仕上げる」アプローチで構造体のみをスタイリングし、
見出し(.heading)やリンクボタン(.link_btn)は、「(A)小さな部品の再利用」のアプローチでスタイリングします。

影響を閉じた「フォトギャラリー」の構造体に、影響を閉じた小さな部品をネスト

														
													

このとき、それぞれの「Roots」(photo_galleryheadinglink_btn)において、それぞれが影響を閉じた状態でスタイリングできていれば、.photo_galleryからの子孫セレクタで.headingを指定してスタイリングする必要はありません。

しかし状況によっては、例外的に上書きしたい場合もあります。

そのときは、.photo_gallery側のSassファイルに、その旨のコメントを添えて上書きのコードを記述すれば、大抵の制作者はその意図を理解できます。

こういった「Roots」から「Roots」への上書きを不許可にしているわけではありません。

多くの例外が発生するのであれば、設計そのものを見直す必要もありますが、部分的な上書きまで制限すると、状況によっては、一か所のデザイン再現のために全体を見直すという「不毛なゲーム」が始まってしまいます。

D小さな部品をイニシャライズし、差分スタイリングで完成させる

小さな部品に基礎のスタイリングのみをおこない、ネストした親からの子孫セレクタでデザインを完成させるアプローチです。

このアプローチが有用な状況とはどういうものかというと、
「小さな部品は一見そのまま再利用できそうだが、よく見ると場所ごとに若干デザインが異なる」といった場合です。

以下の例は、HTMLコードだけ見れば「(C)中粒度で影響を閉じながらも、小さな部品を再利用する」とほぼ同じですが、CSS側のアプローチを変えることで差分スタイリングをおこなおうとしているものです。

差分スタイリングで完成させる「フォトギャラリー」

														
													

CSS側では、.heading.link_btnとその内部部品に、全域で共通するスタイルのみを与えます。
(たとえば、フォントサイズやテーマカラー、余白などです)

そして、.photo_gallaryの子孫セレクタにより、.photo_gallaryで求められるデザインを完成させます。

同様に他の部品の内部でも、.photo_gallaryとは異なる、その部品が求める.heading.link_btnのデザインを完成させます。

考え方としては、リセット系のCSSだけでは影響範囲が広くなりすぎるために、「独自の命名でスコープを狭めてイニシャライズしている」と捉えます。
これによって、意識は「複雑な上書きルール」から、「シンプル化するための部分的な初期設定」に変化します。

単語の汎用化|予約語のように扱う

「汎用的な短い文字列」を再利用しながら、影響を分離するための方法を紹介します。

「汎用的な短い文字列」とは、フロントエンド制作でよく利用する.icon.text.list.linkなどの短い英単語です。

これらを要素への意味付けとして使用すると、いたるところで同じ単語を使用することとなり、自身より大きな粒度の部品にネストする機会も多くなります。

影響の分離を考えたときは、これらの小さな部品を「Roots--Element」の型で固有の名前を与えてもよいのですが、場合によっては「余計な手間」「命名が冗長になり見通しが悪くなる」ことがあります。

予約語による影響分離の基本となる考え方

CSSの仕様として、セレクタのみを記述してプロパティが空の状態でも画面上にエラーが表示されることはありません。

また、SassではCSSプロパティを記述しなければ、そもそもCSSとして出力されません。

この2つの特性を生かすと、制作で何度も使用するような単語には直接的なスタイリングは与えない。というアプローチをとることができます。

text.scss

														//Roots
														.text {}
													

予約語運用のメリット

予約語のように扱うと決めた単語・文字列は、いたる所で再利用できます。
なぜなら、第一セレクタでCSSプロパティを指定しないと決めているため、グローバルな影響が出ないからです。

そして、ネストした他の大きな粒度の特性に応じて、様々な姿に変化できるようになります。

見出し

														

見出しテキスト

ボタン

														
													

上記は、「Roots」内部に同じ単語(.icon.text)を使用していますが、第一セレクタでスタイリングしていないため、グローバルな影響は出ません。
そして、それぞれの親要素(Roots)において求められるデザインに変化できます。

単語を追加していくことによる影響分離方法ではなく、いわば「引き算の影響分離方法」となります。

予約語の明示と情報共有

予約語のように使用していることを情報共有するには、その単語を「Roots」としたSassファイルを作成します。
そして、セレクタを記述し、中身は空の状態で置いておきます。

このとき、Sassコメントで用途を記述しておけば、情報共有するための「簡易の仕様書」や「辞書」になります。

text.scss

														//text
														//--------------------------------
														//意味付け用の「予約語」として使用し、グローバルなスタイルは与えない。

														//Roots
														.text {}

													

上記の状態であれば、「この単語はHTMLに記述されてはいるが、CSSとしてグローバルな影響は出ていない」ということが分かります。

予約語の拡張

予約語として扱っていたRootsの単語そのものを拡張し、辞書を増やすような場合は以下のようにセレクタを追記し、同じ要領で中身は空の状態で置いておきます。

text.scss

														// text
														// --------------------------------
														// 意味付け用の「予約語」として使用し、グローバルなスタイルは与えない。

														// Roots
														.text {}

														// 成功系のテキスト
														.text-success {}

														// 失敗・エラー系のテキスト
														.text-error {}

													

さらに、「(D)小さな部品をイニシャライズし、差分スタイリングで完成させる」といったアプローチに切り替える必要が出てきた場合、このtext.scssの中身を書き換えることで、素早く用途を変更できます。

text.scss

														// text
														// --------------------------------
														// 差分スタイリング用
														// グローバルな基本スタイルのみ指定する

														// Roots
														.text {
															…
														}

														// 成功系のテキスト
														.text-success {
															color: green;
														}

														// 失敗・エラー系のテキスト
														.text-error {
															color: red;
														}

													

REMM使用における影響分離の考え方

影響分離の考え方をガイドとして記載します。

CSS編集における「意図しない影響」や「望まないプロパティ汚染」のメジャーな例の一つとして、
「追加した要素に対する、親要素の子孫セレクタの影響」が挙げられます。

これを防ぐには、何らかの部品を作成しているときに以下の2点を意識します。

  • A今後、この部品の内部に「他の部品が追加される可能性はあるか」、また「その可能性は高いか、低いか」
  • B現在編集中の要素内に他の部品を追加した場合、「その内部部品となるものに影響を与えることはないか

Aの検討事項について

「他の部品が追加される可能性はあるか」という検討事項に対し、可能性が「無い」、または「低い」と判定できるなら、子孫セレクタを使用してもリスクは低いといえます。

例としては、ネスト最下層にあるような小さな部品や、ブランディングエリアなどの、全域で使用される部品です。

具体的な例を挙げると、「見出し内部のアイコンとテキストが、その見出しの内部にもうワンセット追加される」というのは一般的には考えにくいため、サイトのロゴやサイト名を表示するエリアに全く用途の異なるものが追加される可能性は低いと判断できます。

Bの検討事項について

今後、「内部部品となるものに影響を与えることはないか」という検討事項に対しては、次の2つで回避できます。

  1. 1命名のユニーク度を高め、サイト内で一意にする
  2. 2プレーンなHTMLタグを子孫セレクタに使用しない

(1)の「命名のユニーク度を高め、サイト内で一意にする」に関しては、
命名が全域で一意であり、その命名を誤って使用してしまうことがなければ、どれだけCSSの詳細度が低くても他から影響を受ける可能性は低いと言えます。

(※このための方法として「Element」化があります)

(2)の「プレーンなHTMLタグを子孫セレクタに使用しない」に関しては、
そもそもHTMLは文書作成用の言語であるため、当然ですが同じ文字列(タグ)を重複利用します。
「プレーンなHTMLタグ」を子孫セレクタに含めていると、ネストが発生した場合、プロパティ汚染のリスクが高くなります。

小さな部品にも名前を与え、その名前をセレクタに使用することで、未然にリスクを回避できます。

(※このとき、細部部品の命名冗長化を防止するために「予約語」のアプローチがあります)

直接表示に関わるHTMLコードは、bodyを最上としたネストの集合体です。

何かを追加しようとすれば、常に影響が発生し得るのは仕様上避けられず、更には、改善や顧客の要望などによって、将来どこに何が必要になるのか(追加されるのか)は分かりません。

これらの懸念は「プロジェクトによりけり」ではありますが、将来不確定なものに影響を与えたくない場合は、下方階層への影響を「今現在の段階で、そのスコープの中で閉じておく」というのが最善の策と言えます。

Rootsに対するプレフィックス(接頭辞)の考え方

「SMACSS」や「FLOCSS」などのCSS設計手法を導入している場合、以下のようなプレフィックスが必要になるかもしれません。

  • l-header
  • l_header
  • m-header
  • m_header
  • c-header
  • c_header
  • u-clearfix
  • u_clearfix
  • is-active
  • is_active

これらのプレフィックスの目的は、人が素早くその役割や意味を把握するためのものであるため、元の単語の一部として捉えることができます。(※このときの連結記号に特にルールや制限はありません。)

既存CSS設計手法のプレフィックスを導入

site_header

														
heading

														
side_menu

														

上記のように、様々なプレフィックスを付与できます。

独自の一時拡張用のプレフィックス

恒常的に付与するプレフィックスではなく、「Rootsに紐づく部分的な拡張」の場合は、同じSassファイルで管理できます。

以下は、「l-」に対して「意匠を与えないレイアウト専用のボックス」というルールを独自に与えてプレフィックス化した例です。

このとき、.l-side_menuは、「Roots」の.side_menuを、特定条件でposition:fixedにするためだけに働いているかもしれません。

side_menuの例外的なプレフィックス-1

														

このような場合、.l-side_menuは、.side_menuに帰属していると予測がつくため、わざわざ別のSassファイルで管理する必要はなく、.side_menuのSassファイルで管理できます。

このように、何らかの独自規定のプレフィックスがあったとしても、その「Roots」に紐づいていると予測可能であるなら、別のSassファイルとする必要はなく、同じSassファイルで管理します。

CSSフレームワークのプレフィックス

CSSフレームワークの中には、特定のプレフィックスを付与するものがありますが、これらも同様の考え方で利用できます。

以下は、「UIkit」のプレフィックスを持つカードです。

l-header

														

「Roots」であるcardという語句に、識別子としてuk-のプレフィックスが付与されていると捉えることができます。

CSSフレームワークの併用

パーツの命名とデザインがセットになって部品提供されているような「CSSフレームワーク」を併用するパターンです。

前提事項として「併用」がある状況とは、「使用しているCSSフレームワークの部品だけではプロジェクトの要件を満たせないために、何らかのものを追加作成しなければならない」といった状況であると考えられます。

「CSSフレームワーク」の大半はケバブケースを採用しており、REMMも同様です。

このため「記法違いでコードの見通しが悪化する」というリスクは低いと言えます。

Bootstrapを例とした併用アイデア

Bootstrapを例に挙げると、まず、Bootstrapを「MCSS」の概念を拝借して基底に敷きます。(※BaseなどのSassディレクトリ)

これによって、Bootstrapを使用しながら、他のディレクトリで独自部品を管理・追加しやすくなります。

命名規則のコンフリクトが起こるケース

命名規則や概念のコンフリクト(衝突)が起こるのは、
たとえば、Bootstrapの「Components」として定義されている.cardの専用部品などです。

Bootstrapでは.card専用の見出しは.card-titleですが、「REMM」で記述すれば.card--titleとなります。

この例では、.card-titleを使えばBootstrapのスタイルが適用されますが、「内部部品に独自定義のものが必要なら.card--titleで拡張する」といった使い方ができます。

当然のことながら、.cardという同名の「Roots」を作成すれば干渉しますが、そもそも、CSSフレームワークを意図的に導入している場合は、このコンフリクトはどんな状況でも起こります。

他のCSS設計手法との併用

厳格な命名規則が存在するものは、記法の違いでコンフリクトしますが、それ以外のものであれば、概念や手法の良い所を組み合わせやすいと言えます。