Help us understand the problem. What is going on with this article?

CSS設計の基本

More than 1 year has passed since last update.

はじめに

株式会社サイシードのインターンシップにて、CSSを設計する際の規則をまとめました。

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

設計規則を考えるに当たってWeb制作者のためのCSS設計の教科書を参考にさせて頂きました。
より詳しくCSSの設計方法について学びたい方はぜひ手にとってみてください。

本設計規則は、上記の書籍で紹介されている中でも特にBEMFLOCSSに影響を受けています。
本稿が少しでもみなさまの参考になれば幸いです。
 

スタイルの役割の分類

1.構造

形や大きさなどを指定する。
家で言うところの骨格。

例: width, height, border, padding, margin, font-size など
 

2.見た目

色や太さなどを指定する。
家で言うところの外見。

例: color, border-color, background-color など
 

CSSの性質

1.カスケーディング

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

カスケーディングの3大原則

1.ウェブブラウザによって与えられたスタイルよりもウェブブラウザのユーザーによって
与えられたスタイルのほうが強く、ウェブサイトのスタイルはそれよりも強い。

2.宣言に対応するセレクタによる絞り込みが強い(詳細度が高い)ほど,すなわち,
特殊性の高いセレクタを持っているほど強い。

3.最後まで強さがつけられないときは,後に書かれたスタイルほど強い。

 

2.一部のプロパティで親要素のプロパティが継承される

 プロパティには、親要素に指定した値が子要素に継承されるものと継承されないものがあり、
 文字色や文字サイズに関するプロパティなどは継承される。
 一方、bordermarginpadding、背景画像などは継承されない。
 

3.CSSは右から左に読み込まれる

 数の多いものが右にある(数の多い子孫セレクタを記述する)と、
 それだけ多くの要素を探し出すことになり、パフォーマンスが下がる。
 そのため、できる限り下のような子孫セレクタ用いずに、

CSS
 # 
 div#wrapper div#main ul.list li {}

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

CSS
 # 
 .item-list {}

 

4.idやclassには要素名をつけないほうが高速

 div#foo {}li.item {}などとはせずに#foo {}.item {}などのようにする。
 

CSS設計規則

基本

1.構造化はFLOCSSを参考にする

 レイヤーごとに詳細度に関するルールを定義することで、カスケーディングを管理するCSSの設計手法。
 FLOCSSFoundationLayoutObjectの3つのレイヤーから構成され、
 ObjectレイヤーはさらにComponentProjectUtilityの3つの子レイヤーに分けられる。 
 同じような設計手法に、OOCSSSMACSSなどがある。
 

2.命名規則はBEMを参考にする

 構造化と命名規則との違いがあいまいになりやすいので気をつける。
 構造化ではいくつかのレイヤーを考えるが、
 どのレイヤーであっても命名規則にはBEMの考え方を利用する。
 

3.CSSのセレクタにidは使わない

 idを用いると詳細度が高くなるため、スタイルの上書きがしにくくなり、目的のスタイルが
 適用できなくなるため。
 idはCSS以外(javascriptなど)で用いるようにすることで、役割の違いがわかりやすくなる。
 

4.単語の省略はなるべくしない

 他の開発が見たときにでも、その意味がわかるようにして、誤解を招かないようにする。
 

5.マルチクラスを用いる

 役割を分けたclassを用意し、それら複数のclassをHTML要素のclassに与え、目的のスタイルを適用する。
 ただし、@extend@mixinなど(SCSSの機能)も活用して、付与するclassが多くなりすぎないようにする。
 

6.構造と見た目とは明確に分ける

 構造のスタイルを指定するclassと見た目のスタイルを指定するclassは分ける。
 構造のスタイルを指定するclassと見た目のスタイルを指定するclassを組み合わせて適用する
 ことによって、目的のスタイルを適用する。
 

7.HTML構造に依存しないCSSを書く

 HTMLのデフォルトスタイルを初期化する場合以外で、HTML要素をセレクタに用いない。
 

