YATのBlog

当ブログでは商品やサービスの紹介にアフィリエイト広告を掲載しています

Web制作を行う全ての方へ

CSSのコーディング設計について考える事

CSSの設計は人によって様々で、これが正解というものは無いのですが、何も考えずに作っていくと命名の重複で悩んだり、定義したクラスの使い回しがしづらかったりといった悩みが多くなってきます。これらを防ぐためには、CSSの設計を考えながらコーディングすることが大切です。

目次

  • CSSで大切なこと
  • ドキュメントの作成
  • CSS構成について
  • 様々な設計手段
  • SASS、SCSS
  • コードリファクタリング
  • 最後に

CSSで大切なこと

CSSで大切なことは CSS Architecture でPhilip Walton氏が述べているように

  • 予測しやすいこと
  • 再利用しやすいこと
  • 保守しやすいこと
  • 拡張しやすいこと

で、これらはページが多くなれば多くなるほど重要度が高くなります。

予測しやすいということは、命名規則のルールにより、どのクラスがどういった挙動するかが掴みやすく、修正作業が必要な時にソースコードを追う時間が短縮されます。

再利用しやすいということは、ソースコードの構造がわかりやすく、記述したソースの財産を取り出しやすいところになります。しかし、例え命名規則がわかりやすくても、どこに何が記述されているか分かりづらければ再利用が困難になってきます。

保守しやすいということは、ソースコードの修正、加筆が容易にできる状態を維持していることであり、これが破綻すると保守し続けることが難しくなっていきます。

拡張しやすいということは、定義した機能を拡張したものが必要になった場合、容易に作り出せるということで、これを実現するには上記3点が実現されていなければ難しいでしょう。

これらを維持していくには、開発開始時にコーディングルールや命名規則をある程度決めておき、そのルールに徹底する事が重要なファクターとなります。

ドキュメントの作成

プロジェクトを開始する際、まずドキュメントを書き起こします。
上記で触れた通り、コーディングルールや命名規則を決めることは重要で、それをドキュメントに起こしておくことでチーム内での認識の違いや、自分自身の記憶違いを防ぎます。

ドキュメントはチーム内で誰でもいつでもアクセス出来る場所にあることが理想で、プロジェクト管理ツールなどを利用している場合はそれに付随するwikiやドキュメントの添付などを利用し、わかりやすくしておきます。

例)

  • ファイル命名規則の記述
  • コーディング規約
  • リセット利用に関して
  • タスクランナー
  • 対象ブラウザ
  • ブレークポイント
  • PCファーストorモバイルファースト
  • 画像の命名規則(_on,_offによるロールオーバーの切り替えなど)
  • ディレクトリ構成
  • etc

プロジェクトに新しいメンバーが参加した場合や、プロジェクトを誰かに引き継ぐ際、分かりやすい事が重要です。

例え1人で進行している案件であっても、Web制作の場合、保守は納品したクライアントが行っていったり、そこから別の会社へ渡る場合もありますし、納品後保守もお願いしたいと言われるケースもあります。

その場合ドキュメントがあれば作業に入りやすいですし、仮に自分が時間の経過後に保守することになっても、過去の記憶を思い出すことに時間をかける事が少なくなります。

CSSの構成について

CSSの設計

CSSの設計

CSSの設計は人によって様々で、それぞれのやり方に間違いというのは殆どなく、ましてや
クラスの単語を-(ハイフン)で繋ぐのか_(アンダーバー)で繋ぐのか?また、キャメルケースで記述するのか?といった細かい部分について、どれが正しいのか?といった議論はさほど大した意味を持ちません。

大切なのは、ソースの中でルールが統一されており、読みやすいか?、分かりやすいか?という部分です。

クラス名などはCSSだけに関わることではなく、PHPやJavaScriptのような他の言語でも利用されます。
その際、命名規則がバラバラになっていると、プログラムの処理を記述する事が困難になってしまいます。

しかし、上記で述べたドキュメントを渡して簡単な説明をするだけで、書きやすさが変わってきますので、HTMLやCSSのコードを書くという事は、自分だけにかかる領域ではないということを意識しておくことが重要です。

では、ルールをどう決めるのか?についてですが、ひとつは自分自身ですべてのルールを決めてドキュメントにする方法です。

このメリットは自分自身がコーディングする場合、自分でルールを決めるのでコードを書く場合に悩むことが少なくなります。デメリットとしては、わかりやすさ、読みやすさとを言及する場合に、この独自のドキュメントしか使っていなければ、他を知る機会を減らしてしまうので他社と一緒にコーディングをすることが発生した場合、すり合わせに時間がかかってしまいます。

もう一つの手段としては広く知られる案を利用するという事です。

様々な設計手段

設計の種類は様々存在しておりその中でも

  • OOCSS
  • BEM
  • SMACSS
  • FLOCSS

あたりが有名ではないでしょうか

OOCSS

OOCSS

OOCSS

オブジェクト指向のCSS設計でObject Oriented CSSが正式名称です。
オブジェクトに基づいて考案された設計手段で、構造や見た目と内容を分離してクラスを定義、それらの組み合わせでスタイリングしていくのが特徴です。

