最近の僕のCSSとの向き合い方

業務内容に合わせたCSSの書き方が大方定まってきた感じがあるので書く。

ビルド

SassのSCSS記法で書いて、ポストプロセスとしてAutoprefixerとCSSOあたりを通すという風にしてる。

プリプロセッサーとしてPostCSSを使うのは難があって、利用できる機能を独自に追加していけるというのが難しいと思う。仕様にない独自の機能を無秩序に使ってしまって、プロジェクトの治安が悪くなったり、プロジェクトごとに利用できる機能が違うってなりそうでだるい。また、将来の仕様で書けるというプラグインでも、シンタックス上そのように書けるというだけで、機能が実装されてないブラウザでも動くようになるというわけではないというところで混乱を呼びそう。

例えばpostcss-custom-propertiesは、CSS Variablesのシンタックスで記述されていたコードを静的な値に変換するプラグインだけど、これだと仕様と意味が全然違う。変数がコンパイル前のコードにだけ存在するという前提で書いていると、将来的にブラウザ上でCSS Variablesを利用するときに想定してなかった問題にぶつかる可能性がある。これならPostCSSの独自機能として変数を定義できたほうがいい。仕様と関係のないプラグイン上の事情があることもあって、それならSassでいいやってなる。

とは言え、Sassにベッタリな書き方をしているといずれ捨てなければならないときに辛いので、Sassを使いつつ、将来の仕様で置き換えられないようなSassの独自機能にはできるだけ依存しないようにして書いている。

設計

すべての状況下で正しく機能する設計パターンは存在しなくて、CSS設計はサイト構造やデザインフローに依存する。

僕が業務パターンに合わせて利用しているCSS設計は、一般的ないわゆる設計っぽいものでなくて、いろんなことを思い切って諦めるというアプローチを強調したものになっている。

まず、CSSの再利用は可能な限りやめる。コーダーがカンプから読み取れる程度の抽象化なんて、だいたいデザイナーの認識とずれているので機能しない。ここで中途半端にがんばっても、デザインの変更のたびにリファクタリングが必要になるので諦める。CSS設計やコードの品質を上げるためだけに割ける時間はないし、そこにかけた労力を超えるメリットが享受できない。もちろんこれは業務による。

ディレクトリ構成

// core
@import "var";
@import "function";

// base
@import "../../node_modules/ress/ress";
@import "base";

// structure
@import "st/GlobalHeader";
@import "st/GlobalFooter";

// home
@import "home/Hero";
@import "home/GridList";

// about
@import "about/Hero";
@import "about/CompanyInfoTable";

ベースCSS

また、要素名に対してユーザーエージェントから与えられたスタイルはできるだけリセットする。要素名に対するスタイルは、まずデザインがセマンティックに基づいている前提で機能するものだが、すべてのデザインがセマンティックであるとは言えないからだ。マークアップは割とよく変わるので、要素名のスタイルに依存したCSSを書いていると死ぬ。

ressを読み込んだ上で、加えて以下のような感じのベースCSSを書いている。

:root {
  font-family: $font-stack-ui;
  line-height: 1.5;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-size: 100%;
  font-weight: normal;
}

ol,
ul {
  list-style: none;
}

img,
video {
  max-width: 100%;
  height: auto;
}

セレクタルール

  • .namespace-Component_subComponent
  • .namespace-Component_subComponent.-modifier
  • .namespace-Component_subComponent.is-stateOfComponent

という風にする。

ネームスペースはページのパターンごとに分ける。

コンポーネントのクラス名は、JSとかのクラスの命名規則と似たようなイメージ。クラス名はパスカルケースで、そのメンバ変数はキャメルケースというのと同じ。言い換えると親のコンポーネント無しにサブコンポーネントを利用することはない。

liaなど、セマンティックな要素名ならセレクタに利用することも許容する。ただし2階層まで。子セレクタとして書く。

.home-GridList {
  > li {...}

  > li.is-active {...}

  > li > a {...}

  &_heading {...}

  &_heading.-wide {...}
}

ネストは出来る限り浅くする。

ECSSSUIT CSSrscssChainable BEM modifiersあたりに影響されてる。

気持ち

CSSは簡単なので設計するのが難しい。CSS設計をしようとすると、どうしてもデザインの方がそっちに寄せるしかない。

今回書いたやり方は、デザインの方が寄せなくて済むように多少非効率的にCSSを書いていくという感じになってる。

でも、ウェブデザインはCSS設計に限らず、ウェブの性質に寄り添った作りになっているべきで、ウェブデザイナーは可能な限り実装面も理解すべきだと思う。ウェブに合ってないデザインは非効率的で、もっと寄り添った作りになっていれば無駄なコストを使わずより良い結果にできるのにと、いつもそうやって悔しい思いをしている。

ちゃんとウェブデザインを作っていくためのワークフローを作りたいし、絶対にそれがないといいものは作れない。

やっていく。