【BiTT】俺のクローン作るしかなくね!?
【BiTT】俺のクローン作るしかなくね!?
2015.11.25

Gulp.jsとPostCSSを使ってCSSの面倒な作業をなくそう

先生

PostCSS

PostCSSはCSSを解析しツリー化してJavaScriptで処理を加えるツールです。
そのため、PostCSS単体ではCSSに何も変化を加えません。Sassのように記述して変形させることもできます。ここではSassでコンパイルされたCSSを、PostCSSを通してSassを拡張するような形で用いていきます。

PostCSS

npm i gulp-postcss --save-dev

gulpfile.jsを以下のように修正します。

gulp.task('css', function () {
    return gulp.src('*.scss')
        .pipe(sassLint())
        .pipe(sassLint.format())
        .pipe(sassLint.failOnError())
        .pipe(sass())
        .pipe(postcss())
        .pipe(csso())
        .pipe(gulp.dest('dest'));
});

この状態でgulp cssを実行しても特に変化はありません。
次にPostCSS用のプラグインであるAutoPrefixerを導入しましょう。

AutoPrefixer

AutoPrefixerはCSSにあるベンダープレフィックスをCan I Useのデータを元に自動的に付与、または不必要なプレフィックスを削除してくれるPostCSSプラグインです。さっそくAutoPrefixerをインストールしてみましょう。

AutoPrefixer

npm i autoprefixer --save-dev

gulpfile.jsを以下のように修正します。
AutoPrefixerのオプションbrowsersにサポートするブラウザの情報を渡します。
下記の例ではブラウザシェアが3%以上あるもの、という指定になっています。
これ以外にもIE9以上(> ie9)などの指定が複数設定できます。

var browsers = [
    '> 3%'
];
gulp.task('css', function () {
    return gulp.src('*.scss')
        .pipe(sassLint())
        .pipe(sassLint.format())
        .pipe(sassLint.failOnError())
        .pipe(sass())
        .pipe(postcss([
            require('autoprefixer')({browsers: browsers})
        ]))
        .pipe(csso())
        .pipe(gulp.dest('dest'));
});

style.scssにベンダープレフィックスが必要なtransformを使った記述を追加してみましょう。

.a {
    &:hover {
        transform: scale(1.2);
    }
}

そしてgulp cssを実行します。

a:hover {
    -webkit-transform: scale(1.2);
    transform: scale(1.2)
}

自動的に-webkitが付与されました。試しにブラウザシェアを50%以上(> 50%)にして実行してみると、以下のようにベンダープレフィックスはつかなくなりました。

a:hover {
    transform: scale(1.2)
}

また、誤って必要のないプレフィックスを付けてしまった場合でも、以下のように

a:hover {
    transform: scale(1.2)
}

と出力され、不必要なプレフィックスは削除されます。
これでどの記述にベンダープレフィックスがいるのか悩む必要がなくなりますね。

doiuse

先ほどはベンダープレフィックスを自動で付与しましたが、そもそもCSS3のプロパティが要件にあったブラウザでサポートされているかどうかはわかりませんでした。
そこでdoiuseというパッケージを使って、指定ブラウザで使えないプロパティがないかどうかを自動的にチェックしてみましょう。

doiuse

npm i doiuse --save-dev

gulpfile.jsを以下のように修正します。

gulp.task('css', function () {
    return gulp.src('*.scss')
        .pipe(sassLint())
        .pipe(sassLint.format())
        .pipe(sassLint.failOnError())
        .pipe(sass())
        .pipe(postcss([
            require('doiuse')({browsers: browsers}),
            require('autoprefixer')({browsers: browsers})
        ]))
        .pipe(csso())
        .pipe(gulp.dest('dest'));
});

ブラウザの指定はAutoPrefixerと同じにしましょう。ブラウザの対応は> 3%にして、gulp cssを実行してみましょう。

gulp css
# [19:59:25] gulp-postcss: style.css
# doiuse: /Users/frontainer/Documents/test/autocss/style.css:4:5: CSS3 2D Transforms not supported by: Opera Mini (5.0-8.0) (transforms2d)
# doiuse: /Users/frontainer/Documents/test/autocss/style.css:5:5: CSS3 2D Transforms not supported by: Opera Mini (5.0-8.0) (transforms2d)
# [19:59:25] Finished 'css' after 721 ms

するとOpera Miniの5.0〜8.0においてはCSS3の2D Transformsはサポートしていないとのことでした。Transformのサポート範囲はわかっていて毎回出るとうっとうしいな、と思ったときにはオプションを以下のようにしてみましょう。

require('doiuse')({
    browsers: browsers,
    ignore: ['transforms2d']
}),

こうすることでtransforms2dの警告が表示されなくなります。一通りサポート状況がチェックできた時点でignoreするかブラウザの設定を見直すようにしましょう。

CSS MQPacker

続いてCSS3のメディアクエリをひとまとめにするパッケージを導入します。
Sassで構築している際にファイルを複数に分けることがありますが、メディアクエリを複数箇所に書いていては、同じ記述が複数回出てきてしまい、無駄が発生してしまいます。そこでMQPackerを導入して同じメディアクエリを1つにまとめましょう。

node-css-mqpacker

npm i css-mqpacker --save-dev
gulp.task('css', function () {
    return gulp.src('*.scss')
        .pipe(sassLint())
        .pipe(sassLint.format())
        .pipe(sassLint.failOnError())
        .pipe(sass())
        .pipe(postcss([
            require('doiuse')({browsers: browsers}),
            require('autoprefixer')({browsers: browsers}),
            require('css-mqpacker')
        ])))
        .pipe(csso())
        .pipe(gulp.dest('dest'));
});

(本当は別ファイルにするのですが、)以下のようなCSSをMQPackerへ通すと、

@media screen and (max-width:800px) {
    .test {
        width: 100px;
    }
}
@media screen and (max-width:800px) {
    .test2 {
        width: 200px;
    }
}

以下のように1つのメディアクエリにまとまります。記述量が減りましたね。

@media screen and (max-width: 800px) {
    .test {
        width: 100px
    }

    .test2 {
        width: 200px
    }
}

まとめ

CSSに関する自動化をご紹介しました。
JavaScriptなどでは当たり前になりつつあった自動化ですが、CSS方面でも広がりを見せています。このような自動化ツールを活用してCSSをチームで統一させたり、より良い書き方を身につけるための練習をしたりしてみてください。

  • 1
  • 2