期待が高まる PostCSS
SASSからPostCSSへ
およそ1年前、PostCSSはフロントエンドのエコシステムで急速に人気を集め始めた。その理由は、いわゆるプリプロセッサとしての特性、プラグインの高度なカスタマイズ性、cssnextの機能を先取りして使える点、そして各種ビルドツール(gulp、webpack)と組み合わせて非常に手軽に扱える点にある。
変数
最初にPostCSSを見たときはかなりワクワクしたものの、すぐに「本当に今すぐSASSを置き換える必要があるのだろうか?」と考え直した。
PostCSSの利点は、必要なプラグインを選んで必要なときにだけ使える点にある。例えば変数の機能を挙げると、postcss-simple-vars はSASSの変数宣言や利用の挙動を模倣できる。しかし僕からすると、どうしても違和感を覚えてしまう。なぜなら、SASSには変数の宣言だけでなく、mapやlistといった型が存在し、値の取得、条件分岐、ループ機能などの非常に充実したAPIが備わっているからだ。
$colors: (
main: #abc,
sub: #bac,
word: #333,
);
.container {
background-color: map-get($colors, $main);
color: map-get($colors, word);
}
CSS仕様のvarを使ったとしても同様で、mapやlistから値を取得する機能はない。
:root {
--wordColor: #333;
--bgColor: #fafafa;
}
body {
background-color: var(--wordColor);
color: var(--bgColor);
}
(心の声:それに、こう書くのは正直ちょっとダサいかなりダサい)
あるいは、SASSの @function を使えば map-get をさらにラップすることもできる。
$colors: (
main: #abc,
sub: #bac,
word: #333,
);
/* alias method for getting color from $colors map
/// @param {$key} the key you want to choose
///
/// eg:
color: c($word);
*/
@function c($key) {
@if map-has-key($colors, $key) {
@return map-get($colors, $key);
} @else {
@error "Unknown key #{$key}";
}
}
.container {
background-color: map-get($colors, $main);
color: map-get($colors, word);
}
PostCSSのエコシステムが広大であるがゆえに、個人開発者によるプラグインの多くはメンテナンスが放置されていたり、不注意によってコンパイルエラーや細かなバグが発生したりする可能性がある。それに対して、SASS自身が持つ機能は遥かに完成度が高い。
mixinとfunction
対応するプラグインとしては、postcss-mixins や postcss-functions がある。
mixinの挙動を模倣しているものの、条件分岐と組み合わせて使おうとすると、また一苦労することになる。
@mixin state($state,$namespace: '') {
@if ($namespace != ''){
.#{$namespace}-#{$state} {
text-transform: uppercase;
}
}
@else {
.${state} {
text-transform: uppercase;
}
}
}
function についても同様で、純粋なCSSとPostCSSの組み合わせで書く場合、SASSネイティブの関数は使えない。JavaScriptで関数を自作できる点は確かに魅力的だが、SASSと同等の関数を模倣しようとすると車輪の再発明をすることになり、少々面倒に感じてしまう。
SASSに比べるとまだ成熟していない
SASSに比べれば、PostCSSはまだ比較的新しいツールだ。エコシステムは広くプラグインも多いが、現行バージョンは今も急速に変化しており、未解決のIssueも多く残されている。SASSはRubyで書かれているため(現在はDart Sassなどもあるが)、コンパイル速度はPostCSSより遅いものの(正直、かなり遅いが)、その安定性と洗練されたAPI、型システム、構文は、PostCSSがまだ到達できていない領域にある。
PostCSSの強み
PostCSSの強みについても触れておこう!現在僕が組み合わせて使うのが一番気に入っているのは、autoprefixerとcssnanoだ。
autoprefixerは面倒なベンダープレフィックスの付与を肩代わりしてくれる。かつてはmixinを使って解決していたが、今では完全にPostCSS任せにできるため、コードがはるかにクリーンでシンプルになった。cssnanoはCSSのminifyを行ってくれるため、gulpと組み合わせる場合は gulp-postcss、gulp-cssnano、gulp-sass などを導入するだけで、CSSのコンパイルから最小化までをスムーズに実行できる。
上記のプラグイン以外にも、素晴らしいプラグインが揃っている:
postcss-sorting:定義したルールに従ってCSSプロパティをソートするprecss:SASSライクな機能を多数搭載しているstylelint:CSSのLintを行うstylefmt:stylelintのルールに従ってCSSコードをフォーマットするdoiuse:現在のCSSのブラウザ対応状況を検出する- livereload:webpackの強力なエコシステムと組み合わせれば、css-loader自体がHot Reloadの設定を処理してくれるため、スタイルファイルを変更するだけでページ全体をリロードせずに新しいスタイルを適用できる。
なぜ僕はいまだにSASSから離れられないのか
PostCSSとの組み合わせは確かに非常に便利だが、日常的な開発において両方を同時に導入することが工数削減につながるとは限らない。万が一エラーが発生した場合、内部の仕組みを調査するために時間を費やす必要があるからだ。PostCSSでコンパイルした後にSASSへ渡すとエラーが出るかもしれないし、どこかのパッケージのバグによってファイルが正常にコンパイルされず、一部のCSSコードが反映されないといった潜在的な問題が常に付きまとう。そのため、現在の開発では autoprefixer、cssnano、stylelint をCSSの簡略化やチェックのために利用するにとどめている。
結論
ゆくゆくはSASSが完全にPostCSSに取って代わられる日が来るのかもしれない。しかし、SASS自身が持つ完成された成熟した設計と構文こそが、僕がPostCSSへ完全に移行することを躊躇している最大の理由だ。いつかPostCSSが成熟し、SASSから完全に独立して運用できるレベルに達したとき、僕も本格的に移行するのだろう。かつてCSSを学んでいた頃、長いあいだ躊躇した末にようやくSASSを学び始めたときのように。もっとも、この2つ(SASSとPostCSS)は共存し、互いに補り合うことが可能だ。
PostCSSの高い柔軟性というメリットを享受する以上、僕たちは「抽象化の漏れ(Leaky Abstractions)」にも目を向けなければならない。プラグインは時代の変化や作者のメンテナンス停止によってバグを引き起こす可能性があるからだ。一つひとつのプラグインの機能は小さく見えても、すべて組み合わせることで節約できる時間は非常に大きい。一方で、SASSの完成された構文や変数システムは習得に一定の時間がかかるものの、統一された構文によってCSSの保守性を大幅に引き上げてくれる。
コンポーネント化が主流となった現代において、フロントエンド開発はモジュール化されたファイル(React、CSS Modulesなど)の管理へとシフトしつつある。将来的には、それほど複雑な操作(SASSの関数や変数など)を必要とせず、最も原始的な純粋なCSSへと回帰していくのかもしれない。
reference
関連記事
- Three.js で僕の部屋を表現する 僕が React Three Fiber を使って実際の自分の部屋をブラウザ上に再現し、実世界のオブジェクトを目録に見立て、空間の記憶を通してここ数年の生活と仕事について語った話。
- フロントエンドで画像を扱う際に注意すべきこと Jake Archibaldの記事を起点に、現代のレスポンシブ画像の書き方を整理する。なぜwidth/heightを付ける必要があるのか、CSSのaspect-ratioはいつ使うべきか、AVIFとWebPの選び方、そしてpicture/source/srcsetを使ったモバイル向け画像の切り替えについて。
- CSS field-sizing — たった1行のCSSでフォーム要素を自動リサイズする かつてtextareaの自動高さ調整は、JavaScriptでscrollHeightを監視するしかなかった。しかしCSSのfield-sizing: contentなら、わずか1行で代替でき、textarea、input、selectに対応している。本記事では従来のやり方のペインポイントと、field-sizingの使い方をまとめる。
- リンクの下線をもっと見栄え良くする:text-underline-offset デフォルトでは下線と文字が近すぎて、このスタイルを好まないデザイナーもいるし、僕自身もあまり綺麗ではないと感じていた。