この考え方は他の設計手法でも多く取り入れられており、根本的な考え方の基礎となっています。

.btn {
    width: 100px;
    height: 50px;
}
.btn-red {
    background: #f00;
    color: #fff;
}

<button class="btn btn-red">ボタン</button>

ベースとなる.btnを作っておき、それを装飾する.btn-redを定義して装飾するといった使い方をします。

OOCSSについて、CodeGridさんがより詳しく解説されていますので、より詳しく知りたい方はそちらを読んでみてください。

https://app.codegrid.net/entry/oocss-1

BEM

BEM

BEM

Block、Element、Modifierの略で、HTMLを明確にすることを軸においているのが特徴です。OOCSSの概念を取り入れ、且つ、 要素をBlock、Element、Modifierの3つに分けた命名規則を扱ってクラス名を決めていきます。

単語のつなぎに「__」「_」「-」を用いて区切り、これらを使い分けることでBlock、Element、Modifierそれぞれを定義します。

Block=かたまり

ヘッダー、フッター、本文などひとつのまとまりを指します。
Blockはどこでも配置することができますが、CSSにおいてはBlockの中でBlockを定義することができず、Blockは単体で存在して単体で機能することが絶対条件となります。

Element=要素

Block中の一つ一つが要素となります。
ナビゲーション自体がBlockであるならば、その中に存在するリストやリンクはElementとなります。

Modifier=修飾子

BlockやElementの見た目を決定する場合に利用します。OSSで解説した.btn-redがそれに該当します。ただBEMの場合は「__」で接続し、.btn__redという記述になります。
また、タイプの違う派生を作る場合はModiferを利用して派生させ、名前(key)と値(value)を「_」つなぎで記述します。

<article class="box"><!--Block-->
    <h1 class="logo--big">logo</h1><!--Element--Modifier-->
    <ul class="gnavi gnavi_type_none><!--Block Block_key_value-->
        <li class="gnavi__item"><!--Block__Element-->
        <li class="gnavi__item"><!--Block__Element-->
    </ul>
</article>

SMACSS

SMACSS

SMACSS

Scalable and Modular Architecture for CSSの略でスマックスと呼びます。一時期これを利用してコーディングしていました。
ベースは前述のOOCSS、BEMを採用し、CSSを構造化させることでメンテナンス性を向上させています。

BemはBlock、Element、Modifeirの3つで構成していましたが、SMACSSには5つの構成があります。

  • Base – ベース
  • Layout – レイアウト
  • Module – モジュール
  • State – ステート=状態
  • Theme – テーマ
Base

サイトのデフォルトスタイルを定義します。リセット関係や、サイト全体にかかかるフォントサイズ、ホバーの挙動などをここで定義します。

Layout

ヘッダー、フッター、サイドバー、ナビゲーションといったページのレイアウトに関するものを定義します。SMACSSは各ルールにそれぞれ接頭辞を付けるかIDを振ることでソースの可読性をあげています。

基本的にはクラスで定義を行いますが、Layoutのヘッダー、フッターなどページでひとつしかない物に対してはIDでの指定を許可しています。
クラスを用いる場合はクラスの最初にlayout-やl-を利用します。

.l-header {
    width: 100%;
    height: 80px;
}

Module

機能一つ一つを定義します。子を持つ場合は親のクラス名を接頭辞として記述します。

<ul class="gnavi">
    <li class="gnavi-item"></li>
    <li class="gnavi-item"></li>
</ul>

State

見た目などでは使わず、JavaScriptで操作するためのクラスを定義します。接頭辞はis-。

.is-active {
    display: block;
}

Theme

全体のスタイルを変更する場合に利用します。

.box {
    color: #fff;
}

この定義をthemeを利用してオーバーライド=上書きします。

.box {
    color: #f00;
}

SMACSSは上記5つの構成をそれぞれのスタイルシートを用意してそれぞれに定義します。
ですのでcssファイルは

  • base.css
  • layout.css
  • module.css
  • state.css
  • theme.css

という構成になります。

SMACSSについてはO3LOGさんで詳しく解説されてますので、そちらも合わせて読んでみてください。

http://03log.me/blog/2014-09-30-smacss.html

FLOCSS

FLOCSS

FLOCSS

上記のOOCSSやSMACSS、BEMなどのコンセプトを取り入れたCSS設計です。上記以外にSuitCSSも取り入れられています。
僕は最近コーディングをする時これを利用しています。

構成はFoundation、Layout、Objectで構成され、構造はそれぞれ下記となります。

Foundation

リセット系cssの読み込みや、そのサイトの基本となるスタイルを定義します。SMACSSでいうBaseと同じです。

Layout

SMACSSでいうLayoutと同じく、ヘッダー、フッター、コンテンツエリアなど、サイト全体の共通部分となるものを定義します。
こちらも定義する場合IDを採用することが推奨とされています。

Object

サイト内のビジュアルに関するものを定義します。Objectはここから更に

  • Component
  • Project
  • Utility

