12周年記念パーティ開催! 2024/5/10(金) 19:00

ECSSから学ぶ、PostCSSを利用した環境構築 第1回 PostCSSの基本的な使い方

名前空間によりモジュールを分類することで、コードの複雑化を防ぐアプローチを取るECSSの、PostCSSを用いたビルド環境の構築例を紹介します。今回は、PostCSSの基本について触れます。

発行

著者 高津戸 壮 テクニカルディレクター
ECSSから学ぶ、PostCSSを利用した環境構築 シリーズの記事一覧

はじめに

Enduring CSS(ECSS)というCSS設計方法論は、Webアプリケーションを構成するモジュール群を、名前空間でグルーピングして考え、それぞれの名前空間の中でCSSやJavaScriptなどを完結させることで、コードの複雑化を防ぐアプローチを取っています。エンジニアのBen Frain氏が電子書籍として著し、現在ではWebサイト「ECSS: Home Page」上ですべてのコンテンツが読めるようになっています(本連載では、このコンテンツを「ECSS本」と呼ぶことにします)。

ECSSについては、CodeGridの過去の連載でも紹介しました。この連載では、その概要とクラス名の命名規則などを紹介しましたが、どのようにCSSをビルドするのかという点につきましては触れていませんでした。

ECSS本の中では、gulpとPostCSSを使ったビルド例が紹介されているのですが、詳しく解説されているわけではありません。筆者がECSSのビルド環境をgulpとPostCSSで構築してみましたので、本連載ではそのビルドの内容を簡単に紹介、解説します。

なお、紹介するサンプルは次のリポジトリからダウンロード、またはクローンできます。併せて参照してください。

PostCSSでのECSSビルド環境構築

なお、この連載の中では、gulpの使用方法については解説しません。gulpについて知りたい方は、以下の記事をざっとご覧になることをお勧めします。

名前空間ごとにCSSをまとめる

ECSSは、全体で一つとして考えるのをやめ、名前空間で区切るという設計を採用しました。このとき、CSSファイルも分けたほうが良いでしょうか。

たとえば、名前空間ごとにCSSファイルをまとめてみるのはどうでしょう。そのようにすると、テンプレートごとに、そのテンプレート内で使われている名前空間のCSSファイルだけを読み込ませるという実装ができるでしょう。場合によっては、そのような実装がWebサイトの表示高速化につながることもあります。

しかし、名前空間が増えてくると管理が複雑になります。名前空間を100用意したら100のCSSファイルを管理しなければならなくなりますし、なにより、CSSファイルの数だけリクエストが発生することで、ページの表示が遅くなってしまう結果にもなりえます。全体で一つのCSSファイルにまとめてしまったり、いくつかの名前空間でCSSファイルをまとめたりするほうが、高速な表示を実現する結果になることも多いでしょう。そもそもSingle Page Applicationの場合、CSSファイルを分けたところで、どうせ全部読み込ませる必要がありますから、無駄にリクエスト数を増やしてしまうだけです。

表示の高速化と高い保守性を両立するには、どのようにCSS群をまとめるかという点についても設計が必要であると言えそうです。

PostCSSとは

ECSS本の中では、PostCSSを使ったビルド例が紹介されています。本連載で紹介するビルドでもPostCSSを使いますが、まずはPostCSSが何かという点について簡単に紹介しましょう。

PostCSSとは、CSSを別の形に変換するソフトウェアです。JavaScriptで書かれており、npmに登録されています。CSSを変換すると言いましても、PostCSS自体は、CSSファイルの内容を構造化されたデータ(AST:Abstract Syntax Tree)に展開し、別の形に変換するAPIを提供してくれるソフトウェアにすぎません。

そのAPIを使ったCSSの変換処理はプラグインと呼ばれ、JavaScriptで書きます。数多くのプラグインがnpmに登録されているので、自分の好きなものを組み合わせて、自身のプロジェクトに利用できます。

プラグインを用いると、たとえばCSSの中で、以下のようなことができるようになります。

  • 変数が使える
  • for文やif文が使える
  • mixinが使える
  • 括弧{}を入れ子にすることができる
  • 16進数の色指定をrgba形式に変換することができる

CSSをPostCSSが変換し、最終的にブラウザが読めるCSSにするだけですので、「CSSの中でこのようなことができるようになる」という言い方は微妙に正しくありません。けれど、上記のようなことが、あたかもCSS内でできるかのようにコードを書くことができるようになります。

もし自分のやりたいことを実現してくれるプラグインがなければ、自分でプラグインを作ることができます。Sassも、このようなCSSの機能を拡張するセットのようなものですが、PostCSSの場合、自由に機能を選択できるという点が大きく違います。

PostCSSは、拡張性の高さに加え、変換の速度が高速であることでも注目されています。また、Bootstrapの開発者、Mark Otto氏が、Bootstrapの次期バージョンでは、SassではなくPostCSSを使うことを示唆するツイートをしたことも話題になりました。

ただ、自由度が高い分、CSSが独自の記法だらけになってしまいやすいという点には注意する必要があるとも言われています。

Sassを使うべきか? PostCSSを使うべきか?