8.HTMLのタグによるスタイル適用はなるべくしない

 基本的にdivタグを用いて、そのdivタグにclassを付与することでスタイルを適用する。
 smallタグやhタグ、strongタグなど、フォントサイズやフォントスタイルを
 変化させるHTML要素は使わない。
 

9.基本的にimportant!は使わない

 ただし、FLOCSSUtilityレイヤーなどでは許容する。
 

10.上の親要素であるほど適用するスタイルは必要最小限にとどめる

 一部のプロパティは子要素に継承されるため。
 

11.できる限りjavascriptを用いない

 レスポンシブルデザインやモーダルもcssで実装するようにする。
 誤動作を防げるだけでなく、実行速度の向上も見込める。
 

12.インデントはスペース4つ分

 スペースが少なすぎると、インデントがわかりにくいし、多すぎるとエディタ上で折れ曲がってしまい
 見にくくなる。
 

13.再利用は基本的に考えない

 ただし、基準として、3回程度同じ構造が出てきたら、それらを共通化させてもよい。
 

14.セマンティックなclass名をつける

 見た目や振る舞いからではなく、目的や役割に基づいて名前をつける。

悪い例(見た目や振る舞いでclass名をつけている)
 <div class="red pull-left"></div>
 <div class="grid row"></div>
 <div class="col-xs-4"></div>
良い例(目的や役割に基づいてclass名をつけている)
 <div class="header"></div>
 <div class="basket"></div>
 <div class="product"></div>

 

15.CSSフレームワークを用いる

 BootstrapなどのCSSフレームワークを用いる時は、まずはそこで提供されているスタイルだけを
 用いて、UIを作る。
 その後に、足りないところを独自のスタイルを適用することで、より細かいUIを作っていくようにする。
 

16.便利なツール

(1)OneClickCSS
 HTMLを入力またはコピペしてやると、それに応じてセレクタを生成してくれる。

(2)Emment
 HTML構造を効率よく生成できるようになる。

参考:

1.Emmetでマークアップを効率化しよう
2.EmmetをSublime Text 3で使ってみよう
3.cheat sheet

 

構造

1.brタグなどで要素間の隙間を調整してはいけない

 marginpaddingなどで調整する。
 

2.マージンについて

 要素間の間隔の指定は、あわせるようにする。
 そうしなければ、相殺が起き、期待したデザインにならないことがある。
 
(1)上下の要素間の隙間を空ける時は、下にだけ適用する
 つまり、margin-bottomだけを用いる。

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

(4)左右の要素を重ねる時は、左にだけ適用する
 つまり、margin-leftでネガティブマージン(マイナスのマージン)を用いる。
 

見た目

1.サイズについて

 基本的には、em%を用いる。

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

1-1.emと%の相対指定の基準となる相手について

(1)font-size(フォントサイズ)
  emでも%でも親要素のフォントサイズが基準。
  もっと正確に言うと、親から継承している自分自身のフォントサイズが基準。
 
(2)line-height(行の高さ)
  emでも%でも自分自身のフォントサイズが基準。
  自分自身にfont-sizeを指定してる場合は、そのサイズが基準。
  font-sizeを指定していなければ、親のフォントサイズを継承したときの自分自身の
  フォントサイズが基準。
 
(3)margin 、padding 、width 、height(要素間の間隔や要素の大きさ)
  emなら自分自身のフォントサイズが基準。
  %だと親要素のフォントサイズが基準。
 

1-2.%指定の注意点

 %指定すると、親をたどっていって、絶対値がわかるところからの相対指定となるので、
 最悪、html要素までさかのぼり、その大きさからの相対指定となることで、予想外の大きさに
 なることがある。
 

1-3.フォントサイズの基準

 一番最初に基準になるフォントサイズは、<html>要素のフォントサイズ。
 PCブラウザでの<html>要素のデフォルトのフォントサイズは、font-size : 16px
 どのPCブラウザでもこれがデフォルト。
 ちなみに、行高さのデフォルトは、line-height : 24px
 24pxはつまり、1.5em(デフォルトのフォントサイズの1.5倍)。
 

1-4.em、%、pxの使いどころ

