はじめに
CSSやSCSSを書いている時に、こんな経験はありませんか?
- コードを追いにくく、どこを修正すれば良いのかわからない
- 別のメンバーが書いたスタイルを再利用できず、重複して記述してしまう
- 小さな変更のはずが全体に影響し、思わぬバグが発生
これらの問題は、記述ルールを統一することで解決できる場合が多いです。この記事では、普段私が意識しているCSS/SCSSの記述ルールや実践例をご紹介します。これを読むことで、コードの可読性が向上しチーム全体で効率的に開発できる環境を構築するヒントの手助けになれば幸いです。
この記事について
FLOCSSをベースに解説
私の所属するチームでは、CSS設計手法としてFLOCSSを採用しています。そのため、本記事ではFLOCSSの考え方に沿ったルールや具体例を紹介します。
対象読者
CSS設計を始めたばかりの初心者や、記述ルールの見直しを検討している方を対象にしています。基本的な内容が中心なので、既に実践されている方には物足りない部分もあるかもしれません
この記事で得られること
- コードの可読性を向上させるルールの具体例
- チーム開発で一貫性を保つためのアプローチ
- 将来の保守や変更に備えたCSS設計のヒント
この記事を通じて、CSS/SCSSの記述ルールを理解し、あなたのプロジェクトでも取り入れやすくなることを目指しています。
なぜCSS/SCSSの記述ルールが必要なのか?
1. コードの見通しを良くし、開発や保守を容易にする
記述ルールが統一されていないと、ネストが深くなったり、命名規則がバラバラになったりして、コード全体の見通しが悪くなります。結果として、以下のような問題が発生します。
-
問題(例)
ネストが深すぎて特定のスタイルがどの要素に適用されているかわからない -
解決(例)
ネストの深さを制限するルールを設けることで、コードが読みやすくなります
2. 複数人での開発時に一貫性を保つ
一貫性のないコードは、新しいメンバーの参入を難しくし、レビューや保守の手間を増やします。記述ルールを統一することで、誰が書いても同じ書き方になり、プロジェクト全体の一体感が生まれます。
3. 将来的な仕様変更やデザイン改修の工数を削減
整理されていないCSSは影響範囲が特定しにくく、仕様変更や改修に多くの時間がかかります。
一方、統一された記述ルールに基づくコードは、修正箇所を簡単に見つけられ、工数を大幅に削減できます。
CSS設計の「できる4原則」
CSS/SCSSの設計において、次の 4つの「できる」 を意識することで、保守性と拡張性を高めることができます。
- 予測できる: 他の作業者がコードを見て、その動作を予測できる
- 再利用できる: 同じスタイルを複数の場所で使用できる
- 保守できる: 必要な箇所だけを簡単に修正できる
- 拡張できる: 新しいスタイルや機能を追加しても影響が少ない
この「できる4原則」を意識することで、コード全体の品質が向上します。
SCSS記述ルールの実践
私が所属しているチームでは、FLOCSSをCSS設計の基盤として採用しているため、FLOCSSで説明します。
FLOCSSとは?
FLOCSSはスタイルを以下のカテゴリに分類することで、再利用性を高め、スタイルのスコープを明確にします。
カテゴリ | 説明 | 接頭辞 |
---|---|---|
foundation | リセットスタイルや基本スタイル | なし |
layout | ページ全体の構造を定義 | l- |
object/component | 再利用可能なUIパーツ | c- |
object/project | プロジェクト固有のスタイル | p- |
object/utility | 補助的なクラス(非推奨) | u- |
書式ルール
SCSSを記述する際の基本的な書式ルールを以下に示します。このルールに従うことで、一貫性と可読性の高いコードを記述することができます。
セレクタとプロパティの記述
- セレクタ: セレクタの後には半角スペース1つを空けて「 {(中かっこ)」を記述します
- 複数セレクタ: 複数のセレクタを記述する場合は改行します
- インデント: 各プロパティの前には半角スペース2つ分のインデントを入れます
-
プロパティと値:
- プロパティの後にはスペースを入れずに「 :(コロン)」を記述し、その後に半角スペース1つを空けます
- プロパティ値の後には必ず「 ;(セミコロン)」を記述します
- 中かっこ: 閉じ括弧「 } 」の前にはスペースを入れません
記述例
.selector,
.selector {
property: value;
property: value;
property: value;
}
値や色指定に関するルール
-
値が「0」の場合: 単位を省略します
例:margin: 0;
-
色指定: 16進数で指定し、短縮可能な場合は短縮します
例:#fff
(#ffffff
を省略) -
小数値: 1以下の数値では値の「0」を省略せず記述します
例:opacity: 0.5;
-
パス指定: パスは「 '(シングルクォーテーション)」で囲みます
例:background-image: url('path/to/image.png');
- マージンの方向性: 要素間のmarginは、上方向で取るようにします
ネストのルール
SCSSでは、深い階層のネストを避けることが推奨されます。複雑な構造は保守性を低下させるため、以下のルールを遵守してください。
- ネストは3階層以内に収めます(メディアクエリを除く)
- ネストするセレクタの前には改行を入れます
- 「 & 」は、擬似クラスや擬似要素のみに使用します
- メディアクエリは、セレクタごとに記述します
記述例
.selector {
property: value;
property: value;
property: value;
@include メディアクエリ {
property: value;
property: value;
property: value;
}
.child-selector {
property: value;
property: value;
property: value;
@include メディアクエリ {
property: value;
property: value;
property: value;
}
&::pseudo {
property: value;
property: value;
property: value;
}
}
}
その他、書式全般のルール
以下のルールを守ることで、さらに一貫性と効率性を高められます。
- 外部CSSファイルの文字コードはHTMLファイルと統一します
- モバイルファーストの考え方でメディアクエリを記述します
例: 小さい画面から大きい画面へのスタイル変更を想定します。 - インラインスタイルは避けます。外部ファイルで管理し、スタイルと構造を分離します
- JavaScriptで操作するクラスには、接頭辞
js-
を付け、スタイルを適用しないようにします
例:<div class="js-carousel"></div>
SCSSのファイル構造
- 新規でSCSSを記述する時は、import用と編集用をそれぞれ用意して記述する
- import用のファイルでは、必ず設定ファイル(
/common/foundation/_settings.scss
)を読み込む - import用のファイルに記述できるのは、importのみ。styleを記述しない
- importする時は、「.scss(拡張子)」は記述しない
- 編集用のファイルは、ファイル名の頭に「_(アンダーバー)」をつける
- 編集用のファイルは、BEMのブロック要素毎で1つのSCSSファイルにまとめる
- 共通のスタイルを特定のページだけ上書きする場合は、そのページの
_stylefix.scss
に記述する。_stylefix.scss
は最下部に記述する
ルールに基づいた構造例
scss/
├── hoge/ /* 下層にディレクトリが存在しない場合 */
│ ├── _aaa.scss /* 編集用(BEMのブロック単位の)ファイル */
│ ├── _bbb.scss /* 編集用(BEMのブロック単位の)ファイル */
│ └── hoge.scss /* import用(分割したファイルを集約する)ファイル */
│
└── huga/ /* 下層にディレクトリが存在する場合 */
├── aaaaaa/ /* ディレクトリ毎にフォルダを作成 */
│ ├── _aaa.scss /* 編集用(BEMのブロック単位の)ファイル */
│ └── _bbb.scss /* 編集用(BEMのブロック単位の)ファイル */
├── bbbbbb/ /* ディレクトリ毎にフォルダを作成 */
│ ├── _aaa.scss /* 編集用(BEMのブロック単位の)ファイル */
│ └── _bbb.scss /* 編集用(BEMのブロック単位の)ファイル */
├── aaaaaa.scss /* import用(分割したファイルを集約する)ファイル */
└── bbbbbb.scss /* import用(分割したファイルを集約する)ファイル */
import記述例
// 設定ファイル読み込み
@use '../common/foundation/_settings';
// ページ固有デザイン読み込み
@use '_aaa';
@use '_bbb';
@use '_stylefix';
BEMについて
FLOCSSでは、クラス名の命名規則として BEM(Block, Element, Modifier) を採用しています。BEMの基本的な考え方を理解することで、CSSクラス名を直感的かつ効率的に管理することが可能になります。
要素 | 例 | 説明 |
---|---|---|
Block | .card | 独立した意味を持つ要素 |
Element | .card__title | Blockの構成要素 |
Modifier | .card--size-large | BlockやElementの状態や外観を変更する |
Before/Afterで見るBEM記述での統一の効果
統一されたルールに基づくコードは、簡潔で直感的です。他の作業者が見ても、すぐに役割や関係性を理解できます。
Before: 統一されていないコード
.card-box { }
.cardBox__Title { }
.highlight-card { }
問題点
- 命名規則が一貫していない
- クラス名から用途が直感的に理解できない
- スタイルが衝突する可能性がある
After: 統一されたコード
.card { }
.card__title { }
.card--size-large { }
改善点
- 一貫した命名規則(BEM)を採用
- クラス名が直感的で用途が明確
- 再利用性が高まる
BEMの粒度を考える際のポイント
BEMの粒度を考える際は、「Blockは独立」「Elementは部分」「Modifierは状態」という基本を意識することが重要です。
具体的なUIを想定し、クラス名をシンプルかつ直感的にすることで、コードの可読性と管理のしやすさを向上させられます。
特に ModifierはBlockに付与する ことで、UI全体で見たときに関係性が明確になり、スタイルの一貫性を保つことができます。
一方で、Elementに直接Modifierを付けると、同じ状態を持つ他のElementが増えるたびに命名が複雑になり、管理が煩雑になるため避けるべきです。
ModifierをBlockに付けるべき理由とその違い
以下は、ModifierをBlockに付けた場合とElementに付けた場合の具体例です。
<!-- 推奨: ModifierをBlockに付与 -->
<div class="card card--size-large">
<h2 class="card__title">タイトル</h2>
<p class="card__content">内容</p>
</div>
<!-- 非推奨: ElementにModifierを付与 -->
<div class="card">
<h2 class="card__title card__title--size-large">タイトル</h2>
<p class="card__content--size-large">内容</p>
</div>
推奨例の利点
-
BlockにModifierを付与
Block全体の状態(.card--size-large
)を一元管理することで、関連するすべてのElementに対するスタイルが統一され、コードがシンプルになります。
非推奨例の問題点
-
ElementにModifierを付与
Elementごとに状態を管理する必要が生じ、クラス名が冗長になるほか、変更が発生した際に全てのElementを修正する必要が出てくるため、保守性が低下します。
まとめ
CSS/SCSSの記述ルールを統一することで、コードの可読性や保守性を向上させるだけでなく、プロジェクト全体の効率化にもつながります。まずは小さな改善から始めてみてください。