HTML5Experts.jp

PostCSSとcssnextで最新CSS仕様を先取り!

どうも、Kaizen Platform, Inc.@t32kです。今日はPostCSSについて解説しようと思います。PostCSSについてはそれを解説した同僚のスライドも素晴らしいので、そちらも参考にしてもらえば幸いです。

PostCSSとはなにか?

PostCSSは、Autoprefixerの作者でも有名なロシアのAndrey Sitnik氏が開発しているツールです。

公式のレポジトリのREADMEには以下のように書かれています。

PostCSS is a tool for transforming styles with JS plugins. These plugins can support variables and mixins, transpile future CSS syntax, inline images, and more.

PostCSSはCSSのスタイルを変更するためのツールと言えますが、実際に、どのスタイルを変更するかは各種プラグインによって行われます。

PostCSS自体はCSSパーサーでそれによって生成されるAST(抽象構文木、Abstract Syntax Tree)を扱うAPIを提供しているにすぎません。

PostCSSの使用例

例えば、postcss-sizeというプラグインを使えば、独自ショートカットプロパティであるsizeが以下のように使用可能になります。

/* 変換前のCSS */
.rectangle {
    size: 400px 200px;
}
.square {
    size: 250px;
}

/* 変換後のCSS */
.rectangle {
    width: 400px;
    height: 200px;
}
.square {
    width: 250px;
    height: 250px;
}

プラグインを使うことで、sizeプロパティが現状のブラウザでも解釈できるwidthheightプロパティのCSSに置き換わったのが確認できます。

では、実際にGulpでPostCSSとそのプラグインを使用するにはどうしたらよいのか、見ていきましょう。

var gulp = require('gulp');
var postcss = require('gulp-postcss');