そんな利点があるPostCSSですが、「そうは言っても別にSassで事足りているかな」と筆者は思っていました。取り立ててこんな機能がほしい!というような思いもありませんでしたし、何より、PostCSSを持ち込むことで、書かれるCSSに微妙な差異が生まれてしまい、CSS編集のハードルを上げてしまうことになるのではないかと考えていたからです。

ただ、ECSSのビルドを作っている中で、特定ディレクトリ以下にあるCSSファイルをまとめてimportしたいという欲が生まれましたが、これがSassではできませんでした。それを機に、PostCSSを使ってみることにしました。正直に言えば、PostCSSを使いたい理由はそれだけでした。

いざPostCSSを使ってみようとプラグインを眺めていると、CSSの{}内での変数は、そのスコープだけで有効となるようなプラグインがあり、この機能がほしかったんだよな、などと感じたりもしました。

Sassを使っていると、当然のことながら、書けるCSS(SCSS)の文法は、Sassが用意しているものだけになります。その点、PostCSSだったら機能の選択は自由自在です。その自由さが混乱の元になると危惧されるわけですが、自由だからといって、あまり馴染みのない機能を実現するプラグインをどんどん導入するかと言えば、そんなことはないのではないでしょうか。少なくとも筆者は、Sassでできていることが一通りできて、その上でやりたかった「まとめてimport」ができれば、あとはSassからあまりかけ離れたものとしたくはないというように感じました。

そんな気持ちで使い始めたPostCSSですが、gulpの使い方がわかっていれば特に難しいことはなく、普段SassなどのCSSプリプロセッサーを使ってCSSを書いている人にとっては、いつもどおりの書き方でCSSを書いていけるものです。興味がある方はぜひ試してみると良いのではないかと思います。

とりあえずPostCSSを試す

では、実際にPostCSSを動かしてみます。

初めの単純な例として、以下2つの、括弧の入れ子を展開するpostcss-nestedと、変数を有効にするpostcss-simple-varsの2つのプラグインを使ってみたデモを用意しました。

このデモの内容は、以下より参照できます。

リポジトリをcloneし、01.basicディレクトリに移動の後、npm installをしてgulpを実行すると、srcディレクトリ以下に配置されたCSSファイルを、PostCSSが変換します。こうして変換されたCSSファイルは、destディレクトリに書き出されます(用意したサンプルリポジトリにはすでに変換後のCSSファイルも含まれていますので、destディレクトリの中身を空にしてから実行すると、ご自身で一連の動作が確認できます)。

PostCSSによる変換処理の確認

変換前後のCSSファイルの内容を見てみましょう。まずは変換前のsrc/styles.cssです。

$ns1-moduleWidth: 100px;
$ns1-moduleHeight: 100px;
$ns1-moduleBaseColor: pink;

.ns1 {
  &-Module1 {
    width: $ns1-moduleWidth;
    height: $ns1-moduleHeight;
    background: $ns1-moduleBaseColor;
    &_ChildNode1 {
      width: 50px;
      height: 50px;
      margin: 25px;
      background: orange;
      &-variation1 { background: blue; }
      &-variation2 { background: yellow; }
      &-variation3 { background: navy; }
    }
  }
}

これが変換されると、以下の内容の、dest/styles.cssが作成されます。

.ns1-Module1 {
    width: 100px;
    height: 100px;
    background: pink;
}
.ns1-Module1_ChildNode1 {
    width: 50px;
    height: 50px;
    margin: 25px;
    background: orange;
}
.ns1-Module1_ChildNode1-variation1 {
    background: blue;
}
.ns1-Module1_ChildNode1-variation2 {
    background: yellow;
}
.ns1-Module1_ChildNode1-variation3 {
    background: navy;
}

ここで使用した2つのプラグインが実現する機能は、どちらもSassで用意されている機能と同様のものですので、ここでは解説を省きますが、入れ子になった括弧の展開と変数の展開が、きちんと行われているのが確認できます。

gulpでのPostCSSの使い方

次に、gulpfile.jsの中で、PostCSSにCSSを変換させている、compileCssタスクを見てみます。

var gulp = require("gulp");
// PostCSSのプラグイン
var postcss = require("gulp-postcss");
var simpleVars = require("postcss-simple-vars");
var nested = require("postcss-nested");
// その他
var notify = require("gulp-notify");

gulp.task("compileCss", function() {
  // PostCSSのプラグインらを指定
  var processors = [
    simpleVars,
    nested
  ];
  return gulp.src("src/**/*.css") // CSSファイル全てが対象
    .pipe(postcss(processors)) // PostCSSに渡して処理させる
    .pipe(gulp.dest("./dest")) // destに出力
    .pipe(notify("CSS compiled.")); // 通知
});

PostCSSの使い方はとても単純。プラグインを配列にまとめ、postcssに引数として渡し、その返り値をgulpに渡すだけです。さらに追加でプラグインを使いたい場合、上記コード内でプラグインをまとめている、processorsに、使いたいプラグインをrequireしてきて追加すればOKです。

gulpを使ったことがある方であれば、PostCSSの導入が容易であることがわかるでしょう。

まとめ

今回は、ECSSのビルドに必要なPostCSSの基本的な使い方を解説しました。次回は、他のプラグインも利用し、引き続き、ECSSのビルド環境を作っていきます。