SassやLESSといったCSSプリプロセッサーは市民権を得たと言って良いと思う。しかしそれらCSSプリプロセッサーは開発という段階にのみ利をもたらすもので、今のところはそれ以上ではない。CSSを実際にユーザーに届けるまでには、開発だけではなくレビューとリリースという段階もある。レビューとリリースも確実性を持って効率的に行うためには、CSSポストプロセッサーと総称されるようなツール群が必要になるだろう。
この文書はFrontrend Advent Calendar 2013の4日目への記事として寄稿した。明日は@hilokiさんがスタコラサッサ
と書くようだ。
目次
CSSポストプロセッサーとは
CSSポストプロセッサーとは、CSSを機械的に処理して特定の変更を加えるツールのことと考えて貰えば良い。代表的なものはYUI Compressorを始めとしたCSS圧縮ツールだ。圧縮ツールも兼ねているCSSプリプロセッサーの広まりによりめっきり影が薄くなったが、そのCSSプリプロセッサー自体の複雑化により再び必要性が増している。
現在、複雑なCSSプリプロセッサーの文法を駆使した他人に読めないコードと、圧縮された人間に読めないCSSの2つしかないというような状況に、多少悲観的ではあるかもしれないが、なりつつある。レビューのためには読みやすいCSSを一旦出力する必要があり、そのままではリリースに向かないため、レビュー後リリース前に圧縮等の機械的な処理を行う必要がある。それを担うのがCSSポストプロセッサーというわけだ。
CSSプリプロセッサーの出力するCSS
CSSプリプロセッサーではいくつかのフォーマットで出力できることが多い。しかし、多くのプロジェクトで圧縮した形での出力を選択しているのではないかと思う。今年に入ってSource MapsがCSSプリプロセッサーとブラウザー双方でサポートされたこともあり、その傾向は更に強くなると考えられる。
圧縮されたCSSはまったく可読性に欠けているため、当たり前だが人間がちゃんと読むことはほぼ不可能と言って良い。ちゃんと読めないということは、つまりレビューすることが出来ないということになる。リリース用としては申し分ないし、Source Mapsを利用するのなら開発中やリリース後のデバッグも問題ないが、リリース前のレビューが難しいというのは変わらないし、規模によっては大きな問題になる。
「Source Mapsで関連付けられる先のCSSプリプロセッサーのコードをレビューすれば良いのでは?」という疑問も当然あるだろう。Sass 3より前くらいまではCSSをちょっと便利にしたもの程度だったので、CSSの知識さえあればCSSプリプロセッサーのコードをレビューすることは難しくなかった。しかしリリースが控えているSass 3.3で導入される@at-root
やマップ型変数などが使われるようになるこれからは、Sassの仕様を正確に理解していないとレビューすることは難しくなっていくだろう。
レビューはCSSプリプロセッサーで書く人だけでなく、そのウェブサイトやウェブアプリケーションのマネージャーやバックエンド開発者、そして運用を行う人など様々な人が参加すべき段階だ。彼らにCSSプリプロセッサーの機能を正確に理解するよう求めるのは難しいし、はっきりと言うならそれを求めるのは間違っている。彼らは彼らで他に優先して覚えることがそれぞれあるのだから、ウェブ標準のCSSを理解できるという程度で良しとするべきだ。
また、多くのCSSを扱うツールは普通のCSSファイルを前提にして作られている。そのようなツールたちとうまく連携するためには、アグレッシブな作業を行わず普通のCSSファイルを出力するに留めるのが手っ取り早い。そうでないとCSSプリプロセッサーの対応待ちなどということになる。その場合、利用できるまでかなり待たされることになったり、アドホックなハックを使わないとうまく動かないなどということになるだろう。
CSS Lint
レビュー前に機械的なチェックを行うツールとして、CSS Lintを利用することができる。CSS Lintではカレント・ディレクトリに.csslintrc
というファイルを作ってそこに設定を書くことができるようになっている。多くの自動テストツールではこれを利用するようになっているが、v0.9.10からはJSLintのようにCSSにコメントとして設定を埋め込めるようにもなった。
CSSプリプロセッサーで圧縮してしまうと、このCSS Lintの設定を書いたコメントを残すことが難しくなる。もちろん.csslintrc
を使えば良いという話ではあるのだが、CSSファイル(プロジェクトではない)のポータビリティという点で埋め込むのも悪くはない。普通のCSSを出力するようにしておけば、こういった利用したいツールの機能性を一部失わせてしまうようなことにはならない。
つまり、ほとんどのケースでCSSプリプロセッサーからリリース用に圧縮されたCSSを直接出力するべきではないということだ。
開発用とレビュー用、リリース用のCSS
この3つの段階では重要視されるものが違う。
- 開発用: 書きやすく、効率的であること
- レビュー用: 読みやすく、標準的であること
- リリース用: 配信に向く、最適化と圧縮がなされたものであること
大雑把に分けるとこのようになるだろう。CSSプリプロセッサーではリリース用のCSSを直接出力するのではなく、一旦レビュー用に標準的なスタイルで出力し、レビューが通ったらリリース用にCSSポストプロセッサーで変換する、というのが望ましいのではないか。
CSSポストプロセッサーで最適化を行うようにすることにより、開発時にも利はあるだろう。今まではCSSプリプロセッサーの限られた機能で苦労して無理やり複雑に行っていた効率化の多くをなくせるようになり、すっきり簡潔に書けるようになるはずだ。
CSSポストプロセッサーのユースケース
現状の説明が長くなったが、CSSポストプロセッサーの必要性は何となくわかったのではないかと思う。では、どういう作業をCSSポストプロセッサーに任せるのが良いのだろうか?
CSSポストプロセッサーに任せられる処理は後回しにできることが絶対条件だが、それだけではワークフローまでも変化させる理由としては乏しいのではないかと思う。以下の利用例では後回しにすることにより編集時とレビュー時にもそれぞれ利点がある処理に絞り紹介する。これらのツールを採用することにより、レビューまではCSSをシンプルなままで維持できるようになり、快適な編集・レビューを行えるようになるはずだ。
ベンダー拡張プリフィックスの付加
CSSプリプロセッサーではベンダー拡張プリフィックスをミックスインで一気に追加できて便利というような変革が起こったが、それはすぐに別の問題を引き起こすことになった。
- もう必要のないプリフィックスも付いてしまうこと
- 実装の細かな違いや修正に対処できないこと
- ミックスインでプロパティーを記述すると、CSSのコードとして理解できないこと
主なものはこの辺りだろう。CSSプリプロセッサーではウェブ標準のCSS文法のみで記述するだけに留め、CSSポストプロセッサーにプリフィックスの付加を任せることにより、より確実で簡潔なCSSを出力できるようになる。
この類いのツールとしてはAutoprefixerが最も優秀だと思われる。Can I Useのサポート状況を参照してくれるので、もう必要のないプリフィックスが付くことがないのは素晴らしい。ブラウザー上で動的に付加してくれるスタンドアローン版もあるので、レビュー時も問題ない。
See also: Autoprefixer
Media Queriesの取りまとめ
CSSプリプロセッサーではMedia Queriesをネストして書くことができるものが多い。そのためCSSではルールセットごとにMedia Queriesがセットになって出力されることになる。これは特定の要素に対するルールセットが集約するということになるので、あちこち行ったり来たりする必要がなく、非常に読みやすくなる。その反面、同じクエリーがCSS内にいくつも出てくることになるので、ファイルサイズ他の面では無駄が多くなってしまう。
同じクエリーをまとめることができるgroup-css-media-queriesのようなCSSポストプロセッサーを利用すると、それほど絶大な節約にはならないものの確実に減らすことができる。それと同時に、書きやすい形での開発と読みやすい形でのレビューを維持することが可能になる。むしろこちらの方が大きな利点だろう。
See also: group-css-media-queries
Data URIへの変換
HTTPリクエストの削減のためにData URI化して埋め込むという手法もそれなりに認知された。しかしレビュー時にData URIである必要はまったくない。それどころか多くの場合は害悪になる。ファイル名が失われるので、どういう画像を参照しているのかというヒントは全くなくなるし、エディターやデバッグ・ツールの構文強調が壊れたりすることも多いだろう。Data URIへの変換は大抵の実装で安定していることだし、率先して機械化するべき処理と言って良いだろう。
これもあまり選択肢はないが、需要は徐々に増えつつあるように思うので、今後は少しづつ増えてくるのではないかと思う。その中でも古株のひとつ、Image2CSSは信頼出来るという印象だ。
See also: Image2CSS
空白の削除などによる圧縮
転送量の節約はフロントエンドの義務と言って良いので、当然リリース時には圧縮したCSSを配信する方が望ましい。先述のYUI Compressorを始め多くのツールがあるので、好きなものを選択すれば良いだろう。僕はclean-cssというツールを使っている。利用しているCSSプリプロセッサーにもう一回通して圧縮だけ行う、というのも良いかもしれない。
僕の使っているclean-cssはシンプルなコメントと空白除去が主な機能だが、@import
で読み込まれるCSSファイルのインライン展開を行う機能もある。Sassではまだ@import
でCSSファイルはインライン展開はしてくれない上、インライン展開できるSCSSファイルでもパスのずれの修正は行えない。clean-cssで処理するように変更すれば、その辺りの問題を解決でき、より効率的にCSSを書くことができるようになるだろう。Normalize.cssの拡張子をscss
に変えて置いておくなどといったバカバカしい作業も必要なくなるのだ。
See also: clean-css
Gruntでまとめて実行
ここまでに例として上げたCSSポストプロセッサーたちは、それぞれの作業は簡単なものだが、ひとつひとつ手作業で行うのは無理がある。自動実行されるようにリリース作業に組み込むべきだ。プロジェクトによってそれに最適なツールは変わってくるだろうが、有力な候補のひとつとしてGruntが挙げられるだろう。
Gruntの具体的な導入や使い方についてはその公式ドキュメントを始め、いくつも素晴らしい解説があるのでここでは省略し、上記CSSポストプロセッサー達の代わりになるGruntプラグインをリストアップするだけにしておく。
- autoprefixer: grunt-autoprefixer
- group-css-media-queries: grunt-combine-css-media-queries (別実装)
- image2cssConverter: grunt-data-uri (別実装)
- clean-css: grunt-contrib-cssmin
あとはこれらを順に実行するGruntタスクを書き、リリース作業に組み込むだけだ。
最後に
僕が主に使っているのがSassなので、それを前提にして書いてきた。しかしCSSポストプロセッサーはCSSを対象にして動作するツールなので、CSSプリプロセッサーにはSassでもLESSでもStylusでも何でも良い。……Closure Stylesheetsでも! CSSプリプロセッサーを使わない開発にももちろん利用できる。CSSプリプロセッサーに依存しないので、標準的な概念・作業として広く定着できるのではないかと思う。
CSSプリプロセッサーたちは、同じ記号を別の機能に割り当てていたりするので、いずれかの知識に偏っていると勘違いや読み間違いを頻繁に犯してしまう。既にSassに習熟した人がLESSのコードを間違えずに読むのは難しいだろう。そういう点でも標準的なCSSでレビューというのは重要になってきているはずだ。
また、後処理に回せるような機械的な処理ならば、CSSプリプロセッサーの実装を待たずにCSSポストプロセッサーとしてワークフローに取り込むことができるという利点もある。clean-cssの説明で少し触れたSassになくてLESSにはある@import
でのパス解決機能などはその例のひとつだ。
もしGruntで実行させているのなら、プロジェクトに依存したちょっとした処理ならさっとJavaScriptで書ける。やりすぎはGrunt依存につながるので禁物だが、フロントエンド側の人間ならばうれしいところだろう。
強力なCSSプリプロセッサーのさらなる進化はCSSとの大きなギャップをももたらした。そのギャップはCSSプリプロセッサーの利用を制限することで抑えることは可能ではあるが、それはあまりにも後ろ向きだと思う。CSSプリプロセッサーの利点を最大限に利用した上で、圧縮などリリースのための機械的な作業をCSSポストプロセッサーに任せることにより、開発しやすさ・レビューしやすさ・配信しやすさのどれも失わずにプロジェクトを完走させることができるのではないだろうか。
ようこそ! CSSポストプロセッサー時代へ!