CodeCode

なんか色々おぼえ書き。だいたいweb制作関連。

未来を先取るPostCSS

現在のweb制作はSassを使うのが当たり前になり、もうSassなしでは開発ができないくらいまでに恩恵をもたらしてくれました。 しかし、Sassが登場してから10年がたち次世代CSSの声が聞こえはじめました。 そこで、海外のフロントエンド界隈で普及しつつある、「PostCSS」をgulp環境で使ってみたので、簡単な書き方と概要をまとめました。 デモファイル - GitHub

PostCSSとは

PostCSSとは、JavaScriptで書かれた次世代CSSを変換するためのツールです。 PostCSSは、ES2015を現行のJavaScriptにトランスポートする「Babel」と同じで、未来のcssを現行のcssに翻訳してくれます。 PostCSS自体は、はあくまで変換するツールで、必要な機能をプラグインとして自分で取捨選択し、機能拡張していきます。

PostCSSのメリット

次世代CSSを先取りできることが一番大きなメリットです。 仮に将来、SassやPostCSSが開発終了になっても、そのころにはブラウザが次世代のCSSを読み込めるようになっているはずなので、あらたに何かを探し、勉強する必要はありません。

PostCSSのデメリット

PostCSSは、必要な機能をプラグインとして機能拡張していくといいました。 しかし、これがデメリットをうみます。 というのも、どんどんプラグインを入れていくと自分だけの環境ができあがってしまい、 他の人が読めない・書けないCSSになってしまいます。 なので、プラグインのデファクトスタンダードになりつつある、cssnextに含まれるプラグインのみ使うなどのルールが必要です。 この後の説明もcssnextに含まれるプラグインを中心に、cssnextには含まれていませんが、記法とは直接関係ない便利なプラグインの導入方法をまとめています。

PostCSS導入

すでにgulpを使ってる方は読み飛ばしてください。

gulpの準備

Node.jsのインストール プロジェクトの初期設定
npm init
プロジェクトの初期設定が始まりますが、わからないところはenterで飛ばして、分かるところだけ記入で問題ありません。 gulpのコマンドが使えるように、グローバルインストールします。
npm install -g gulp
次に、プロジェクトディレクトリに移動してローカルインストールします。
npm install —save-dev gulp
これでgulpの設定は完了です。

PostCSSのインストール

gulp用のPostCSS本体をインストールします。
npm install —save-dev gulp-postcss
デモの階層はこんな感じです。
project/
    ├ htdocs/
    │   ├ common/
    │   │   ├ postcss/
    │   │   └ css/
    │   └index.html
    │
    ├ .git/
    ├ node_modules/
    ├ gulpfile.js
    └ package.json
gulpfile.js に設定を書いていきます。 全体像:
var rootpath    = \'htdocs/\';
var cmnpath = rootpath + \'common/\';

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

