PostcssとCSS Level 4の現状と今後のCSSプリプロセッサとの付き合い方を考える

この記事では私が2年以上PostCSSを実務で利用してきた、CSS Level 4の状況を振り返ります。

## CSS4を使うための環境について

まず、PostCSSが出てからcssnextを使ってCSS Level 4を使えるようにという記事が世に多く出回り、（ぼくの中で）実質的にpostcss-cssnextを使うことがPostCSSにおけるデファクトのようになっていました。

[PostCSSとcssnextで最新CSS仕様を先取り！ | HTML5Experts.jp](https://html5experts.jp/t32k/17235/)にも以下のようにアツいメッセージが書かれています。

> cssnextでFuture CSS syntaxを先取る！

これには非常に心を掴まれました。
また、[cssnext](http://cssnext.io/)が発信しているコピーも簡潔に心を捉えています。

> Use tomorrow’s CSS syntax, today.

これには**「トゥモローズシーエスエスをわれもトゥデイにユーズしたい！」**と、例の彼っぽく共感したものです。

それからというものの早3年の月日が流れました。

## 環境の変化 - postcss-cssnextは死にました

![image.png](https://qiita-image-store.s3.amazonaws.com/0/58800/4adc1dd2-42fa-f538-6766-2fbcd6eb8710.png)

詳しいことは、オーナーであるMoOxのブログに書いてあります。 [Deprecating cssnext](https://moox.io/blog/deprecating-cssnext/)
簡潔に言うと、MoOxはもうCSSを書くことがなくなり譲渡したいが、譲渡先が見つからなかったということ。
移行先は、postcss-preset-envをおすすめするということです。

そう、postcss-preset-envというものが存在していました。2014年の当時はまだbabel-preset-envなどがフロントエンドの人にとって定番となっていませんでしたが、今となっては、モジュールとして利用できるものの必要なアセット一式そろえた環境だぜ！みたいなものをpreset-envとして用意するというのは非常に馴染み深いはずなので、これはむしろPostCSSとcssnext使おうといっていた時代よりはよっぽど理解しやすい形になったでしょう。

（え？`@babel/preset-env`って名前に変わっただろって？知らんな）

## postcss-preset-envとは何か

先にも書きましたが、基本的な概念は`babel-preset-env`のPostCSS版って認識よいです。（と思っています）

[postcss-preset-env](https://preset-env.cssdb.org/)

なお、表示はひかえめになったもののコピーは変わっていません。

> Use tomorrow’s CSS today.

「トゥモローズシーエスエスをトゥデイにユーズしたいよな？」ってことです。

ちなみに、Twitterを見る限りcssnext死亡のお知らせを私が認知したのは2018年6月頃でした。

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">postcss-cssnextはpostcss-preset-envになったのか</p>&mdash; なる / Studio Opt (@naru0504) <a href="https://twitter.com/naru0504/status/1004602951422263296?ref_src=twsrc%5Etfw">June 7, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

それでもnpm周辺の変更は余裕のあるときにと思っていたので、書き換えは8月になっていました。
ここが最後にgulpと共にいた日だった。v4リリースされたのもチェックしておらぬ……。

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">postcss-cssnextがもうdeprecatedなので、リプレイスした。postcss-preset-envに移行するだけでもよかったけど、gulpを外そうと思ったので、npm scriptsでpostcss-cli使ってプラグインとしてpostcss-preset-envを読み込ませた。<a href="https://t.co/BGKKSO6187">https://t.co/BGKKSO6187</a></p>&mdash; なる / Studio Opt (@naru0504) <a href="https://twitter.com/naru0504/status/1028950750825607174?ref_src=twsrc%5Etfw">August 13, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

今もだが、当時はpostcss-preset-envを使った日本語情報はものすごく少ない印象だった。というか、vue-cliやらNuxt.jsとセットな情報とかしかない印象あったので、もっと上に包括した環境を用意していることが多いんだと思った。
フレームワークなどにセットで入っているCSSプリプロセッサを利用したりしているんだろう。


## 便利そうなPostCSSプラグインたちとそのリスク

さて、お察しの通り、PostCSSにはたくさんのプラグインがあり、どの機能を使うかに合わせてスキに入れていくことができます。

[PostCSS.parts](https://www.postcss.parts/) といったサイトもあり、どんなモジュールがあるか見てみるのがよいでしょう。

しかし、これらがすべてCSSの次期仕様でブラウザ上でネイティブに動くようになるわけではありません。
最たる例としては、`postcss-simple-vars`です。このプラグインは、Sassライクな記法の変数機能を提供しています。

また、別の例を挙げると、ネストを利用する機能を提供するプラグインは似たようなものが2つあります。

- [postcss-nested](https://github.com/postcss/postcss-nested)
- [postcss-nesting](https://github.com/jonathantneal/postcss-nesting)

このネストのプラグイン、どちらが仕様に近いかというと後者のpostcss-nestingです。
仕様を追って何を使うか判断……とてもめんどくさそうですよね。
そんなときに戻ってくるのがやっぱりpostcss-preset-envなのです。

postcss-preset-envが利用しているプラグインこそがpostcss-nestingなのです。

## CSS仕様のステージに合わせて使えるのがpostcss-preset-envの強み

postcss-preset-envはオプションがあります。

- Stage 3 +
- Stage 2 +
- Stage 1 +
- Stage 0 +

3ほど実装される可能性が高いものです。（悲しいことに真逆の内容を書いている記事も見受けられます。）

もっとちゃんと言うと、CSSDBというところから情報を取って来ています。
W3C基準で表にしてみました。

| Stage | W3C基準 |
| :--- | :--- |
| Stage3 | 勧告候補 |
| Stage2 | 草案 |
| Stage1 | 初期草案 |
| Stage0 | アレなやつ |


とはいえ、これでわからない人も多いと思うのでめちゃくちゃ雑に言ってはいけないことを言います。
stage 3+の設定であれば、別にコンパイルとかする必要もなく各ブラウザのlatest2版くらいは通ります。

postcss-preset-envでは次のようなものがあります。

- all property
- break porperties
- custom properties
- font-variant property
- gap properties
- media query ranges

さて、注目すべきはやはり`custom properties`です。
いわゆる変数です。

Can I Useで対応状況を見ると以下のとおりです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/58800/5dc80017-0d7f-7323-3b09-d821ec6935f6.png)

CSSにおける変数は、IEを除いてブラウザネイティブに通ります。

ところで、カスタムプロパティを実現してきた、postcss-custom-propertiesには、preserveというオプションがあります。

```
postcssCustomProperties({
  preserve: false
});
```

このオプションでは次のように :root: 要素に定義されたカスタムプロパティをコンパイル後に残すか残さないかの選択ができます。

```
:root {
  --color: red;
}
```

デフォルトでは残ります。
これは変数はあくまでもコンパイル前の概念という人にはとても不思議に思えると思います。

ですが、ネイティブにブラウザが理解できるようになっているものなので、あくまでコンパイル後のものはすでに古いブラウザ対策でしかないです。

そういえば言い忘れていましたが、変数をJavaScriptで操作するなんてことも当然できます。

## Sassがもう必要ないかもと考えることもできる。

Lessが私にとっての初のCSSプリプロセッサだったのですが、その一番の利用したい欲求は変数でした。その変数は、custom propertiesという形となり、ブラウザで利用できます。

ネストと言っている人も周囲にいた記憶があるので書いておくと、コンパイル後のCSSの管理がアンコントローラブルになりそうだなと、ふわふわした抵抗感を抱いていたのであまり使っていませんでした。

その後、[Trello CSS Guideline](https://qiita.com/naru0504/items/5427f3795171c540ed91)を翻訳しました。（Less前提ですが、基本的にSassに置き換えても問題ないので、話をわかりやすくそうします。）

この記事では**セレクタがコンパイル後にネストされていない範囲でしかネストを使うべきでない。**といった旨が繰り返し説かれています。 （この説明をかつてできなかったのだけども、なんて言ったらよいのかで言語化できたことが誇らしいです。）

上記も含めて、Sassの機能をフルに使うことなく、運用体制に合わせて使用される機能を選択するべきだという考え方があります。（もちろん、一方で機能として提供されているんだから使えばよいって考え方もありますが。）

## 今後のCSSプリプロセッサとの付き合い方

さて、ここまでつらつらと書いてきたことを踏まえて、今後CSSプリプロセッサをどう扱うかを考えます。

### Sassを部分的に利用する

変数はcustum-propertiesの形式に乗っ取り、他の利用したい機能を利用するという方法です。
既存のプロジェクトをモダンな形に近付けるための一歩としてやるのは意味があります。

### PostCSS + postcss-preset-envを利用する

PostCSSを利用する明確な基準としてpostcss-preset-envを利用します。
Level0になると、実装されるか怪しいものもあるが、applyルール（いわゆるmixin）はこのレベルでないと使えなかったりします。
他のプラグイン何でも使えばよい方式は、個人的にはそれはもうSassの方が優位性高いのではとなるので書きません。

### 生のCSSを使う

最近はスコープを持たせたCSS構造のプロジェクトに関わることもあって、そのプロジェクトではSassが使われていたのだが必要ないなという印象がとても強かったです。
思うに、スコープ切られていると細分化された中で最適化していけばよいという思考が働いたのだと思います。
変数を使いたい欲求は一方であったので、グローバルな扱いのところでカスタムプロパティ定義しておけば十分やっていけるなと思いました。

## Sassがデファクトスタンダードでありつづけることを支える基盤

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">置き場所悪かったかも。 <a href="https://twitter.com/hashtag/FROKAN?src=hash&amp;ref_src=twsrc%5Etfw">#FROKAN</a> <a href="https://t.co/X352PxV6L6">pic.twitter.com/X352PxV6L6</a></p>&mdash; LINLY (@linlymatsumura) <a href="https://twitter.com/linlymatsumura/status/973878184302190593?ref_src=twsrc%5Etfw">March 14, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

[Frontend de KANPAI! #03](https://frokan.connpass.com/event/79568/)のときのアンケートTweetからわかりますが、Sassはこれだけのシェアを得ています。ここまでの偏りがあれば、統計的に有意な母数かどうかとか気にしないでほしいくらい、とにかくSassは使われています。（ところで、このボード描いたのはあの方なんだと思うのだが相変わらずグラフィックのコンテンツ力が高い）


なぜSassを使っているのか、という問で多く聞けるのは、そもそも入っていたということではないでしょうか。
というのも、CSSの設計を専門とした人を中心にプロジェクトのアーキテクチャ全体を設計することは少ないというファクトがあるからと考えています。

Nuxt.jsやVue-cliがPostCSSの利用環境をドキュメント上で提供しているので前述したような日本語情報があったんだと思います。

Bootstrap v5やMaterialデザインを実現するフレームワークがPostCSSを利用してCSS Level4志向にならないと現状は変わらないでしょう。

[マテリアルデザインをサクッと実装できるCSSフレームワーク6選【2017年版】](https://www.webprofessional.jp/free-material-design-css-frameworks-compared/) の記事が昨年のものですが、非常にわかりやすくプリプロセッサはすべてSassですね。

今後も継続的にPostCSSを利用していくつもりなので、何か進展あれば追って記載したいと思います。
ありがとうございました。