の3つに分けて定義していきます。

Component

再利用することができる最小単位のモジュールを定義します。
buttonやtitleなどがそれにあたり、どこで利用しても破綻しないレベルで定義しておくことが望ましいです。接頭辞は c-をつけます。

Project

一つの機能そのものを定義します。ProjectはComponentなどの集合体で構成され、グローバルナビや画像ギャラリーなどをここで定義します。接頭辞は p-をつけます。

Utility

ComponentやProjectを拡張したり装飾するための記述を行います。
例えば.boxをProjectで定義し、.boxの下に.boxをHTMLで記述した際、間に10pxの余白を儲ける場合

.u-mb10 {
    margin-bottom: 10px;
}
<div class="box u-mb10">ボックス</div>
<div class="box">ボックス</div>

と定義しておいて、これを活用することでComponentやProjectを破綻させること無く、見た目を拡張することが出来ます。
また、clearfixといったものもここで定義します。接頭辞は u-となります。
尚、FLOCSSでの単語つなぎは

.btn__element = 子要素
.btn--modifeir = 親要素のバージョン違い
.btn__element--modifeir = 子要素のバージョン違い

という書き方をします。

SASS、SCSS

ファイルのディレクトリ構造などの問題や、親のネーミングを子の接頭辞に使う問題などを簡素に解決するため、SASSやSCSSを利用する事はこれらの利便性をあげることとなり、より扱いやすくなります。

FLOCSSを例に上げると、ファイルの構造は以下のようになり

├── foundation
│   ├── _base.scss
│   └── _reset.scss
├── layout
│   ├── _footer.scss
│   ├── _header.scss
│   ├── _main.scss
│   └── _sidebar.scss
└── object
    ├── component
    │   ├── _button.scss
    │   ├── _dialog.scss
    │   ├── _grid.scss
    │   └── _media.scss
    ├── project
    │   ├── _articles.scss
    │   ├── _comments.scss
    │   ├── _gallery.scss
    │   └── _profile.scss
    └── utility
        ├── _align.scss
        ├── _clearfix.scss
        ├── _margin.scss
        ├── _position.scss
        ├── _size.scss
        └── _text.scss

これらをひとつの.scssファイルから以下のようにそれぞれのファイルを呼び出します。

// ==========================================================================
// Foundation
// ==========================================================================

@import "foundation/_reset";
@import "foundation/_base";

// ==========================================================================
// Layout
// ==========================================================================

@import "layout/_footer";
@import "layout/_header";
@import "layout/_main";
@import "layout/_sidebar";

// ==========================================================================
// Object
// ==========================================================================

// -----------------------------------------------------------------
// Component
// -----------------------------------------------------------------

@import "object/component/_button";
@import "object/component/_dialog";
@import "object/component/_grid";
@import "object/component/_media";

// -----------------------------------------------------------------
// Project
// -----------------------------------------------------------------

@import "object/project/_articles";
@import "object/project/_comments";
@import "object/project/_gallery";
@import "object/project/_profile";

// -----------------------------------------------------------------
// Utility
// -----------------------------------------------------------------

@import "object/utility/_align";
@import "object/utility/_clearfix";
@import "object/utility/_margin";
@import "object/utility/_position";
@import "object/utility/_size";
@import "object/utility/_text";

また、親要素から子要素への継承については

.box {
    &-sample {
    }
}

と定義することで、cssにコンパイル後

.box { }
.box-sample { }

という形で吐き出されます。

FLOCSSのドキュメントはいつもgithubにあがっているドキュメントを参照しているので、是非そちらを読んでもらうことをおすすめします。

FLOCSS Readme

コードリファクタリング

ここまでで解説したルールを採用することで、再利用のしやすさ、メンテナンス性は上がると思いますが、それでもコーディングが進むにつれそれが少しづつ破綻していきます。
そのときに重要なのは、定義した命名をそのままにして新たにコードを書くことを避け、一旦定義したクラス名を考え直し、命名をやり直すことです。

他にもComponentで定義した記述を実際にはUtilityで定義しておいたほうが良かったといったこともでてきます。その場合はソースを一度見つめ直し定義し直すことも重要です。

これらを置こうなうことをコードリファクタリングと呼ぶのですが、これを行っていくことでCSSの再利用のしやすさであったり、メンテナンス性が向上し、持続していくことが可能となります。

大切なことは、そのコードが使いやすいか?見やすいか?メンテナンスし易いか?を常に考えて書き進める事で、完成後時間が経過してもわかりやすく利用しやすくなっていることです。

最後に

コーディングは難しくないと昔言われてましたし、概念自体はそれほど難しくないです。
ただそれは書くこと自体が難しくないだけであって、分かりやすいCSSを維持するのは難しいです。より詳しく知りたい方は とろゆにさん さんが過去にWordBench Osakaで話したときのスライドが詳しいので是非読んでみてください。

https://speakerdeck.com/torounit/css-she-ji-kotohazime

お役に立てたらお願いします🙇

Kyashで送金する

Ad



Share