(1)em を使うところ
  フォントサイズを基準にしたサイズ。
  例えば、2emだと基準の文字サイズに対して、2倍の大きさになる。

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

 emを用いる具体例:

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

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

 
(2)%を使うところ
  ボックスのサイズ指定(特に、width)でよく使う。
  ページ全体に対してどれくらいの大きさにするかが重要なところで用いる。
  例えば、親要素に対して左右いっぱいにしたいボックスはwidth:100%で指定。
  レスポンシブレイアウト(ウィンドウサイズによってサイトの幅が可変する)で%をよく使う。
 
(3)px を使うところ
  フォントサイズ、ボックスサイズに関係なく、サイズを固定したいところで用いる。

  pxを用いる具体例:

・border-width(border の幅)
 もっとも良く使う。
・border-radius(ブロック要素の角丸)
 正円や楕円形の場合以外はpxで指定
・サイトのメインボックスの幅
 メインボックスの幅をpxで固定してしまい、端末ごとにメディアクエリで幅を切り替える。
・デザイン上、サイズを固定したい部分もpxで指定
 グローバルナビや、<h1>、<h2> を、背景画像と一緒に作り込むような場合などは、
 ガッチリpxで固定する。
 この場合も、メディアクエリで切り替えが必要。

 

2.見た目の変更

2-1.State

  状態を表す。
  Stateとして作成したセレクタ単体に対しては、スタイルを適用してはならない。
  他のclassと組み合わせて使う。
  
  接頭辞としてis-をつける。
  

 例:ボタンが押された状態になっているかどうか
HTML:例
<div class="button button-primary is-active">
CSS:例
.button-primary.is-active {・・・}

     

2-2.Theme

  Stateのような小さい範囲でのスタイル変更ではなく、ページ全体のテーマなどより大きい範囲での
  スタイル変更時に用いる。
  
  接頭辞として、t-をつける。
 

命名規則

id名、class名に使用する接頭辞一覧

接頭辞 用途 使用例
js- javascriptの対象となる要素につける id="js-move-icon"  
l- Layoutレイヤー(FLOCSS)の要素につける class="l-header"
c- Componentレイヤー(FLOCSS)の要素につける class="c-btn"
p- Projectレイヤー(FLOCSS)の要素につける class="p-btn--primary"
u- Utilityレイヤー(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名のつなぎ方

1.-(ハイフン)

名前の区切り。

例: class="p-edit-modal"

2.--(ハイフン2つ)

BEMの命名規則のModifier(後述)で用いる。

例: class="p-edit-modal--primary"

3.__(アンダースコア2つ)

BEMの命名規則のElement(後述)で用いる。

例: class="p-edit-modal__header"
 

BEMについて 

BEMでは、次の3つの要素を考える。

1.Block

 最も基本的な要素。
 あるUIを作る時の一番上の親要素をBlockとする。

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

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

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

 例:モーダル

 以下の例におけるp-modalp-panelBlockにあたる。

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>

 

2.Element

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

 例:モーダル

 以下の例におけるp-modal__headerp-modal__bodyp-modal__footer
 p-  modal__child-formElementにあたる。

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>

 

3.Modifier

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

 例:モーダル

 以下の例におけるp-modal--primaryp-modal__header--defaultModifierにあたる。

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_(アンダースコア)2つで、Blockに対して一段下がっている
 つまり親子関係であるというイメージ。
 Modifier-(ハイフン)2つで、バリエーション違いとしてBlockElementに対して
 対等の関係にあるというイメージ。
 

まとめ

この設計規則でどこまで通用するかは、今後の運用次第なところはありますが、
とりあえずの設計規則を決めました。

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

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

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

こうした問題をどのように解決するかが、本稿の設計規則を用いる上での課題となってきそうです。
 
 

参照

1.カスケーディングの基礎
2.スタイルの継承
3.ほんっとにはじめての HTML5 と CSS3
4.hiloki/flocss
5.CSSの設計 – FLOCSSをベースにしたファイルの構成と命名規則を考える
6.manabuyasuda/styleguide
 
 
最後に
オリジナル音楽の投稿配信サービスMicstackを運営しています。
よろしければご利用ください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away