Engineering

Dec 10, 2017

CSSスタイルガイドのSMACSSを勉強してみたまとめ

SMACSSって知ってますか?

css初心者レベルからぬけだしたいのであれは知っておいていた方がいいcss設計に関する知識です。

私もこないだまでは名前しか知らない程度だったの他人のことを言える立場ではないのですが、これを勉強すればcssをさらに深くしれるなと思い勉強してみました。

参考にしたサイト

今回は公式サイトのドキュメントをダウンロードして読み込みました。

130ページ程度の電子書籍で(無料です)短いのでぜひ読んでみることをオススメします。

https://smacss.com/ja

本の流れとしては、最初にそれぞれのレイヤーのルールを紹介した後に、テンプレートエンジンやSASSなどのプリプロセッサ、パフォーマンスなどSMACSSに関連したトピックについて記載されています。

本自体は元々英語で書かれているもののようなのですが、訳が若干読みづらいかもしれません。 何はともあれ、しっかりと理解したい方は一度読んでみてみると良いと思います。

SMACSSの概要

SMACSSは、CSS設計の際に用いるアーキテクチャのルールやパターンの事です。 規約がものすごい厳密という訳でもなさそうですのでスタイルガイドと言ってしまって良いと思います。

CSS設計に関するアーキテクチャとしては他にも OOCSS, BEM などがありSMACSSもその一つになります。

このアーキテクチャの目指すところは

よりセマンティックで、拡張性が高く変更に強い CSSです。

この場合の変更に強いとは

HTMLへの依存性が低く、HTMLの変更がCSSに影響を与えない

ようなことを言います。

セマンティックであるとは、見た目や振る舞いではなく、目的や意図がわかるということです。

それを実現する方法がSMACSSとして提唱されているのですが、基本的な思想として

CSSの役割を

  • ベース
  • レイアウト
  • モジュール
  • ステート(状態)
  • テーマ

の5つのカテゴリに分けて管理します。

名前でなんとなく想像はつくと思いますが、 簡単に説明すると

ベース

bodyタグやhtmlタグなどデフォルトでのスタイル定義。サイトの背景食や文字サイズ、フォントスタイルなども含みます。

レイアウト

名前の通りレイアウトを定義する層です。ただし、ボタンや吹き出し、カルーセルなどの部品はここでは定義しません。

モジュール

ボタン、カルーセル、アコーディオンなどアプリケーションの中の部品を定義します。

ステート

モジュールやレイアウトの状態を定義しています。表示・非表示やアコーディオンが畳んだ状態か開いた状態かなどの部分です。

テーマ

これは常に必須のレイヤーではないそうなのですが、デザインの表層の部分が定義されます。サイト全体の色やフォントをデフォルトのものと切り替えるというような用途に使われるようです。

となります。

これらのカテゴリは、 CSSを書く際にどこのカテゴリのコードを書くか意識する事で、複雑な絡み合ったコードを避けるためにあります。カテゴリをはっきりと分けることで、コードを共通化させシンプルでメンテナンスしやすいコードが実現できます。 本では、それぞれのルールに対して細かな解説があるのでまとめてみました。

ベース

スタイル例:

body, form {
    margin: 0;
    padding: 0;
}

a {
    color: #039;
}

a:hover {
    color: #03F;
}

対象:

bodyタグ、htmlタグ、aタグ、h1タグ..

命名規則:

要素セレクタでのスタイル

説明:

ベースのカテゴリではクラスセレクタやIDセレクタを使わず、要素セレクタでそれぞれの要素のデフォルトの状態を定義します。 ベーススタイルには見出しのサイズ、デフォルトリンクスタイル、デフォルトフォントスタイルそしてbodyの背景が含まれます。

要は、bodyタグ、aタグ、h1タグ、h2タグなどのデフォルトのスタイルを定義する部分になります。他のカテゴリでは、html構造への依存を避けるため極力要素セレクタ( h2指定で直接スタイル)でスタイルを定義したりしないのですが、ベースは例外です。

それぞれの要素のデフォルトのスタイルを定義する必要があるので要素セレクタにスタイルを指定します。

リセットCSSやnormalize CSSはこの層になりますが、本ではリセットCSSは積極的に使用しましょうと言う感じではありませんでした。 リセットCSSは一度デフォルトのスタイルを解除して、再度スタイルを定義し直すことになるので読み込むコードが増えますと言うところが懸念点としてあるようです。

レイアウト

スタイル例:

#header, #article, #footer {
    width: 960px;
    margin: auto;
}

#article {
    border: solid #CCC;
    border-width: 1px 0 0;
}

対象:

ヘッダー、フッター、サイドバーなどページを分割する要素

命名規則:

原則IDセレクタ一つでスタイル、クラスセレクタの場合はl-やlayout-のようなprefix(接頭辞)をつける。

説明:

名前の通りレイアウトを定めるカテゴリで、一ページをどのようなセクションに分割するかという部分について定義されます。

ヘッダーやフッターなどの主要なレイアウトはIDタグで定義されることが多いが、それはページ内で本当に繰り返し使用されないことを確認した上でそうすべきで、繰り返される場合はクラスセレクタでスタイルが良いとされています。

