狠狠撸

狠狠撸Share a Scribd company logo
2017: A CSS Design Odyssey
KenjiroKubota
社内勉强会のため自己绍介なし
今日伝えたいこと
あらゆるCSS設計の思想を知ることで、今後の自分たちのCSS設計に
フィードバックしていきたい。してほしい。
良いCSS設計はメンテナンスしやすい。
楽していこう
A Long Past
html
<a id="btn-main">メイン</a>
<a id="btn-sub">サブ</a>
css
#btn-main {
width: 100px;
height: 40px;
background-color: red;
}
#btn-sub {
width: 100px;
height: 40px;
background-color: blue;
}
問題点
使いまわせないID要素
似たようなプロパティ値
HTMLとCSSが密結合
贬罢惭尝の构造と颁厂厂は分离していきたい
OOCSS
Object Oriented CSS
OOCSS
2009 -
米Yahoo!のNicole Sullivanが提唱
オブジェクト指向の考え方を参考にした設計方法
Twitter 叠辞辞迟蝉迟谤补辫が採用している设计
CSS is too fragile
Nicole Sullivan
プロパティ より セレクタ
.selector { ... }
コンテナ(入れ物)とコンテンツ(中身)を分離
ストラクチャー(構造)とスキン(装飾)の分離
html
<a class="btn btn-red">メイン</a>
<a class="btn btn-blue">サブ</a>
css
.btn {
width: 100px;
height: 40px;
}
.btn-red {
background-color: red;
}
.btn-blue {
background-color: blue;
}
OOCSSで重要なこと
重複を避ける、冗長性を避ける
同じようなプロパティの要素はまとめる
要素依存、場所依存を避ける
HTML要素を変更しても崩れない(にくい)
Past ━
OOCSS
HTMLの変更は簡単そうだ。
だがCSSはどうだろう
BEM
Block Element Modi er
BEM
2012~13 -
Yandexのフロントエンジニアが提唱
長期間メンテナンスできる設計で尚且つファーストバージョンの開
発を素早く行える
チームのスケーラビリティ
コードの再利用性が高い
Block - 要素のルート
Element - Blockの子要素。単体では存在しない
Modi er - 元となるBlock,Elementから変化した
状態を表す要素
2017: A CSS Design Odyssey
2017: A CSS Design Odyssey
MindBEMding
MindBEMding
BEMをCSSのクラス名に適用するための規則
Elementはアンダースコア2つ、Modi erはハイフン2つで区切って繋
げることでBEMの各要素を表現する
※この区切りをBEMではセパレーターと呼ぶ
.Block__Element--Modi er
html
<ul class="main-tab">
<li class="main-tab__button">
<a href="">Tab1</a>
</li>
<li class="main-tab__button">
<a href="">Tab2</a>
</li>
<li class="main-tab__button main-tab__button--active">
<a href="">Tab3</a>
</li>
<li class="main-tab__button">
<a href="">Tab4</a>
</li>
</ul>
css
.main-tab {
...
}
.main-tab__button {
...
}
.main-tab__button--active {
...
}
scss
.main-tab {
...
&__button {
...
&--active {
...
}
}
}
Block単位でファイル分割するのが通例(main-tab.scss)
MindBEMdingの書き方に拒絶反応を示す人もいる
かもしれないけどルールが明確で命名に迷いにくい
Rule
.widget_list / .widget__list
BEM
MCSS
Multilayer CSS
MCSS
2012~3 -
OOCSS, BEMを基とした構成システム
海外のSNSサイト会社のチームから作られた
レイヤーで分割
Layer
0. Foundation
1. Base
2. Project
3. Cosmetic
2017: A CSS Design Odyssey
0: Foundation
リセットとちょっとした変更を加えるだけのメインレイアウトのベース
を記述した、全ページに適用されるスタイルを含める。
すべてのリセットのようなファンデーションスタイルは、分割ファイル
と共通CSSファイルの先頭とのどちらの場合でも、スタート直後に配置
される。
※ 当時はCSSプリプロセッサは考慮されいないので分割でCSSファイルを作成し、レイ
ヤー順にリンクさせるように説明されている。
1: Base
再利用可能で抽象的な構造
フォーム
ボタン
ナビゲーションブロック
その他
MCSS導入時にまず最初に再利用可能な標準スタイルのセットを作成す
ること。
2: Project
分離されたページを構成するプロジェクトモジュールを含む
登録フォーム
ログインブロック
ショッピングカート
その他
可能な限りユニークなCSSクラスの仕様が推奨される。
3: Cosmetic
わずかに影響するスタイル。
リンクカラー
シンプルなOOCSS
グローバルな修飾子
Layer(再掲)
0. Foundation (reset, normalize)
1. Base (OOCSS)
2. Project (BEM)
3. Cosmetic (OOCSS)
OOCSSとBEMの要素を取り入れ、階層の概念を持っている
SMACSS
Scalable and Modular Architecture for CSS
SMACSS
2013-
CSSのルールを5種類にカテゴライズし、それぞれの考え方や記述ル
ールが決められている
電子書籍で無料で提供
コード量を減らす
メンテナンス性を高める
ユーザー体験の一貫性の向上
CSSプリプロセッサ前提っぽい?
CSSのカテゴライズ
Base - 要素そのもののデフォルトスタイル
Layout - ページをエリアごとに分割
Module - 再利用可能なパーツ
State - レイアウトやモジュールの特定の状態を示す
Theme - サイトのルック&フィールを定義
Base Rule
サイト全体で要素そのもののデフォルトスタイルを定義
要素そのものの定義という性質のため、IDやクラスは使わない。
CSSリセットもベースに含む
要素セレクタ( body , a )
属性セレクタ( input[type=text] )
擬似クラスセレクタ( a:hover )
※要素セレクタに対しては具体的なスタイル指定をしない。(上書きが発生しないように)
Layout Rule
ページのエリア分けを行う。
.l- , .layout- プレフィックスを付ける。
IDはCSSの詳細度を高めてしまうのでなるべく避ける(SMACSSでは禁
止はしていない)
※詳細度は後ほど説明します
子孫セレクタを使って分岐
.l-main {
width: 70%;
}
.l-fixed .l-main {
width: 600px;
}
.l-fixed が付いている場合はpx指定、そうでなければ%指定
Module Rule
再利用可能なパーツ
ロゴ
ナビゲーション
タブ
レイアウトパーツの中に入れて、どこに置いても再利用できるように独
立させておく。
モジュールの命名規則
親モジュールの名前をプレフィックスでつける
<div class="item">
<p class="item-text"></p>
</div>
IDや要素セレクタは避けて、クラスで統一する
モジュール全部にクラスを付ける必要はない。
li , a ... クラスとつけなくても良い
(モジュール内で何度も登場する要素にはクラスをつける)
State Rule
特定の状態に依ってスタイルを上書きする
状態の切り替えはJavascriptが行う
結果がtrueの場合は .is-
表示/非表示
.is-hidden
.is-error
.is-active
Theme Rule
すべての主要なルールに対して影響を与える。
main.css
.mod {
border: 1px solid;
}
theme.css
.mod {
border-color: blue;
}
規模によっては上書きではなくテーマ特有のクラスを設定するほうが良
いかもしれない。
そういう場合は .theme- プレフィックスを使う。
.theme-border {
border-color: purple;
}
.theme-background {
background: linear-gradient( ... );
}
惭颁厂厂より、より実践的な印象
闲话休题
CSSの詳細度
https://www.w3.org/TR/selectors/#speci city
詳細度の概念
詳細度は、どのプロパティ値が最もある要素に関係があり、適用される
かをブラウザが決定する手段です。詳細度は異なる順のセレクタで構成
されるマッチング規則にのみ基づきます。
どのように評価されるか
詳細度はそれぞれのセレクタ型の数の連結で計算されます。それは、一
致するマッチング表現を適用する重みではありません。
詳細度が等しい場合は、 CSS で発見される最も後の宣言が要素に適用
されます。
(MDN)
speci cityは直訳だと特異性なんだけど…
個人的には詳細度というより優先度と置き換えて覚えるとわかりやすい
かもしれません。
詳細度の序列
小
全称セレクタ (*)
タイプセレクタ (要素名)
クラスセレクタ
属性セレクタ ([type="text"], [href="#"])
擬似クラス (:after, :nth-child)
ID セレクタ
インラインスタイル
大
!important の例外
詳細度とは無関係に上書きを行う
:not の例外
否定擬似クラスの :not は詳細度の計算では擬似クラスとは見なされま
せん。しかし、否定擬似クラスの中に置かれたセレクタは、通常のセレ
クタのように計算されます。
Question
html
<p id="hoge">
<span id="fuga" class="piyo1 piyo2 piyo3">
ここは何色?
</span>
</p>
css
#hoge #fuga {
color: red;
}
#hoge .piyo1.piyo2.piyo3 {
color: blue;
}
正解は 赤
詳細度はCSSの複雑度を上げてしまう
わかりやすく同レベルの詳細度に留めておくことで後勝ちの法則を保つ
id や !important は使わない
FLOCSS
Foundation Layout Object CSS
FLOCSS
2014 -
サイバーエージェントの谷拓樹氏が提唱
「CSS設計の教科書」の著者
OOCSS, SMACSS, BEM, SuitCSSのコンセプトを取り入れ、MCSSの
レイヤー構成にも影響を受けている
いいとこ取り
CSSプリプロセッサ前提
基本原則
FLOCSSは3つのレイヤーとObjectレイヤーの子レイヤーで構成される
Foundation
Layout
Object
Component
Project
Utility
Foundation
Reset.cssやNormalize.cssなどを用いたブラウザのデフォルトスタイル
の初期化や、プロジェクトにおける基本的なスタイルを定義します。
ページの下地としての全体の背景や、基本的なタイポグラフィなどが該
当します。
Layout
ページを構成するヘッダーやメインのコンテンツエリア、サイドバーや
フッターといったプロジェクト共通のコンテナーブロックのスタイルを
定義します。
基本的には、ページ単位で唯一の存在である要素となるため、Layout
レイヤーの要素ではIDセレクタを採用することも可能です。
ただしIDセレクタは高い詳細度を持つため、それを懸念する場合に
は、 l-* プレフィックスをつけた命名を採用するか、あるいは
[id="header"] のような属性セレクタを用いることを推奨します。
Object
OOCSSのコンセプトを元に、プロジェクトにおける繰り返されるビジ
ュアルパターンをすべてObjectと定義します。
FLOCSSでのObjectは、さらに次の3つのレイヤーに分けられます。
Component
再利用できるパターンとして、小さな単位のモジュールを定義しま
す。
出来る限り、最低限の機能を持ったものとして定義されるべきであ
り、それ自体が固有の幅や色などの特色を持つことは避けるのが望
ましいです。
Project
プロジェクト固有のパターンであり、いくつかのComponentと、そ
れに該当しない要素によって構成されるものを定義します。
Utility
ComponentとProjectレイヤーのObjectのモディファイアで解決する
ことが難しい?適切では無い、わずかなスタイルの調整のための便
利クラスなどを定義します。
命名規則
MindBEMdingを採用。
状態を表すものはSMACSSのStateパターンを用いて .is- プレフィック
スを使う。
Objectのプレフィックス
Component - .c-*
Project - .p-*
Utility - .u-*
ディレクトリ構成
├── foundation
├── layout
└── object
├── component
├── project
└── utility
今までのCSS設計の良いところ
実践的なことが詰まっている印象
RSCSS
Reasonable System for CSS
RSCSS
2015 -
合理的にCSSを組み立てるためのアイデア集
5つの分類
Components
Elements
Variants
Layouts
Helpers
Components
検索フォームのようなひとかたまりを一つのコンポーネントとして考え
る
命名規則
Componentはダッシュで区切られた少なくとも2つの単語からなる
Likeボタン .like-button
検索フォーム .search-form
ニュースカード .article-card
Elements
Componentを構成する内部要素
命名規則
それぞれのComponentは通常、複数のElementを持つ。Elementの名前
は1単語にする
.search-form {
> .field { /* ... */ }
> .action { /* ... */ }
}
Elementのセレクター
可能な限り子セレクタ > を使う。Componentのネスト防止になるし、
子孫セレクタよりパフォーマンスが良い。
複数の単語が使いたい
2つ以上の単語からなる名前をつけたい場合は、ダッシュやアンダース
コアを使わないで連結する
タグセレクタは避ける
ちゃんとクラス名を付ける
Variants
ComponentもElementもそれぞれvariantを持つことができる
命名規則
variantのためのクラス名にはダッシュをプレフィックスとして付ける
.like-buttoon {
&.-wide { /* ... */ }
&.-short { /* ... */ }
&.-disabled { /* ... */ }
}
Elementのvariant
Elementもまたvariantを持つ頃ができる
.shopping-card {
> .title { /* ... */ }
> .title.-small { /* ... */ }
}
Layouts
ポジションに関するプロパティは避ける
Componentは異なるコンテキストで再利用するべきなので以下のよう
なプロパティを書くのは避ける
Positioning (position, top, left, right, bottom)
Floats ( oat, clear)
Margins (margin)
Dimensions (width, height) *
親要素でポジションを定義する
.article-list {
& {
@include clearfix;
}
> .article-card {
width: 33.3%;
float: left;
}
}
.article-card {
& { /* ... */ }
> .image { /* ... */ }
> .title { /* ... */ }
> .category { /* ... */ }
}
Helpers
._unmargin { margin: 0 !important; }
._center { text-align: center !important; }
._pull-left { float: left !important; }
._pull-right { float: right !important; }
汎用クラスはアンダースコアで始まる名前で別ファイルに置かれ、値を
上書きする。通常、 !important でタグ付けされる。
命名規則
アンダースコアをクラス名のプレフィックスとして付ける。
<div class='order-graphs -slim _unmargin'></div>
Heplerの整理
helpers というひとつのファイルに収める。複数ファイルに分割するこ
ともできるが、たくさんの helper を最小限に維持するのが好ましい。
CSS Structure
ファイル単体でひとつのComponent
Use glob matching
@import 'components/*';
過剰なネストを避ける
/* ? Better: 2 levels */
.image-frame {
> .description { /* ... */ }
> .description > .icon { /* ... */ }
}
Atomic Designのアイデアも
取り入れられている印象
ESCC
Enduring CSS
ECSS
2015 -
bet365.com フロントエンジニア
Enduring = 長続きする、永続的な、不屈の、我慢強い、心房強い
OOCSSとは真逆のアプローチ
顿搁驰ではなく顿别肠辞耻辫濒颈苍驳
ECSSが目指すもの
CSSシンタックスにあるブレース {} の外側をどのように扱うか。
プロパティをDRYにするのではなくキーセレクタをDRYにするべき。
(OOCSSもセレクタに着目し他考え方だが、あくまでもブレース内を
DRYにするための思想)
キーセレクタをDRYにする
コンテキストが違うコンポーネントは既存のコンポーネントと似ていて
も別物として扱う。
抽象化したモジュールは変更に対する影響範囲が大きく扱いずらい。
モジュール
namespace - クラス名の衝突を防ぐための接頭辞
Module - 個別の機能領域の最も大きな区分
Component - Moduleに含まれる機能性を持つ部品
ChildNode - Componentに含まれる独立した部品
variant - Module内の部品の別の状態
命名規則
ECSSとBEM
Module,Component === Block
ChildNode === Element
variant === Modi re
ECSSとAtomicDesign
Module === Organisms
Component === Molecules
モジュールは以下のようなシンタックスで表現されます
namespace-ModuleName_ChildNode-variant
namespace-ComponentName_ChildNode-variant
namespace はModule名になることもあります。
modulename-ComponentName_ChildNode-variant
namespaceとvariantはダッシュ、それ以外はアンダースコアで繋ぐ。
名前空間(namespace)
クラス名の重複を避けるためECSSでは必ず名前空間を付ける
トップページ TopPage .tp-
カテゴリートップ CategoryTop .ct-
ショッピングカート ShoppingCart .sc-
サイトに共通する構造的なモジュール
Structureから取った .st- の名前空間を付けると良い
サイトに共通する汎用的なモジュール
SideWideから取った .sw- の名前空間を付けると良い
Layout名前空間
レイアウトを管理するモジュールの場合は .layout- 名前空間がオススメ
ディレクトリ構成(略)
└── css
├── font/
├── base/
│ ├── variable/
│ ├── function/
│ ├── mixin/
│ ├── _normalize.scss
│ ├── _base.scss
│ └── _Icon.scss
├── SiteWide/
├── Structure/
├── namespace/
│ ├── layout/
│ ├── news/
│ ├── product/
│ ├── results/
│ ├── search/
│ └── sitemap/
└── site.scss
Moduleの状態変化
状態変化はWAI-ARIA(ウェイ?アリア)を使うことが推奨される
aria-selected="true"
aria-disabled="true"
aria-hidden="true"
aria-expanded="true"
aria-busy="true"
などなど。標準化された支援技術によってアクセシブルになることが期
待できる。
WAI-ARIAを使わない場合はvariantを使うことが勧められてます
.co-Button-selected
ECSSの十戒
1 すべてのキーセレクタは"Single Source of truth"であること
2 入れ子にしない
3 IDセレクタは使わない
4 ベンダープレフィックスは書かない
5 サイズや色、z-indexに変数を使う
6 モバイルファーストで書く(max-widthを避ける)
7 mixinを控えめにする(extendを避ける)
8 すべてのマジックナンバーとブラウザハックに対してコメントを書く
9 インラインイメージを使わない
10 複雑なCSSを書かない
長い長い旅でしたね
で、結局どの設計を使えばいいの???
どの設計を使うかはサイトの規模や、成長性次第
コンパクトなサイトでSMACSS, FLOCSSなどは過剰かもしれない。
将来的にサイトデザインが大きな変わりそうであれば捨てやすいECSS
が良いかもしれない。でもデザインの統一性は必要ならOOCSSのエッ
センスが必要なことも?
大切なのはこのような設計方法を知ることでその良い部分を取り
入れること
自分たちのルールを混ぜるもよし。READMEにXXCSS設計を基にデザ
インされていると明記して、後からジョインされるメンバーも導入しや
すい環境など。
thanks;)

More Related Content

2017: A CSS Design Odyssey