CSSベンダープレフィックス-webkit-を今この瞬間に辞める為のAutoprefixerの導入

ブラウザの進化が早い昨今、CSSのベンダープレフィックス(`-webkit-`や`-ms-`)が必要なプロパティと不要なプロパティが入り乱れています。必要なベンダープレフィックスのみを付与しようとした場合、途端にコード量が倍増し、メンテナンス性が低下し、バグの温床となります。この**ベンダープレフィックス地獄を解消するAutoprefixerをGulpやwebpackで使う方法**を紹介します。

# 今なお続くベンダープレフィックス地獄
角丸を表現する`border-radius`プロパティはIE 11を含む全ての主要ブラウザで、ベンダープレフィックス無しで使えます。([Can I use border-radius](http://caniuse.com/#search=border-radius))

一方で、ボックスレイアウトモジュールの為の`flexbox`プロパティやテキスト要素を変形する`transform`プロパティ等では、Android 4.4以下等一部のブラウザではベンダープレフィックスが必要です。

しかし、毎日刻々と変化するブラウザの仕様を追い続け、必要なベンダープレフィックスだけを付与していくのは大変な労力です。また、ベンダープレフィックスを全てつけて解決を試みるコードを見かけます。確かにブラウザによるレイアウト崩れは防げるものの、一つの値を編集するだけで通常の何倍もの作業が発生し、ストレスとタイピングミスが増えるので辞めるべきです。


```css:ベンダープレフィックス地獄の例
div {
     -webkit-transform: scale(2);
         -ms-transform: scale(2);
             transform: scale(2);
}
```


# ベンダープレフィックス地獄を解決するAutoprefixer
これらのベンダープレフィックス地獄は[Autoprefixer](https://github.com/postcss/autoprefixer)を使うことで解決できます。**Autoprefixerは最新のブラウザ実装状況をまとめたサイト「[Can I use](http://caniuse.com/)」の情報を使用し、必要なベンダープレフィックスのみを付与する為のツール**です。

また、ベンダープレフィックスの適用範囲を細かく指定することが可能で、例えば下記のような指定ができます。

- 各ブラウザの最新バージョンと一つ前のバージョンで必要なベンダープレフィックスのみ
- IEは11以上、Android標準ブラウザは4以上で必要なベンダープレフィックスのみ
- シェアが5%以上のブラウザで必要なベンダープレフィックスのみ

簡単な変換を通して、Autoprefixerの設定手順を紹介します。

# 変換用のCSS
プロジェクトフォルダに`src`フォルダを作成し、テスト用のstyle.cssファイルを作成します。

```
projectFolder/
　└ src/
　　 └ style.css
```

style.cssの中には下記のようなスタイルを設定しました。`border-radius`プロパティや`display`プロパティに、自動で必要なベンダープレフィックスを付与します。

```css:style.css
main {
  border-radius: 5px;
  display: flex;
}
```

Autoprefixerはwebpack、Gulp、CLIなど様々な環境で使えます。本エントリーではwebpackとGulpでの設定方法について解説します。自身の環境にあったものをご覧ください。

- [GulpでAutoprefixerを使う](https://qiita.com/tonkotsuboy_com/items/377913c51b1ac00deffe#gulpでautoprefixerを使う)

- [webpackでAutoprefixerを使う](https://qiita.com/tonkotsuboy_com/items/377913c51b1ac00deffe#webpackでautoprefixerを使う)

- [ParcelでAutoprefixerを使う](https://ics.media/entry/19580)

# GulpでAutoprefixerを使う

この章ではGulpとの連携方法について解説します。Gulpの詳しい導入方法や使い方については記事「[絶対つまずかないGulp入門(2018年版) – インストールとSassを使うまでの手順 - ICS MEDIA](https://ics.media/entry/3290)」を参照してください。

## 環境のセットアップ
プロジェクトフォルダにて、下記コマンドを使って初期化します（※1）。

```bash
npm init -y
```

必要なモジュールをインストールします。Autoprefixerは「[PostCSS](https://postcss.org/)」の一部なので、本体「[autoprefixer](https://www.npmjs.com/package/autoprefixer)」とあわせてGulpでPostCSSを使うための「[gulp-postcss](https://www.npmjs.com/package/gulp-postcss)」をインストールします。

```bash
npm i -D gulp gulp-postcss autoprefixer
```

※ Gulp用のAutoprefixerプラグイン「[gulp-autoprefixer](https://www.npmjs.com/package/gulp-autoprefixer)」もありますが、こちらは暫くメンテナンスされておらず、内部で使われているAutoprefixerは古いです。

## タスクの定義
Gulpタスク用にgulpfile.jsを作成して下記のタスクを定義します。☆部分がベンダープレフィックスをどのように設定するかを指定する部分です。他の指定方法は「[BrowserslistのREADME](https://github.com/ai/browserslist/blob/master/README.md)」を参照するとよいでしょう。例えば、「IE 11以上、Androidは4以上、その他は2バージョン」を指定してみます。

```js:Gulp
const gulp = require("gulp");
const postcss = require("gulp-postcss");
const autoprefixer = require("autoprefixer");

gulp.task("default", function () {
  return gulp.src("src/style.css")
    .pipe(postcss([
      autoprefixer({
        // ☆IEは11以上、Androidは4.4以上
        // その他は最新2バージョンで必要なベンダープレフィックスを付与する設定
        browsers: ["last 2 versions", "ie >= 11", "Android >= 4"],
        cascade: false
      })
    ]))
    .pipe(gulp.dest("dist"));
});
```

上記のタスクを実行するには、下記コマンドを使います（※2）。

```bash
$ npx gulp
```


## 必要なベンダープレフィックスが付与された
Autoprefixerが適用されたCSSは下記です（上記のタスクで`dist`フォルダにstyle.cssが書き出されます）。`border-radius`プロパティはベンダープレフィックスが付与されず、`flex`プロパティのみに必要なベンダープレフィックスが付与されます。

```css:必要なベンダープレフィックスのみが適用されたstyle.css
main {
  border-radius: 5px;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}
```

ちなみに、`browsers: [(中略), "ios_saf >= 8"],`のように、iOS Safari 8を対象にした場合、`-webkit-flex`と旧仕様のプロパティが追加されます。

```css:iOSのSafari8を対象にした場合
main {
  border-radius: 5px;
  display: -webkit-box;
  display: -webkit-flex; /* 旧仕様が追加された */
  display: -ms-flexbox;
  display: flex;
}
```

# webpackでAutoprefixerを使う

この章ではwebpackとの連携方法について解説します。webpackの詳しい導入方法や使い方については以下の記事も参照ください。

- [最新版で学ぶwebpack 4入門 - JavaScriptのモジュールバンドラ](https://ics.media/entry/12140)
- [最新版で学ぶwebpack 4入門 - スタイルシート(CSSやSass)を取り込む方法](https://ics.media/entry/17376#postcss-autoprefixer)

webpackの初期設定では、`src`フォルダの`index.js`で`import`した各ファイルをバンドル（一つにまとめること）します。次のように`index.js`を追加します。

```
projectFolder/
　└ src/
　　 └ style.css
　　 └ index.js
```

`index.js`内でCSSファイルを読み込みます。

```js:index.js
// import文を使ってCSSファイルを読み込む。
import './style.css';
```

プロジェクトフォルダにて、下記コマンドを使って初期化します。

```bash
npm init -y
```

必要なモジュールをインストールします。Autoprefixerは「[PostCSS](https://postcss.org/)」の一部なので、本体「[autoprefixer](https://www.npmjs.com/package/autoprefixer)」とあわせてGulpでPostCSSを使うための「[postcss-loader](https://www.npmjs.com/package/postcss-loader)」をインストールします（※1）。

```bash
npm i -D webpack webpack-cli style-loader css-loader postcss-loader autoprefixer
```

## webpack.config.jsの定義

webpack.config.jsを作成し、下記の設定を記述します。☆部分がベンダープレフィックスをどのように設定するかを指定する部分です。他の指定方法は「[BrowserslistのREADME](https://github.com/ai/browserslist/blob/master/README.md)」を参照するとよいでしょう。例えば、「IE 11以上、Androidは4以上、その他は2バージョン」を指定してみます。


```js:webpack.config.json
module.exports = {
  mode: "development",
  module: {
    rules: [
      {
        test: /\.css/,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              url: false,
              importLoaders: 1
            },
          },
          // PostCSSのための設定★
          {
            loader: "postcss-loader",
            options: {
              plugins: [
                // Autoprefixerを有効化
                require("autoprefixer")({
                  // ☆IEは11以上、Androidは4.4以上
                  // その他は最新2バージョンで必要なベンダープレフィックスを付与する設定
                  browsers: ["last 2 versions", "ie >= 11", "Android >= 4"]
                })
              ]
            }
          }
        ]
      }
    ]
  }
};
```

下記コマンドでwebpackを実行すると、Autoprefixerによるベンダープレフィックスの自動付与が行われます。

```bash
npx webpack
```

## 必要なベンダープレフィックスが付与された
Autoprefixerが適用されたCSSは下記です。`dist`フォルダのmain.js内のCSS部分をぬきだしたものです。

```css:必要なベンダープレフィックスのみが適用されたスタイル
main {
  border-radius: 5px;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}
```

- [main.jsコード内の該当箇所](https://github.com/tonkotsuboy/kanobox/blob/eba989c94970024aa93cbe53177f5cb038aa41ff/180710_first_autoprefixer/1_webpack/dist/main.js#L96)


# ParcelでAutoprefixerを使う
ParcelでAutoprefixerを使う方法については、次の記事を参照ください。webpackやGulpの場合と異なり、設定ファイルが不要なのでラクです。

- [Sassのモダンなコンパイル環境が3分で作れるParcel入門 \- 独自設定ファイルは不要 \- ICS MEDIA](https://ics.media/entry/19580)

# 対象ブラウザは外部ファイルに記述もできる
webpack、Gulpの場合共に、対象ブラウザは`package.json`や`.browserslistrc`というファイルに記述することも可能です。Autoprefixer以外のツールと対象ブラウザの設定を共有したい場合に役立ちます。この場合は`webpack.config.js`や`gulpfile.js`でのブラウザ指定は不要です。

## `package.json`の場合

```json
{
  "dependencies": {
    "autoprefixer": "^8.6.4"
  },
  "browserslist": [
    "last 2 versions",
    "ie >= 11",
    "Android >= 4"
  ]
}
```

## `.browserslistrc`の場合

```text:.browserslistrc
> 0.5%
last 2 versions
ie >= 11
Android >= 4
```

# Grid対応も強力
CSS GridでIE 11対応をする場合も、Autoprefixerは強力です。次の記事で詳しく解説しましたので参照ください。

- [AutoprefixerがパワーアップしてCSS GridのIE 11対応がバリ楽になってた \- Qiita](https://qiita.com/tonkotsuboy_com/items/bce73685cd6b1ea511dc#_reference-89a98a1045e622321fcb)
- [CSS Gridのgap（grid-gap）が遂にIE 11でも再現できるように。Autoprefixerが待望のアップデート](https://qiita.com/tonkotsuboy_com/items/10fc250ac579a32e9ee9)

# もうベンダープレフィックスで消耗するのは辞めましょう
**美しいCSSコードとは、ベンダープレフィックスが必要最低限だけ付与されたコード**です。Autoprefixerに出会う前は、逐一プロパティ毎のベンダープレフィックス必要性を調べ、適用していくという大変な苦労を強いられました。Autoprefixerを使って面倒なベンダープレフィックスの処理は全て自動化し、ストレスとタイピングミスから解放されたCSSコーディングを今日から行いましょう。

※1 `-y`や`-D`について不明であれば、[GulpやSassを使う時に覚えて幸せになったnpmの便利な使い方](https://qiita.com/tonkotsuboy_com/items/32b56eef5c8114cae43c)を参照ください。

※2 npxについて不明であれば、「[npm 5\.2\.0の新機能！ 「npx」でローカルパッケージを手軽に実行しよう ](https://qiita.com/tonkotsuboy_com/items/8227f5993769c3df533d)」を参照ください。