PostCSS

PostCSSには変数が使えるようになるプラグインがいくつかあるので比較してみました。

PostCSSの導入記事はこちら

PostCSSを導入してみた & PostCSSの便利プラグインと誰得プラグイン

gulpでPostCSSまでインストールしたらgulpfile.jsに以下のコードを書いておきます。

var gulp = require('gulp');
var postcss = require('gulp-postcss');
gulp.task("css", function() {
  return gulp.src('./src/css/*.css')
    .pipe(postcss([]))
    .pipe(gulp.dest('./src/'))
});
もくじ
  1. PostCSS Simple Variables
  2. PostCSS CSS Variables
  3. postcss-custom-properties

PostCSS Simple Variables

$を使って変数を使うSassに近い書き方ができるプラグインです。

npm i postcss-simple-vars -D

そして追記します。

var gulp = require('gulp');
var postcss = require('gulp-postcss');
gulp.task("css", function() {
  return gulp.src('./src/css/*.css')
    .pipe(postcss([
      require('postcss-simple-vars') // ここ追記
    ]))
    .pipe(gulp.dest('./src/'))
});

style.cssなど作って以下を書きます。

$color: red;
h1 {
  color: red;
}

そして「gulp css」コマンドを打ちコンパイルするとこうなります。

h1 {
  color: red;
}

オプション

オプションがいくつか用意されています。オプションはカンマで繋いでいくことができます。

variables

変数をconfigファイルなどで外部管理ができます。

config.jsを作ってこんな感じで書いておきます。

module.exports = {
  blue: '#056ef0'
}

そしてオプションを付け足します。

var gulp = require('gulp');
var postcss = require('gulp-postcss');
var color = require('./config.js'); // ここ追記
gulp.task("css", function() {
  return gulp.src('./src/css/*.css')
    .pipe(postcss([
      require('postcss-simple-vars')({ variables: color }) // ここ追記
    ]))
    .pipe(gulp.dest('./src/'))
});

CSSで変数が使えます。

h1 {
  color: $blue;
}

onVariables

コンパイル後の処理を追加できます。

gulp.task("css", function() {
  return gulp.src('./src/css/*.css')
    .pipe(postcss([
      require('postcss-simple-vars')({
        onVariables: function (variables) {
            // ここに処理を書く
            console.log('CSS Variables');
            console.log(JSON.stringify(variables, null, 2));
        }
       })
    ]))
    .pipe(gulp.dest('./src/'))
});

unknown

未定義の変数をコマンド上で教えてくれます。

gulp.task("css", function() {
  return gulp.src('./src/css/*.css')
    .pipe(postcss([
      require('postcss-simple-vars')({
        unknown: function (node, name, result) {
            node.warn(result, 'Unknown variable ' + name);
        }
       })
    ]))
    .pipe(gulp.dest('./src/'))
});

silent

trueにすると未定義の変数があった場合でも何も通知せずコンパイルを通します。デフォルトはfalse。

PostCSS CSS Variables

W3Cに仕様に近い書き方で書けるプラグイン

npm i postcss-css-variables -D

以下に追記します。

var gulp = require('gulp');
var postcss = require('gulp-postcss');
gulp.task("css", function() {
  return gulp.src('./src/css/*.css')
    .pipe(postcss([
      require('postcss-css-variables') // ここに追記
    ]))
    .pipe(gulp.dest('./src/'))
});

変数は以下のように:root内でハイフン2つで定義して、var()で使います。この書き方はすでに対応しているブラウザのバージョンもあります。コンパイルしなくてもchromeなどでは使えます。

:root {
  --color: red;
}
h1 {
  color: var(--color);
}

こうなります。

h1 {
  color: red;
}

変数は何回でも使えますが、セレクタ内で指定した場合はそれが優先されます。

:root {
  --some-color: red;
}
.foo {
  color: var(--some-color);
}
.bar {
  --some-color: blue;
  color: var(--some-color);
}
.bar:hover {
  --some-color: green;
}

他にもいろいろな指定方法があるみたいです。

.component {
  --text-color: #080;
}
.component .header {
  color: var(--header-color, blue);
}
.component .text {
  color: var(--text-color, black);
}
:root {
  --width: 100px;
}
@media (max-width: 1000px) {
  :root {
    --width: 200px;
  }
}
.box {
  width: var(--width);
}

postcss-custom-properties

こちらもW3Cに仕様に近い書き方で書けるプラグイン

npm i postcss-custom-properties -D

追記します。

var gulp = require('gulp');
var postcss = require('gulp-postcss');
gulp.task("css", function() {
  return gulp.src('./src/css/*.css')
    .pipe(postcss([
      require('postcss-custom-properties') // ここ追記
    ]))
    .pipe(gulp.dest('./src/'))
});

こう書いたのが

:root {
  --some-color: red;
}
.foo {
  color: var(--some-color);
}

こうなります。

.foo {
  color: red;
}

この基本形のコンパイルはできますが、postcss-css-variablesでサンプルで書いたようなコードはコンパイルできないです。

コンパイルできる記法が少ないからpostcss-css-variablesよりダメとかそういうことではなくて、理由はちゃんとありそうです。GitHubの冒頭にあるこの文から始まるところ。

Per w3c specifications, the usage of var() is limited to property values. Do not expect the plugin to transform var() in media queries or in selectors.

英語あまりできないのでGoogle先生に変換して何となーく感じとった意味は、変数を変換するプラグインでメディアクエリ内やセレクタ内で変数変換するようにするべきじゃないとかそんな感じのことかなと(間違ってたらご指摘を…)。

以下のように書いた時、postcss-css-variablesでは変換してくれますが、postcss-custom-propertiesでは「not scoped to the top-level :root element (:root { … -width: … }), in atrule」こんな通知がでて、コンパイルしてくれません。

:root {
  --width: 100px;
}
@media (max-width: 1000px) {
  :root {
    --width: 200px;
  }
}
.box {
  width: var(--width);
}

さいごに

今のところぼくが使っているのは最後に紹介した「postcss-custom-properties」です。変数を指定するなら、これで十分だったりします。Sassの書き方をするならSassを使ったほうがいいかなと。