フロントエンド開発環境の続きです。前回はHTMLHintでHTMLの構文チェックしました。今回はAutoprefixerでCSSのベンダープレフィックスを自動で付けてみます。ベンダープレフィックスはとても悩ましい存在で、これを付けるのが面倒であるために、その機能を使うのを諦めたり、逆にこれに対応していないブラウザへへの対応を諦めたりしてきました。自動的に付けてくれるなら辛くない!それでは行きましょう!
【目次】
- ベンダープレフィックスとは何か
- ベンプレの何が辛いのか
- Autoprefixerのインストールの準備
- AutoprefixerはPostCSSのプラグインだった!
- Autoprefixerをインストール(Gulpで実行する)
- gulpfile.jsにAutoprefixerの設定を書く
- Autoprefixer実行(真っ赤な注意書き。。)
- browsersオプションをbrowserslistオプションに書き換えてみる
- browserslistオプションから固有のバージョンをなくしてみる
- 最後に
前回の記事
※参考:【HTML】HTMLHintで構文チェックを事始める - クモのようにコツコツと
※参考: qiita.com
ベンダープレフィックスとは何か
ベンプレ(ベンダープレフィックスの略*1)辛い。。
ベンプレとは何か。CSSのプロパティの頭に付ける接頭辞。
ベンダープレフィックス(接頭辞)とは、ブラウザベンダーが独自の拡張機能を実装したり、草案段階の仕様を先行実装する場合に、 それが拡張機能であることを明示するために付ける識別子のことです。
主要ブラウザのベンダープレフィックス
- -moz- …… Firefox
- -webkit- …… Google Chrome、Safari
- -o- …… Opera
- -ms- …… Internet Explorer
ちなみに、Opera用の-o-
については今は-webkit-
でいけるようなので既に過去の書き方らしい。Chromeと同じBlinkというHTMLレンダリングを使用している。
そしてそして、Edgeも今はBlinkになったので-webkit-
でいけるらしい!そのため、IEさえ市場から消えてくれれば今後はこうなりますな。
- -moz- …… Firefox
- -webkit- …… Google Chrome、Safari、Edge、Opera
-o- …… Opera-ms- …… Internet Explorer
FireFox(-moz-
)とそれ以外(-webkit-
)の世界。
※参考:そのベンダープレフィックス、いつまでつけてるの? - Qiita
ベンプレの何が辛いのか
いやー、それにしてもベンプレを付けるのは辛い作業。何がそんなに辛いのか・
例えばCSS3で追加されたグラデーション(linear-gradient()
)。
bg { background-image: linear-gradient(to bottom, #8BCC8E 0%, #A7F5AB 100%); }
昔はCSSの背景色は1色ベタ塗りでグラデーションは画像を配置する必要があったが、これのおかげで画像なしでグラデーションの表現ができるようになった。とても助かる機能です。
しかしながら、この機能が追加された当初は対応ブラウザが少なくこんな書き方をしていた。
br { background-image: -webkit-gradient( linear, left top, left bottom, color-stop(0, #8BCC8E), color-stop(1, #A7F5AB) ); background-image: -o-linear-gradient(bottom, #8BCC8E 0%, #A7F5AB 100%); background-image: -moz-linear-gradient(bottom, #8BCC8E 0%, #A7F5AB 100%); background-image: -webkit-linear-gradient(bottom, #8BCC8E 0%, #A7F5AB 100%); background-image: -ms-linear-gradient(bottom, #8BCC8E 0%, #A7F5AB 100%); background-image: linear-gradient(to bottom, #8BCC8E 0%, #A7F5AB 100%); }
※参考:CSS Gradient Generator | CSS3 Factory
なんじゃこりゃあ!!*2
一番下にベンプレ無しのプロパティを書いているが、その上に「ベンプレなしのプロパティに非対応のブラウザは代わりにベンプレ付きの値の方を読んでね」と防衛策を打っているわけですな。(if文みたいなものですな)
いや、まあ、頭に-webkit-
とか付けるだけならまだ単純作業なのでいいんですよ。コピペして接頭辞付けるだけなので。
ベンプレは何が辛いって修正が辛い!ベンプレ書いた分だけ何箇所も書き直さないといけないっ!!(しかも、種類によっては値の書き方も微妙に違うことがあるから注意が必要。。)
ベンプレを付けたくないがために未対応ブラウザを切り捨てたり、逆にその機能の対応を諦めたり、でも付けるのも辛い。不幸せの連鎖。。
ちなみに今はlinear-gradients()
はほぼ全ブラウザ対応しているのでこんなに書かなくても大丈夫です。
※参考:Can I use... Support tables for HTML5, CSS3, etc
ベンプレはあくまでブラウザが正式対応してくれるまでの間の過渡期的な書き方なんですな。
ただし!IEは進化を止めてメンテナンスしかしない余生ブラウザなので機能追加は期待できない!!先の記事にもあるように、ベンプレを付けようが付けまいが全く対応してくれてない機能は動かない!
※参考:そのベンダープレフィックス、いつまでつけてるの? - Qiita
あと、CSS3とは無関係なブラウザ独自使用にはベンプレ必要な部分もあるようで、今後も完全になくなるわけではないようだ。
Autoprefixerのインストールの準備
案件によってはベンプレを付けてでもそのブラウザのユーザーに対応しよう、ということがどうしてもあるでしょう。そういった時に、手動ではなく自動でベンプレを付けてくれると嬉しい。
それを実現してくれるのが「Autoprefixer」らしい。そうだ Autoprefixerで 自動ベンプレ付けよう!
※参考:GitHub - postcss/autoprefixer: Parse CSS and add vendor prefixes to rules by Can I Use
早速インストールする。
まず、Node.jsとnpmは既に入っている前提(ターミナルで下記を叩くとバージョン番号が出る)
node -v npm -v
Autoprefixerを入れるフォルダを作る。今回は「autoprefixer_test」とした。
cdコマンドでautoprefixer_testフォルダに移動。
cd (フォルダのパス)/autoprefixer_test
package.jsonの作成
npm init -y
ここまでいつもの流れ。
AutoprefixerはPostCSSのプラグインだった!
Autoprefixerというのは以前、「AltCSS」の記事で紹介した「PostCSS」のプラグインの一つらしい。(この記事では「NextCSS」というプラグインを使っている)*3
※参考:【LESS, SCSS, Sass, Stylus, PostCSS】 AltCSS 事始め - クモのようにコツコツと
PostCSSはプラグインを組み合わせてプロジェクトごとに最適な仕様にする、という思想。そのため、Sassなどの他のAltCSSとも競合せずに一緒に使うことができるらしい!
Sassの代わりではない
はい、これです。
この記事で言いたいことは、これがほぼ全てです。僕は、PostCSSを、コンパイルしてCSSを生成するSassのようなものだと思っていました!
ですが、そもそもSassを使っていたので全くと言っていいほど必要性を感じてませんでした。PostCSSというくらいなので、ポストプロセッサーとして、生成されたCSSに対して後処理をすることに使えます。
(導入するプラグインによっては、Sassのようなプリプロセッサー的な使い方も出来ます)そのため、使い慣れているSassでコードを書きつつ、コンパイル後のCSSの最適化にPostCSSの様々なプラグインを使用するといったことが可能です!
※参考:SassとPostCSSを組み合わせて作るCSS開発環境 | Tips Note by TAM
これ、自分も全く同じ印象を持っていたのでビックリした!そうかー、Sassとかは「プリプロセッサー」でPostCSSは「ポストプロセッサー」。違うタイミングで実行できるから共用可能なんだ。
そのため、SassでコンパイルしたCSSにAutoprefixerでベンプレを付けるという使い方もできるわけだ。
Autoprefixerをインストール(Gulpで実行する)
Autoprefixerを実行する方法はいくつかあるようだ。
- Gulp(タスクランナー)
- Webpack(バンドルツール)
- CSS-in-JS(ReactのようにJSのモジュールにHTMLもCSSも書く)
- PostCSS CLI(PostCSSの実行環境)
※参考:GitHub - postcss/autoprefixer: Parse CSS and add vendor prefixes to rules by Can I Use
今回はこちらの記事を参考にGulpで実行できるようにしてみる。
※参考:CSSベンダープレフィックス-webkit-を今この瞬間に辞める為のAutoprefixerの導入 - Qiita
以下の3つのツールをローカルにインストールする。
- gulp
- gulp-postcss
- autoprefixer
gulp-postcssがGulpでPostCSSを実行できるオプション
インストール!
npm i -D gulp gulp-postcss autoprefixer
`package.jsonに追記された!
"devDependencies": { "autoprefixer": "^9.7.4", "gulp": "^4.0.2", "gulp-postcss": "^8.0.0" }
gulpfile.jsにAutoprefixerの設定を書く
フォルダ直下にgulpfile.js
を作成して、Autoprefixer設定を書く。
まず、先ほどのツールを読み込む。
const gulp = require("gulp"); const postcss = require("gulp-postcss"); const autoprefixer = require("autoprefixer");
- 変数
gulp
にrequire()
でgulp
を読み込み - 変数
postcss
にrequire()
でgulp-postcss
を読み込み - 変数
autoprefixer
にrequire()
でautoprefixer
を読み込み
Gulpの設定を書く。
gulp.task("default", function () { return gulp.src("src/test.css") .pipe(postcss([ autoprefixer({ browsers: [ "last 2 versions", "ie >= 11", "Android >= 4" ], cascade: false }) ])) .pipe(gulp.dest("benpre")); });
gulp.task()
でgulpの設定を書く。第一引数はdefault
、第二引数は無名関数- 無名関数の中、
return
で設定を返す。gulp
の後にメソッドチェーンが続く src()
で対象ファイルを指定。src
フォルダの中のtest.css
- 1つ目の
pipe()
の引数にpostcss()
で、postcss()
の引数は配列
配列の値はautoprefixer()
で、autoprefixer()
の引数はオプションで連想配列
連想配列の中、browsers
オプションの値は配列
配列の値はブラウザの設定。2つ前のバージョン、IE11以上、Android4以上
cascade
オプションの値はfalse
- 2つ目の
pipe()
の引数、gulp.dest()
でファイルのエクスポート先を指定。benpre
フォルダ。
cascade
オプションは公式サイトによると
cascade (boolean): should Autoprefixer use Visual Cascade, if CSS is uncompressed. Default: true
cascade(boolean):CSSが圧縮されていない場合、AutoprefixerはVisual Cascadeを使用する必要があります。 デフォルト:true
うーん、よくわかんない。。
こちらのサイトによると結果は基本的にtrueでもfalseでも同じだが、インデントの見栄えに違いがあるっぽい。
※参考:css - gulp-autoprefixerのカスケードオプション - プログラミングQ&A - BugInfo
以上の設定を書き終えると、ベンプレの付与がgulp
で実行できるようになる。
npx gulp
(ローカルインストールのため、頭にnpx
を加える。
Autoprefixer実行(真っ赤な注意書き。。)
フォルダ直下にtest.css
に先程のグラデ設定を書いてみる。
bg { background-image: linear-gradient(to bottom, #8BCC8E 0%, #A7F5AB 100%); }
Autoprefixer実行!
npx gulp
むむっ、実行中になんだか真っ赤な注意書きが…
Replace Autoprefixer browsers option to Browserslist config. Use browserslist key in package.json or .browserslistrc file. Using browsers option can cause errors. Browserslist config can be used for Babel, Autoprefixer, postcss-normalize and other tools. If you really need to use option, rename it to overrideBrowserslist. Learn more at: https://github.com/browserslist/browserslist#readme https://twitter.com/browserslist
なんぞこれ?翻訳すると
Autoprefixer browsersオプションをBrowserslist configに置き換えます。 package.jsonまたは.browserslistrcファイルでbrowserslistキーを使用します。 ブラウザオプションを使用すると、エラーが発生する可能性があります。 Browserslistの構成 Babel、Autoprefixer、postcss-normalizeなどのツールに使用できます。 本当にオプションを使用する必要がある場合は、BrowseBrowserlistをオーバーライドするように名前を変更します。 詳細については: https://github.com/browserslist/browserslist#readme https://twitter.com/browserslist
browsers
オプションはBrowserslist
オプションに書き換えておくれと。
Browserslist
オプションの詳細はこちら。
※参考:GitHub - browserslist/browserslist: 🦔 Share target browsers between different front-end tools, like Autoprefixer, Stylelint and babel-preset-env
注意書きの下にはフィニッシュの文字が・
[10:02:09] Finished 'default' after 124 ms
一応、benpre
というフォルダが作られて、中にtest.css
が書き出されている! しかし、Autoprefixerを実行するたびにこの赤い文字を見るのはあまり気分がよろしくないw
新しい書き方にも対応してみようかと。
browsersオプションをbrowserslistオプションに書き換えてみる
browsersオプションをbrowserslistオプションに書き換え、こちらの記事が参考になった!
まずgulpfile.js
のbrowsers
オプションを削除する。
gulp.task("default", function () { return gulp.src("src/test.css") .pipe(postcss([ autoprefixer({ browsers: [ cascade: false }) ])) .pipe(gulp.dest("benpre")); });
オプションをpackage.json
に移動してbrowserslist
にリネイムしてみる
"browserslist": [ "last 2 versions", "ie >= 11", "Android >= 4" ]
Autoprefixer実行!
npx gulp
おお、今度はエラーが出ずに成功!
benpre
フォルダの中のtest.css
はこうなった。
bg { background-image: -webkit-gradient(linear, left top, left bottom, from(#8BCC8E), to(#A7F5AB)); background-image: -webkit-linear-gradient(top, #8BCC8E 0%, #A7F5AB 100%); background-image: linear-gradient(to bottom, #8BCC8E 0%, #A7F5AB 100%); }
最初のベンプレの例に比べて、-webkit-
のみでスッキリした!
browserslistオプションから固有のバージョンをなくしてみる
さらに、browserslist
オプションの設定を変えてみる。こちらの記事の解説がわかりやすい!
※参考:Autoprefixerの対象ブラウザの選び方 | Rriver
まず、browserslist
オプションは何も書かないとデフォルトではこんな設定らしい。
> 1%, last 2 versions, Firefox ESR
「1%以上のシェアのブラウザ、2バージョン前のブラウザ、最新のFirefox ESR版 」という意味になる。
AutoprefixerはCan I Use のブラウザ・サポート情報とStatCounterの全世界のブラウザ利用状況データを参照してBrowserslistの記述に当てはまるブラウザを抽出します。
ブラウザの対応状況を自動で見に行ってくれるのは嬉しい!我々の方ではバージョン番号の固有値を入れる必要がないということだ。
「Firefox ESR版」ってなんぞ?と思って調べると今のFirefoxは「Quantum」でESRは旧型らしい。
Firefox ESRの “ESR” は、Extended Support Releaseの略。
Mozillaが提供している、教育機関、公共機関など一括導入している法人に向け、延長サポートしている旧型のFirefoxだ。
※参考:「Firefox Quantum」と「Firefox ESR」 2匹の火狐を使い分ける!
Edgeに対するIEみたいな位置づけねw
先程の記事に戻ると、browserslist
オプションの値がどのブラウザをカバーするかはこのサイトで確認ができる。
※参考:browserl.ist: A page to display compatible browsers from a browserslist string.
そんでもって%
は世界のシェアなので日本限定にする場合はin JS
を加える。
> 1% in JP, last 2 versions, Firefox ESR
うむ、IE10〜が対象になっているので、これで十分かな?
※参考:browserl.ist: A page to display compatible browsers from a browserslist string.
では、`packege.jsonを書き換える。JSONの形式にする。
"browserslist": [ "> 1% in JP", "last 2 version", "Firefox ESR" ]
Autoprefixer実行!
npx gulp
benpre/test.css
の実行結果。
bg { background-image: -webkit-gradient(linear, left top, left bottom, from(#8BCC8E), to(#A7F5AB)); background-image: linear-gradient(to bottom, #8BCC8E 0%, #A7F5AB 100%); }
お、-webkit-linear-gradient()
がなくなった!この設定だと不要ということか。
最後に
ということで、人類を悩ませてきたベンプレ手動付与を自動化することができました!これはJSでいうBabel(ES6〜の記法をES5に変換する)のような位置づけに感じました。
Gulpで対象ファイルと実行ファイルを分けることで、対象ファイルの時はベンプレを全く気にせず、実行後にベンプレの値を変更することもありません。完全に切り分けられた世界です。
また、browserslist
によって固有のバージョン番号ではなく相対的な%や世代を常に調べてくれるのもメンテナンスのしやすさを感じました!
CSSデバッグではもう一つやりたいテーマがあって、プロパティの書き順を自動でソートしたい。こちらも方法を調べています。それではまた!
※参考: qiita.com