gulp.task('css', function () { return gulp.src('src/css/*.css') .pipe(postcss([ require('postcss-size') ]) .pipe(gulp.dest('dest/css')); });

簡単ですね。postcssの引数の配列に使いたいプラグインを指定するだけです。gulp cssとコマンドを打てば、先ほどのCSSが生成されるようになります。

AutoprefixerもまたPostCSSのプラグインの一種なので、これを先ほどのタスクに追加したのが下記のコードです。Autoprefixerのオプションの設定にlast 2 versionsを設定していますが、基本的には配列の中にプラグインを足していくだけです。

gulp.task('css', function () {
  return gulp.src('src/css/*.css')
    .pipe(postcss([
            require('postcss-size'), 
            require('autoprefixer')({ browsers: ['last 2 versions'] })
        ])
    .pipe(gulp.dest('dest/css'));
});

今回はGulpでのタスク実行例でしたが、もちろんGruntなどの他のビルドツールにもPostCSSは対応していますので、みなさんの好きなビルドツールを使うことができます。

PostCSSのプラグインはおおまかに分類すると以下のようなカテゴリーのものがあり、現在100種類以上のプラグインが存在します。

cssnextでFuture CSS syntaxを先取る!

前述の通り、PostCSSには便利なプラグインがたくさんあり、フロントエンド開発の助けとなることでしょう。しかし、そういったことは既にSassでもできていることなので、メリットとは感じることも少ないかもしれません。個人的にPostCSSを使う一番の意味としてはFuture CSS syntaxを先取ることが可能であるということです。

例えば、CSSで変数を使いたい場合、Sassでは$記号を使い宣言しますが、言うまでもなくこれはSassによる独自構文であり、CSSの標準構文でありません。

/* 変換前のSass */
$brand-color: #88E18E;

.logo { color: $brand-color; }

/* 変換後のCSS */
.logo {
    color: #88E18E;
}

W3CのCSS Custom Properties for Cascading Variables Moduleに対応した現在の書き方だと以下のようになります。

/* 変換前のCSS */
:root {
    --brand-color: #88E18E;
}

.logo { color: var(--brand-color) }

そして、このCSSはpostcss-custom-propertiesプラグインを使えば、Sass同様、通常のCSS 2.1に対応したコードに変換することができます。

このような、新しい標準仕様CSSを使うことができるPostCSSプラグインをまとめたパッケージがcssnextです。これを使えば、postcss-custom-propertiespostcss-custom-selectors…のように、いちいち一つひとつプラグインを読み込まなくても大丈夫になります。

cssnextが内包しているFuture CSS syntaxプラグイン一覧

上記のパッケージを使えば、JavaScriptにおけるBabelのような使い方がCSSにおいても可能です。

ただ、今年策定されたECMAScript 6のように仕様が固まっているものが少なく、標準に沿った記述をしていても未来の仕様変更に伴い、コードを変更しなければならないといったリスクも存在します。

この点については、cssnextの作者であるMaxime Thirouin氏はcssnextはsemverを遵守しているので、プラグインをアップデートしたらコードが使えなくなるといったことは防げるとも述べています(互換性がない変更はメジャーアップデートするので、マイナーアップデートで止めれば危険性はないです。semverに関しては以前に取り上げたので次の記事を参照してください)。

なにはともあれ、個人的にはSassばかりに目を向けていた昨今なので、CSSの標準仕様に目を向けるという面でも、このようなプラグインを使うことに意味はあるかと考えます。さすがに、cssnextのパッケージに入っているプラグインの仕様すべて追いかけるのは厳しいので、自分が本当に使いたいFuture Specプラグインだけ選んで、それだけ気にかけるというのが落としどころかと思います。

PostCSSの普及

自分にとって必要なプラグインだけ選んで使えるPostCSSの使い勝手の良さから、利用者は増えています。『Sass and Compass for Designers』の著者であるBen Frain氏がSassからPostCSSに乗り換えたという記事は話題になりました。

また、フロントエンド開発者のためのコード共有サイトCodePenにおいても、SassやLessなどの他のCSSプリプロセッサ同様に、PostCSSをサポートするようになりました。

世界で最も使われているであろうCSSフレームワークBootstrapが、Version 4においてLessからSassに移行したと最近話題になりましたが、Version 5においては、さらにSassからPost CSSに移行するであろうと作者のMark Otto氏がTweetしたのも興味深いです。

Sassから乗り換えるべきか?

さて、これまでSass、Less、Stylusと群雄割拠のCSSプリプロセッサ時代において、ようやくSassで落ち着きそうなところに、また新しい技術が出てきて困惑しているあなた!大丈夫、僕もそうです!

PostCSSでできることはたいていSassでもできる(ないものはRubyで拡張しなければなりませんが…)ので、機能面で乗り換えるメリットというのはあまりないかもしれません。ただ、パフォーマンス面ではRuby Sassを使っている方ではあれば、少し考慮したほうがよいかもしれません。圧倒的にコンパイル速度が違います。

ただ2007年頃から開発されているSassは仕様的に安定していますし、コミュニティも成熟していますから、あなたの開発プロジェクトに新メンバーが入ってきてもSassであれば問題なく受け入れることがあっても、PostCSSで書かれたコードにはすこし驚く可能性があるでしょう(PreCSSというパッケージを使えば、PostCSSをのプラグインを使用しSassと似たようなコードを記述可能です)。

各自のプロジェクトに合わせて、技術を選択していけばよいでしょう。個人的には自分が1人でやっているプロジェクトであれば最近はPostCSSを採用しています。そもそも、Sassの機能においても@extend@mixinといったこともあまり使いませんし、Too muchな面は否めません。自分としては変数(postcss-custom-properties)と@importによるconcat(postcss-import)さえあれば問題ないといった印象だからです。

Webは常に進化し続けているものなので、それを構成しているコードも変わってくるのは当然でしょう。この際にPostCSSで最新仕様を先取ることで、未来のCSSについていろいろ考えるキッカケにしてもらえば幸いです。