これについては、伝統的にそうされてきたかのような記述があるのですがイマイチIDセレクタで指定する必要性があまりわからないですね。。何か深い理由があるのでしょうか。主要なレイアウトとして目立たせる為にIDセレクタとしてスタイルすると言うのはまあわかる気もしますが。

また、基本的にはレイアウトは一つのセレクタで定義されますが、ユーザの権限ごとにレイアウトを変えたいなどの場合もあるのでそう言う場合は下のような複数セレクタでスタイルすることあります。

.l-admin #header { hoge: foo }

命名規則として他のカテゴリと区別する為に、クラスセレクタで指定する場合は先頭にl-やlayout-のようにレイアウトのスタイルであることをわかりやすくする規則があります。

モジュール

スタイル例:

.carousel  > h2 {
    padding: 5px;
}

.carousel  span {
    padding: 5px;
}

対象:

カルーセル、アコーディオンなどなど

命名規則:

IDや要素セレクタを避け、クラスセレクタのみを利用。モジュール内の要素は子・子孫セレクタで指定。

説明:

モジュールはカルセール、アコーディオンなどのスタイルを行うカテゴリです。

命名規則にあるように要素セレクタは極力避ける必要があります。h1,h2など見出しタグはセマンティック性が一定程度あるので、(タグをみただけで見出しなんだなと言う意図がわかる)良いですが、divやspanなど一見して意図がわかりづらいものはクラスセレクタを使ってその意図を補足してやるのが良いです。

<div class="item-list">
     <div class="item">Scissors</div>
     <div class="item">Hammer</div>
     <div class="item">Ruler</div>
</div>

クラスセレクタを使うとスタイルの意図がわかりやすくセマンティック性が保たれるので、クラスセレクタの利用が推奨されています。

また、サブクラスのモジュールを定義する際に場所による制約をスタイルするのは避ける必要があります。

これはあらかじめデフォルトのボタンをスタイルした後に、サイドバーに少しスタイルの違うボタンを設置する場合に、

.pod {
    width: 100%;
}
.pod input[type=text] {
    width: 50%;
}
#sidebar .pod input[type=text] {
    width: 100%;
}

のようにサイドバー内のボタンとして指定するのではなく、

.pod {
    width: 100%;
}
.pod input[type=text] {
    width: 50%;
}
.pod-constrained input[type=text] {
    width: 100%;
}

このようにスタイルして、htmlの要素には

class="btn btn-constrained"

のように指定します。

sidebarのような指定の仕方でも一見問題ないように思えますが、 この後にサイドバーやそれ以外にも配置可能ななモジュールを作る場合にベースのpodのスタイルと、 サイドバー内のスタイル両方のスタイルを上書きしないといけなくなってしまいます。

レイアウトなどの親要素に依存するモジュールを作成する場合は注意が必要です。 場所に依存する(サイドバーの中ののような)スタイルすることを極力されるのが良さそうです。

ステート

スタイル例:

.is-hidden{
    display:none;
}

対象:

モジュール等の状態の指定。表示・非表示。メニューが開いているか閉じているか。

命名規則:

  • 1つのクラスセレクタのみ。
  • 特定のモジュールについてのみ適用される状態であればモジュール名を含める。
  • 利用に注意しながら!importantの利用可

ステートはモジュールの状態を示し、表示・非表示などをスタイルする。

サブモジュールと役割上の類似点があり、混乱を招きがちだが、

1. 状態スタイルはレイアウトやモジュールに割り当てることができ
2. 状態スタイルはJavaScriptに依存するという意味を持つ

といった違いがあります。

2つめがわかりやすくサブモジュールクラスは、htmlがレンダリングされた際に描画されているもので、ステートはユーザのアクションや経過時間などに応じてクラスが付加されたり削除されたりするものです。

テーマ

スタイル例:

.theme-border {
    border-color: purple;
}

.theme-background {
    background: linear-gradient( ... );
}

対象:

テーマでは色やアプリケーションやサイトが持つルック&フィールを定義

命名規則:

テーマの規模によりtheme-などのprefixをつける。

テーマではアプリケーションが持っている他のカテゴリで定義されたデフォルトのボーダーの色などを上書きする。

想定される用途としてユーザー側にいくつかのテーマを決めさせてサイトの雰囲気をユーザ好みにカスタマイズできるようにする場合などがあります。

まとめ

今回は、簡単なカテゴリのルールだけまとめました。電子書籍の中には他の項目についての記載もありますが、まとめるのも大変ですし読み切るのも大変なので紹介はここまでとさせて頂きます。

冒頭でも書きましたが、130ページ程度の本なので自身でも読んでみると良いかと思います。

  • 状態の変更について
  • 適応性の深度
  • セレクタパフォーマンス

らへんの部分は結構参考になると思います。

本は読むだけでは意味がないのでお次は、実際にSMACSSを意識しながら簡単なページをコーディングしてみたいですね。ちゃんとできたらその様子もアップしたいです。

では

関連記事

記事検索

気になるサイト内の記事を検索する

プロフィール

バンクーバー在住のフルスタックエンジニアです。React, Ruby on Rails, Go などでお仕事しています。職場がトロントなので日本、トロント、バンクーバーの三つの時天空を操って生活しています。

プロモーション

Index

  • 参考にしたサイト
  • SMACSSの概要
  • ベース
  • レイアウト
  • モジュール
  • ステート
  • テーマ
  • まとめ