CSS設計の基本

#**はじめに**
[株式会社サイシード](http://sciseed.jp)のインターンシップにて、CSSを設計する際の規則をまとめました。

本稿で記述している設計規則に基づいての開発は、始めてから日が浅いです。
実際に使用していく中でさらに改善を進めて行く予定です。


設計規則を考えるに当たって**「[Web制作者のためのCSS設計の教科書](https://www.amazon.co.jp/Web%E5%88%B6%E4%BD%9C%E8%80%85%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AECSS%E8%A8%AD%E8%A8%88%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E3%83%A2%E3%83%80%E3%83%B3Web%E9%96%8B%E7%99%BA%E3%81%AB%E6%AC%A0%E3%81%8B%E3%81%9B%E3%81%AA%E3%81%84%E3%80%8C%E4%BF%AE%E6%AD%A3%E3%81%97%E3%82%84%E3%81%99%E3%81%84CSS%E3%80%8D%E3%81%AE%E8%A8%AD%E8%A8%88%E6%89%8B%E6%B3%95-%E8%B0%B7-%E6%8B%93%E6%A8%B9/dp/4844336355/ref=pd_sim_14_14?_encoding=UTF8&psc=1&refRID=2GA9KPPVTQV58CREHT4G)」**を参考にさせて頂きました。
より詳しくCSSの設計方法について学びたい方はぜひ手にとってみてください。

本設計規則は、上記の書籍で紹介されている中でも特に**BEM**と**FLOCSS**に影響を受けています。
本稿が少しでもみなさまの参考になれば幸いです。
　
###**スタイルの役割の分類**
####**１．構造**
形や大きさなどを指定する。
家で言うところの骨格。

例：　`width`, `height`, `border`, `padding`, `margin`, `font-size`　など
　
####**２．見た目**
色や太さなどを指定する。
家で言うところの外見。

例：　`color`, `border-color`, `background-color`　など
　
###**CSSの性質**
####**１．カスケーディング**
**CSS（Cascading Style Sheets、カスケーディングスタイルシート）**の名前の由来で、
カスケーディングとは **何段も連なった小さな滝**という意味。
あるHTML要素に対して複数のスタイルが適用され得る時に、どのスタイルを適用するか
決めるための仕組み。
適用される得るスタイルの強さは以下のように決められる。

######**カスケーディングの３大原則**
>１．ウェブブラウザによって与えられたスタイルよりもウェブブラウザのユーザーによって
与えられたスタイルのほうが強く、ウェブサイトのスタイルはそれよりも強い。

>２．宣言に対応するセレクタによる絞り込みが強い（**詳細度**が高い）ほど，すなわち，
特殊性の高いセレクタを持っているほど強い。

>３．最後まで強さがつけられないときは，後に書かれたスタイルほど強い。

　
####**２．一部のプロパティで親要素のプロパティが継承される**
　プロパティには、親要素に指定した値が子要素に継承されるものと継承されないものがあり、
　文字色や文字サイズに関するプロパティなどは継承される。
　一方、`border`、`margin`、`padding`、背景画像などは継承されない。
　
####**３．CSSは右から左に読み込まれる**
　数の多いものが右にある（数の多い子孫セレクタを記述する）と、
　それだけ多くの要素を探し出すことになり、パフォーマンスが下がる。
　そのため、できる限り下のような子孫セレクタ用いずに、

```css:CSS
　# 例
　div#wrapper div#main ul.list li {}
```

　上の例の`li`にclassを振って以下のようにするほうが良い。

```css:CSS
　# 例
　.item-list {}
```

　
####**４．idやclassには要素名をつけないほうが高速**
　`div#foo {}`や`li.item {}`などとはせずに`#foo {}`や`.item {}`などのようにする。
　

#**CSS設計規則**
###**基本**
####**１．構造化は[FLOCSS](https://github.com/hiloki/flocss)を参考にする**
　レイヤーごとに詳細度に関するルールを定義することで、カスケーディングを管理するCSSの設計手法。
　**[FLOCSS](https://github.com/hiloki/flocss)**は**Foundation**、**Layout**、**Object**の3つのレイヤーから構成され、
　**Object**レイヤーはさらに**Component**、**Project**、**Utility**の3つの子レイヤーに分けられる。　
　同じような設計手法に、**OOCSS**や**SMACSS**などがある。
　
####**２．命名規則はBEMを参考にする**
　構造化と命名規則との違いがあいまいになりやすいので気をつける。
　構造化ではいくつかのレイヤーを考えるが、
　どのレイヤーであっても命名規則には**BEM**の考え方を利用する。
　
####**３．CSSのセレクタにidは使わない**
　idを用いると詳細度が高くなるため、スタイルの上書きがしにくくなり、目的のスタイルが
　適用できなくなるため。
　idはCSS以外（javascriptなど）で用いるようにすることで、役割の違いがわかりやすくなる。
　
####**４．単語の省略はなるべくしない**
　他の開発が見たときにでも、その意味がわかるようにして、誤解を招かないようにする。
　
####**５．マルチクラスを用いる**
　役割を分けたclassを用意し、それら複数のclassをHTML要素のclassに与え、目的のスタイルを適用する。
　ただし、`@extend`や`@mixin`など（SCSSの機能）も活用して、付与するclassが多くなりすぎないようにする。
　
####**６．構造と見た目とは明確に分ける**
　構造のスタイルを指定するclassと見た目のスタイルを指定するclassは分ける。
　構造のスタイルを指定するclassと見た目のスタイルを指定するclassを組み合わせて適用する
　ことによって、目的のスタイルを適用する。
　
####**７．HTML構造に依存しないCSSを書く**
　HTMLのデフォルトスタイルを初期化する場合以外で、HTML要素をセレクタに用いない。
　
####**８．HTMLのタグによるスタイル適用はなるべくしない**
　基本的に`div`タグを用いて、その`div`タグに`class`を付与することでスタイルを適用する。
　`small`タグや`h`タグ、`strong`タグなど、フォントサイズやフォントスタイルを
　変化させるHTML要素は使わない。
　
####**９．基本的にimportant!は使わない**
　ただし、**FLOCSS**の**Utilityレイヤー**などでは許容する。
　
####**１０．上の親要素であるほど適用するスタイルは必要最小限にとどめる**
　一部のプロパティは子要素に継承されるため。
　
####**１１．できる限りjavascriptを用いない**
　レスポンシブルデザインやモーダルもcssで実装するようにする。
　誤動作を防げるだけでなく、実行速度の向上も見込める。
　
####**１２．インデントはスペース4つ分**
　スペースが少なすぎると、インデントがわかりにくいし、多すぎるとエディタ上で折れ曲がってしまい
　見にくくなる。
　
####**１３．再利用は基本的に考えない**
　ただし、基準として、3回程度同じ構造が出てきたら、それらを共通化させてもよい。
　
####**１４．セマンティックなclass名をつける**
　見た目や振る舞いからではなく、目的や役割に基づいて名前をつける。

```html:悪い例（見た目や振る舞いでclass名をつけている）
　<div class="red pull-left"></div>
　<div class="grid row"></div>
　<div class="col-xs-4"></div>
```

```html:良い例（目的や役割に基づいてclass名をつけている）
　<div class="header"></div>
　<div class="basket"></div>
　<div class="product"></div>
```

　
####**１５．CSSフレームワークを用いる**
　BootstrapなどのCSSフレームワークを用いる時は、まずはそこで提供されているスタイルだけを
　用いて、UIを作る。
　その後に、足りないところを独自のスタイルを適用することで、より細かいUIを作っていくようにする。
　
####**１６．便利なツール**
**（１）[OneClickCSS](https://css.miugle.info/)**
　HTMLを入力またはコピペしてやると、それに応じてセレクタを生成してくれる。

**（２）Emment**
　HTML構造を効率よく生成できるようになる。
######**参考：**
>１．[Emmetでマークアップを効率化しよう](http://www.granfairs.com/blog/staff/efficiency-by-emmet-01)
>２．[EmmetをSublime Text 3で使ってみよう](http://catcher-in-the-tech.net/2057/)
>３．[cheat sheet](https://docs.emmet.io/cheat-sheet/)

　
###**構造**

####**１．brタグなどで要素間の隙間を調整してはいけない**
　`margin`や`padding`などで調整する。
　
####**２．マージンについて**
　要素間の間隔の指定は、あわせるようにする。
　そうしなければ、相殺が起き、期待したデザインにならないことがある。
　
**（１）上下の要素間の隙間を空ける時は、下にだけ適用する**
　つまり、`margin-bottom`だけを用いる。

**（２）左右の要素間の隙間を空ける時は、右にだけ適用する**
　つまり、`margin-right`だけを用いる。
　
**（３）上下の要素を重ねる時は、上にだけ適用する**
　つまり、`margin-top`でネガティブマージン（マイナスのマージン）を用いる。

**（４）左右の要素を重ねる時は、左にだけ適用する**
　つまり、`margin-left`でネガティブマージン（マイナスのマージン）を用いる。
　
###**見た目**
####**１．サイズについて**
　基本的には、`em`か`%`を用いる。

　レイアウトやボックスなど大きい範囲のサイズ指定（特に、`width`）は、`%`を用い、
　文字の大きさやちょっとした隙間などは`em`を用いる。
　基本的には`em`を用いることになる。
　迷ったら、`em`。

#####**１－１．emと%の相対指定の基準となる相手について**
**（１）font-size（フォントサイズ）**
　　`em`でも`%`でも**親要素のフォントサイズ**が基準。
　　もっと正確に言うと、親から継承している自分自身のフォントサイズが基準。
　
**（２）line-height（行の高さ）**
　　`em`でも`%`でも**自分自身のフォントサイズ**が基準。
　　自分自身に`font-size`を指定してる場合は、そのサイズが基準。
　　`font-size`を指定していなければ、親のフォントサイズを継承したときの自分自身の
　　フォントサイズが基準。
　
**（３）margin 、padding 、width 、height（要素間の間隔や要素の大きさ）**
　　`em`なら**自分自身のフォントサイズ**が基準。
　　`%`だと**親要素のフォントサイズ**が基準。
　
#####**１－２．%指定の注意点**
　%指定すると、親をたどっていって、絶対値がわかるところからの相対指定となるので、
　最悪、html要素までさかのぼり、その大きさからの相対指定となることで、予想外の大きさに
　なることがある。
　
#####**１－３．フォントサイズの基準**
　一番最初に基準になるフォントサイズは、`<html>`要素のフォントサイズ。
　PCブラウザでの`<html>`要素のデフォルトのフォントサイズは、`font-size : 16px` 。
　どのPCブラウザでもこれがデフォルト。
　ちなみに、行高さのデフォルトは、`line-height : 24px`。
　24pxはつまり、1.5em（デフォルトのフォントサイズの1.5倍）。
　
#####**１－４．em、%、pxの使いどころ**
**（１）em を使うところ**
　　フォントサイズを基準にしたサイズ。
　　例えば、2emだと基準の文字サイズに対して、2倍の大きさになる。

　　フォントサイズが変わると影響を受ける部分、文字の大きさに対するサイズが
　　重要なところで用いる。

######**　emを用いる具体例：**
>**・font-sizeや line-height（行の高さ）はem**
　PCブラウザのデフォルトの`16px`を基準に、まず`<body>`の`font-size`を`em`で決める。
　これが本文の文字サイズになる。
　これをもとに、見出しはでっかく、コラムの本文は小さくなどと、
　文字の大きさのバランスを`em`で設計していく。

>**・line-heightもemで指定**
　ボックスの`padding`や`margin`も、`font-size`の変更によって調整が必要になりそうな　　
　`padding`や`margin`は`em`で相対指定する。
　フォントサイズを変更したら自動変更してくれるから。
　`%`は使わない。

　
**（２）%を使うところ**
　　ボックスのサイズ指定（特に、`width`）でよく使う。
　　ページ全体に対してどれくらいの大きさにするかが重要なところで用いる。
　　例えば、親要素に対して左右いっぱいにしたいボックスは`width:100%`で指定。
　　レスポンシブレイアウト（ウィンドウサイズによってサイトの幅が可変する）で`%`をよく使う。
　
**（３）px を使うところ**
　　フォントサイズ、ボックスサイズに関係なく、サイズを固定したいところで用いる。
######**　　pxを用いる具体例：**
>**・border-width（border の幅）**
　もっとも良く使う。
>**・border-radius（ブロック要素の角丸）**
　正円や楕円形の場合以外は`px`で指定
>**・サイトのメインボックスの幅**
　メインボックスの幅を`px`で固定してしまい、端末ごとにメディアクエリで幅を切り替える。
>**・デザイン上、サイズを固定したい部分も`px`で指定**
　グローバルナビや、\<h1>、\<h2> を、背景画像と一緒に作り込むような場合などは、
　ガッチリ`px`で固定する。
　この場合も、メディアクエリで切り替えが必要。

　
####**２．見た目の変更**
#####**２－１．State**
　　状態を表す。
　　Stateとして作成したセレクタ単体に対しては、スタイルを適用してはならない。
　　他のclassと組み合わせて使う。
　　
　　接頭辞として`is-`をつける。
　　
######**　例：ボタンが押された状態になっているかどうか**

```html:HTML：例
<div class="button button-primary is-active">
```

```css:CSS：例
.button-primary.is-active {・・・}
```
　　　　　
#####**２－２．Theme**
　　Stateのような小さい範囲でのスタイル変更ではなく、ページ全体のテーマなどより大きい範囲での
　　スタイル変更時に用いる。
　　
　　接頭辞として、**`t-`**をつける。
　
###**命名規則**
####**id名、class名に使用する接頭辞一覧**

|接頭辞 |用途                                      |使用例
|:----:|:----------------------------------------:|:----------------------------:|
|js-   |javascriptの対象となる要素につける          |`id="js-move-icon"` 　         |
|l-    |Layoutレイヤー（[FLOCSS](https://github.com/hiloki/flocss)）の要素につける         |`class="l-header"`            | 
|c-    |Componentレイヤー（[FLOCSS](https://github.com/hiloki/flocss)）の要素につける      |`class="c-btn"`               |
|p-    |Projectレイヤー（[FLOCSS](https://github.com/hiloki/flocss)）の要素につける        |`class="p-btn--primary"`      |
|u-    |Utilityレイヤー（[FLOCSS](https://github.com/hiloki/flocss)）の要素につける        |`class="u-clearfix"`          |
|t-    |比較的広い範囲の状態変更を伴う要素につける    |`class="t-blue-sky"`          |
|is-   |比較的狭い範囲の状態変更を伴う要素につける    |`class="is-active"`           |
|a-    |ページ内リンクのアンカー要素につける          |`id="a-page-top"`             |
|m-    |modal要素につける（※Bootstrap使用時など）   |`id="m-edit-prfile"`          |
|cl-   |collapse要素につける（※Bootstrap使用時など）|`id="cl-tag-options"`         |
　
####**id名、class名のつなぎ方**
#####**１．-（ハイフン）**
名前の区切り。

例：　`class="p-edit-modal"`
#####**２．--（ハイフン２つ）**
**BEM**の命名規則の**Modifier**（後述）で用いる。

例：　`class="p-edit-modal--primary"`
#####**３．__（アンダースコア２つ）**
**BEM**の命名規則の**Element**（後述）で用いる。

例：　`class="p-edit-modal__header"`
　
####**BEMについて**　
**BEM**では、次の3つの要素を考える。
#####**１．Block**
　最も基本的な要素。
　あるUIを作る時の一番上の親要素を**Block**とする。

　**Block**は単独で機能するようにし、他の**Block**に依存させない。

　SCSSファイルとして分割する時は、この要素の名前と同じ名前にすると良い。
　そうすることで、ネームスペースの重複が起きないようにする。

　仮にネストされていたとしても、親の構造に依存しない構造が入る時は、
　新しい**Block**を考える（例としては、下の"例：モーダル"の`p-panel`）。

######**　例：モーダル**
　以下の例における`p-modal`、`p-panel`が**Block**にあたる。

```html:HTML：例
<div class="p-modal p-modal--primary">
  <div class="p-modal__header">
  ・・・
  </div>
  <div class="p-modal__body">
　　<div class="p-panel">
　　　<div class="p-panel__title">
　　　・・・
　　　</div>
　　　<div class="p-panel__body">
　　　・・・
　　　</div>
　　</div>
  </div>
  <div class="p-modal__footer">
　・・・  
  </div>
</div>
```

　
#####**２．Element**
　**Block**を構成する要素。
　**Block**の中の一つ一つの要素が**Element**となる。
　**Element**は、**Block**を起点として、**_（アンダースコア）２つ**で役割となる名前をつなげる。
　色や大きさなど見た目を表すものを含んではならず、あくまで**構造**的なもので、
　**Block**に自然と含まれるものにする。
　
　ElementにElementをつなげることは極力避ける。
　HTMLの構造でElementを考えるのではなく、Blockに対するElementとModifierの関係性を示すようにする。
　例えば、ElementのさらにElementであるときは、subやchildといった名前によってBlockとの関係性を示す。

######**　例：モーダル**
　以下の例における`p-modal__header`、`p-modal__body`、`p-modal__footer`、
　`p-　　modal__child-form`が**Element**にあたる。

```html:HTML：例
<div class="p-modal p-modal--primary">
  <div class="p-modal__header">
　・・・
  </div>
  <div class="p-modal__body">
　　<div class="p-modal__child-form">
  　・・・
　　</div>
  </div>
  <div class="p-modal__footer">
　・・・  
  </div>
</div>
```

　
#####**３．Modifier**
　**Block**または**Element**のバリエーション違いの要素。
　色や大きさの違いなど**見た目**を含む。
　**Modifier**は、**Block**あるいは**Element**を起点として、**-（ハイフン）２つ**で
　役割となる名前をつなげる。
　**Element**は構造、**Modifier**は見た目と考えておけばよいが、あいまいなものもある。
　あいまいなものは、バリエーションの違いとして適切かどうかで判断する。

######**　例：モーダル**
　以下の例における`p-modal--primary`、`p-modal__header--default`が**Modifier**にあたる。

```html:HTML：例
<div class="p-modal p-modal--primary">
  <div class="p-modal__header p-modal__header--default">
  ・・・
  </div>
  <div class="p-modal__body">
　・・・
  </div>
  <div class="p-modal__footer">
　・・・  
  </div>
</div>
```
　　　
#####**※ ElementとModifierの覚え方**
　次のようなイメージを持っておくと覚えやすい。
　**Element**は**_（アンダースコア）２つ**で、**Block**に対して一段下がっている
　つまり**親子関係**であるというイメージ。
　**Modifier**は**-（ハイフン）２つ**で、バリエーション違いとして**Block**や**Element**に対して
　**対等の関係**にあるというイメージ。
　
#**まとめ**
この設計規則でどこまで通用するかは、今後の運用次第なところはありますが、
とりあえずの設計規則を決めました。

今のところの不安要素には以下のようなものがあります。

・**BEM**の考え方を使うことでclass名をつけやすくなる一方で、class名が長くなってしまう。

・ある構造をどのレイヤーに含めるか、またその構造の中の要素がそれぞれ**BEM**のどの要素に該当するか、
　といったことはあくまで主観的である。

こうした問題をどのように解決するかが、本稿の設計規則を用いる上での課題となってきそうです。
　
　
#**参照**
１．[カスケーディングの基礎](http://www.tg.rim.or.jp/~hexane/ach/lbcs/lbcs2-05.htm
http://d.hatena.ne.jp/amachang/20080407/1207594307)
２．[スタイルの継承](http://www.htmq.com/csskihon/008.shtml)
３．[ほんっとにはじめての HTML5 と CSS3](http://honttoni.blog74.fc2.com/blog-entry-221.html)
４．[hiloki/flocss](https://github.com/hiloki/flocss)
５．[CSSの設計 – FLOCSSをベースにしたファイルの構成と命名規則を考える](http://www.tam-tam.co.jp/tipsnote/html_css/post10205.html)
６．[manabuyasuda/styleguide](https://github.com/manabuyasuda/styleguide/blob/master/css-styleguide.md)
　
　
**最後に**
オリジナル音楽の投稿配信サービス[Micstack](https://www.micstack.com/)を運営しています。
よろしければご利用ください。