gulp.task(\'postcss\', function(){
    gulp.src(cmnpath + \'postcss/*.css\')
    .pipe(postcss())
    .pipe(gulp.dest(cmnpath + \'css\'))
});


gulp.task(\'watch\', function(){
    gulp.watch(cmnpath + \'postcss/**/*.css\',[\'postcss\']);
});

gulp.task(\'default\', [\'watch\']);
PostCSSのタスクだけ抜き出してみると、非常に単純です。 postcssディレクトリにあるcssファイルを読み込んできて、postcss実行して、cssディレクトリに書き出す。 以上です。
gulp.task(\'postcss\', function(){
    gulp.src(cmnpath + \'postcss/*.css\')
    .pipe(postcss())
    .pipe(gulp.dest(cmnpath + \'css\'))
});
実行
gulp
ですが、このまま実行して、 css/style.css を見てみると postcss/style.css と変化ありません。 それは、PostCSSは本体は何かをするわけではなく、ただツールとしてのAPIを提供しているのでこの結果になりました。 実際の処理はPostCSSのプラグインが行います。

PostCSSのプラグイン

postcss-import

postcss-importは外部ファイルをimportして一つにまとめれるようになります。

インストール

npm install —save-dev postcss-import

gulp.js

gulp.task(\'postcss\', function(){
    gulp.src(cmnpath + \'postcss/*.css\')
    .pipe(postcss([
        require(\'postcss-import\')
    ]))
    .pipe(gulp.dest(cmnpath + \'css\'))
});

実行結果

postcss/test.css
h1{
    color: #f00;
}
postcss/style.css
@import “test”;

h2{
    color: #00f;
}
gulpを実行すると css/style.css
h1{
    color: #f00;
}

h2{
    color: #00f;
}
このように1つのCSSにまとめることができます。

postcss-custom-properties

postcss-custom-propertiesは変数を使うことができます。

インストール

npm install —save-dev postcss-custom-properties

gulp.js

上のgulpfile.jsに追記していきます。
gulp.task(\'postcss\', function(){
    gulp.src(cmnpath + \'postcss/*.css\')
    .pipe(postcss([
        require(\'postcss-import\'),
        require(\'postcss-custom-properties\')
    ]))
    .pipe(gulp.dest(cmnpath + \'css\'))
});

実行結果

postcss/style.css
:root {
  --color-red: #f00;
  --color-green: #0f0;
  --color-blue: #00f;
}

h1{
    color: var(--color-red);
}
gulpを実行すると css/style.css
h1{
    color: #f00;
}
:rootに、変数名の頭に -- をつけて定義して、 var(--変数名) で展開します。

postcss-calc

postcss-calcは四則演算ができます。

インストール

npm install —save-dev postcss-calc

gulp.js

上のgulpfile.jsに追記していきます。
gulp.task(\'postcss\', function(){
    gulp.src(cmnpath + \'postcss/*.css\')
    .pipe(postcss([
        require(\'postcss-import\'),
        require(\'postcss-custom-properties\')
        require(\'postcss-calc\')
    ]))
    .pipe(gulp.dest(cmnpath + \'css\'))
});

実行結果

postcss/style.css
h1{
    font-seze: calc(10*5)px;
    font-seze: calc(10px*5);
    font-seze: calc(10*5px);
    font-seze: calc(10px*5px);
}
gulpを実行すると css/style.css
h1{
    font-size: 50px;
    font-size: 50px;
    font-size: 50px;
    font-size: 50px;
}
単位を含んでいてもいなくても計算が可能です。

postcss-selector-matches

postcss-selector-matchesはセレクタをグルーピングできます。

インストール

npm install —save-dev postcss-selector-matches

gulp.js

上のgulpfile.jsに追記していきます。
gulp.task(\'postcss\', function(){
    gulp.src(cmnpath + \'postcss/*.css\')
    .pipe(postcss([
        require(\'postcss-import\'),
        require(\'postcss-custom-properties\')
        require(\'postcss-calc\'),
        require(\'postcss-selector-matches\')
    ]))
    .pipe(gulp.dest(cmnpath + \'css\'))
});

実行結果

postcss/style.css
li :matches(a,i,.red){
    color: var(--color-red);
}
gulpを実行すると css/style.css
li a, li i, li .red{
    color: #f00;
}
子要素を指定するセレクタです。

postcss-nesting

postcss-nestingはネスト記法が使えます。

インストール

npm install —save-dev postcss-nesting

gulp.js

上のgulpfile.jsに追記していきます。
gulp.task(\'postcss\', function(){
    gulp.src(cmnpath + \'postcss/*.css\')
    .pipe(postcss([
        require(\'postcss-import\'),
        require(\'postcss-custom-properties\')
        require(\'postcss-calc\'),
        require(\'postcss-selector-matches\'),
        require(\'postcss-nesting\')
    ]))
    .pipe(gulp.dest(cmnpath + \'css\'))
});

実行結果

postcss/style.css
li{
    font-size: 12px;

    & a{
        color: #f00;
    }
}
gulpを実行すると css/style.css
li{
    font-size: 12px;
}

li a{
    color: #f00;
}

autoprefixer

autoprefixerは「Can I use...」をもとに、ベンダープレフィックスを自動でつけてくれます。

インストール

npm install —save-dev autoprefixer

gulp.js

上のgulpfile.jsに追記していきます。
gulp.task(\'postcss\', function(){
    gulp.src(cmnpath + \'postcss/*.css\')
    .pipe(postcss([
        require(\'postcss-import\'),
        require(\'postcss-custom-properties\')
        require(\'postcss-calc\'),
        require(\'postcss-selector-matches\'),
        require(\'postcss-nesting\'),
        require(\'autoprefixer\')
    ]))
    .pipe(gulp.dest(cmnpath + \'css\'))
});

実行結果

postcss/style.css
.box{
    display: flex;
}
gulpを実行すると css/style.css
.box{
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
}

postcss-custom-media

postcss-custom-mediaはメディアクエリの定義を変数化できます。

インストール

npm install —save-dev postcss-custom-media

gulp.js

上のgulpfile.jsに追記していきます。
gulp.task(\'postcss\', function(){
    gulp.src(cmnpath + \'postcss/*.css\')
    .pipe(postcss([
        require(\'postcss-import\'),
        require(\'postcss-custom-properties\')
        require(\'postcss-calc\'),
        require(\'postcss-selector-matches\'),
        require(\'postcss-nesting\'),
        require(\'autoprefixer\'),
        require(\'postcss-custom-media\')
    ]))
    .pipe(gulp.dest(cmnpath + \'css\'))
});

実行結果

postcss/style.css
@custom-media --mq_tab screen and (max-width:980px);
@custom-media --mq_mob screen and (max-width:480px);

@media (--mq_tab) {
    h1{
        color: #00f;
    }
}

@media (--mq_mob) {
    h1{
        color: #0f0;
    }
}
gulpを実行すると css/style.css
@media screen and (max-width:980px){
    h1{
        color: #00f;
    }
}

@media screen and (max-width:480px){
    h1{
        color: #0f0;
    }
}
@custom-media --変数名 で定義して @media (--変数名) で展開します

css-mqpacker

このプラグインはcssnextに含まれていませんが、便利なので入れています。 css-mqpackerは散らばったメディアクエリを集めてくれます。

インストール

npm install —save-dev css-mqpacker

gulp.js

上のgulpfile.jsに追記していきます。
gulp.task(\'postcss\', function(){
    gulp.src(cmnpath + \'postcss/*.css\')
    .pipe(postcss([
        require(\'postcss-import\'),
        require(\'postcss-custom-properties\')
        require(\'postcss-calc\'),
        require(\'postcss-selector-matches\'),
        require(\'postcss-nesting\'),
        require(\'autoprefixer\'),
        require(\'postcss-custom-media\'),
        require(\'css-mqpacker\')
    ]))
    .pipe(gulp.dest(cmnpath + \'css\'))
});

実行結果

postcss/style.css
@custom-media --mq_tab screen and (max-width:980px);
@custom-media --mq_mob screen and (max-width:480px);

h1{
    font-size: 30px;

    @media (--mq_tab) {
        color: #f00;
    }

    @media (--mq_mob) {
        color: #00f
    }
}

h2{
    font-size: 20px;

    @media (--mq_tab) {
        color: #f00;
    }

    @media (--mq_mob) {
        color: #f00;
    }
}
gulpを実行すると css/style.css
h1{
    font-size: 30px
}

h2{
    font-size: 20px
}

@media screen and (max-width:980px){
    h1{
        color: #f00
    }

    h2{
        color: #f00
    }
}

@media screen and (max-width:480px){
    h1{
        color: #00f
    }

    h2{
        color: #f00
    }
}
このようにセレクタに直接メディアクエリを書くことで、修正が簡単になります。 しかし、そのまま出力してしまうとCSSもくちゃぐちゃで、記述が増えてしましますが、このプラグインを通すことでメディアクエリごとにまとまります。

まとめ

現在、Sass 、LESSなどプリプロセッサーがいくつも出ていますが、PostCSSをつかうことで、方向修正がゼロというわけではないですが、最低限で次世代のCSSに対応できるとようになると思います。

参考

トップへ戻る