弁護士ドットコム株式会社 Creators’ blog

弁護士ドットコムがエンジニア・デザイナーのサービス開発事例やデザイン活動を発信する公式ブログです。

postcss-preset-envで少し未来のCSSを予習する

こんにちは、弁護士ドットコムでデザイナーをしているhosogaiです。 ふだんは https://www.bengo4.com/ サービス内のUI改善などをしています。

先日このブログ「弁護士ドットコム株式会社 Creators’ blog」のデザインカスタマイズを行った際にCSSの新機能をいくつか試す機会があったので、今回ここで紹介させていただこうと思います。

きっかけ

このブログのプラットフォームであるはてなブログには、CSSを編集してオリジナルテーマを作る「デザインテーマ」という機能がついており、CSSを管理画面上に貼り付けて保存すると<style>タグでサイトに読み込まれる仕組みになっています。

公式でもデザインテーマ制作の手引きが用意されており、BoilerPlateとしてSassで開発できるセットも用意してくれています。

弁護士ドットコムの業務では主にSassを使っているのですが、W3Cで策定中のNesting CSS Moduleを少し試してみたいという気持ちがあり、少し未来のCSSを書けると噂のPostCSSを試してみようと考えました。

PostCSSとは

PostCSSはCSSに対して自動処理を行うツールです。プラグインを入れることでさまざまな処理ができ、CSSの構文チェックや変数の展開、未来の構文を現在の構文に変換する、といったこともできます。

https://postcss.org/

PostCSSには多くのプラグインがあり、組み合わせるとSassと遜色ない機能が利用できます。 今回はまだ策定中のCSS構文を実際に使うことができるpostcss-preset-envというプラグインを利用しました。

Use tomorrow’s CSS today

「明日(未来)のCSSを今日使う」というキャッチコピーがかっこいいですね! PostCSSのプラグインが複数組み込まれており、使用するCSS構文にあわせてPolyfillを適用してくれる仕組みです。

postcss-preset-envの使い方

プラグイン側で「CSSの策定段階にあわせた0〜4までのステージ」を設定できます(ステージについては後で説明します)。

npm packageで使う場合

今回はブログのテーマ制作でCSSを生成するので、かんたんな開発環境を用意してnpm packageをインストールしました。configに少し設定を追加するだけで、Sassの導入とほとんど変わらないくらいかんたんに使用できました。

  1. npm install postcss postcss-preset-env --save-dev でパッケージをインストール
  2. postcss.config.jsで使いたい機能を設定する
  3. package.jsonに "css:watch": "postcss src/style.css -o dist/style.css -w" のようなスクリプトを書いて実行&監視する
module.exports = {
  plugins: {
    "postcss-preset-env": {
      // stage: 2, // 有効にしたいStageを指定(デフォルトは2)
      features: { // 有効・無効にしたい機能を個別に指定
        "nesting-rules": true,
        "custom-media-queries": true
      },
    },
  },
};

CodePenで使う場合

私を含めてチームのデザイナーが愛用しているCodePenでも2015年からPostCSSがサポートされており、GUI上でプラグインが追加できます。 開発環境をつくるほどではないけれど、ちょっとした試し書きをしたいときに便利でした。

https://blog.codepen.io/2015/07/14/postcss-now-supported-on-codepen/

  1. CodePenでPenを作成し、PostCSSを選択する
  2. 設定画面を開き、Need An Addonをクリック
  3. @use postcss-preset-env をAddして設定を保存
/* Stageの設定や個別の機能追加もできる */
@use postcss-preset-env{
  features: {
    "nesting-rules": true,
    "custom-media-queries": true, 
  }
};

試せるCSSの機能

策定段階(ステージ)はcssdb に掲載されているリストが元になっており、W3CのMaturity Levels の安定性によって各機能が分類されています。

Stage0(意欲的)

W3Cの Unofficial Draft / 非公式な草案 または Editor’s Draft / 編集者草案 段階。W3Cのコミュニティに属する個人またはグループが検討のために下書きしている状態であり、まだ正式なレビューを受けてない段階です。

ID(機能名) 概要
environment-variables ユーザーエージェントが定義した環境変数の値を var() 関数やカスタムプロパティと同じ方法で CSS に挿入する

Stage1(実験)

W3Cの Editor’s Draft / 編集者草案 または 初期の Working Draft / 草案 段階。Stage0と似ていますが、実際の機能として検討されはじめている機能をStage1としているようです。

ID(機能名) 概要
custom-selectors @custom-selector を使ってセレクタのエイリアスを定義する
font-format-keywords format()関数を使ってブラウザに最適なフォント形式を指定する
nesting-rules CSSのスタイル規則を入れ子にする

Stage2(許容)

W3Cの Working Draft / 草案 段階。仕様が変更される可能性はあるものの、一部のブラウザで利用ができる機能です。 弁護士ドットコムもIE11サポートを終了しているので、擬似クラスやclamp()など、すでに使っている機能も多く含まれています。

ID(機能名) 概要
any-link-pseudo-class :any-link 擬似クラスを使ってhref 属性を持つすべての <a> または <area> 要素を選択する
blank-pseudo-class :blank 擬似クラスを使って空のユーザー入力要素( <input><textarea>など)を選択する
case-insensitive-attributes [attr i] の構文を使って属性値の大文字と小文字を区別させない
clamp clamp() 関数を使って値を上限と下限の間に制限する
color-function color() 関数を使って定義済みまたは独自の色空間で色を指定する
color-functional-notation ホワイトスペース区切りの構文で色を指定する
custom-media-queries @custom-media を使ってメディアクエリのエイリアスを定義する
dir-pseudo-class :dir() 擬似クラスを使って中に含まれる文字列の方向にもとづいて要素を選択する
display-two-values displayプロパティの外部と内部の 2 つの値を設定できる新しい構文
double-position-gradients グラデーションの指定時に2つの値を設定する
focus-visible-pseudo-class :focus-visible 擬似クラスを使って、タブ移動時にフォーカスされる要素にスタイルを適用する
focus-within-pseudo-class :focus-within 擬似クラスを使って、その要素または子孫要素にフォーカスがある場合にスタイルを適用する
has-pseudo-class :has() 擬似クラスを使って、 該当する要素が1つ以上含まれている要素を選択する
hexadecimal-alpha-notation 4文字および8文字の16進色表記でアルファ値(透明度)を指定する
hwb-function hwb() 関数を使ってHWB色空間で色を指定する
ic-unit その要素のフォントにおける“水” のグリフを表す長さの単位を使用する
image-set-function image-set() 関数を使って、指定されたセットからもっとも適切なCSS画像をブラウザで表示する
is-pseudo-class :is() 擬似クラスを使って、セレクターのリストを引数に入れて要素を選択できる
lab-function lab() 関数を使ってLAB色空間で色を指定する
logical-properties-and-values 論理プロパティを使って方向や寸法をマッピングしレイアウトを指定する
not-pseudo-class :not() 擬似クラスを使って、列挙されたセレクターに一致しない要素を選択する
oklab-function oklab() 関数を使ってOKLab・OKLCH色空間で色を指定する
opacity-percentage opacityの指定に を使用する
overflow-property overflow-x / overflow-yの指定にショートハンドを使用する
overflow-wrap-property overflow-wrap プロパティを使って、インライン要素のテキストが行ボックスをあふれないように、改行を入れるかどうか設定する
place-properties place-content プロパティを使って要素内の配置を一括指定する
prefers-color-scheme-query ユーザーがシステムに要求したカラーテーマが明色か暗色かを検出する
rebeccapurple-color エリック・メイヤーに敬意を表して追加された色キーワードを使用する
system-ui-font-family 指定されたプラットフォームの既定のユーザーインタフェースフォントからfont-familyを設定する

Stage3(包含)

W3Cの Candidate Recommendation / 勧告候補 段階。少なくても2つ以上のブラウザベンダーで実装されており、変更の可能性が低く、標準となる可能性が高い機能が含まれています。

ID(機能名) 概要
break-properties break-inside プロパティを使ってボックス途中でのカラムの区切りを設定する
custom-properties var() 関数を使って他の宣言の中で使用可能な変数を定義する
gap-properties gap プロパティを使って行や列の間のすき間 (溝) を定義する
media-query-ranges 比較演算子を使ってメディアクエリ範囲を定義する

Stage4(標準化)

W3Cの Recommendation / 推奨事項 段階。一般的なブラウザベンダーに実装されており、W3C勧告の「Web標準」として広く活用できるようになった機能です。

ID(機能名) 概要
all-property all プロパティを使って要素のすべてのプロパティを初期化する
font-variant-property font-variant プロパティを使って、フォントをスモールキャップ(欧文などで小文字の表示が小文字サイズの大文字になる)にするかどうかを指定できる

新機能のNesting CSS Moduleを使ってみる

プラグインを設定したあと、実際にブログのデザインテーマ制作に使ってみました。 すべての機能を話題にあげると収拾がつかなくなりそうなので、今回の目当てだったNesting CSS Module(Nesting Rules)を中心に紹介していきます。

Nesting CSS Moduleは、SassのようにCSSのスタイル規則を入れ子にし、関連するスタイルをグループ化して可読性や保守性を改善する機能です。 この機能は Stage1 なので、対応ブラウザはまだありません。プラグインを使って、入れ子の構文を現在のブラウザに理解できる形に変換します。

Nesting CSS Moduleのルール

& {セレクタ} で別のスタイルルール内にネストできます。

直接入れ子にする場合

  • Sassと違う点として、最初の単体選択肢に & を必ず入れる必要があります(選択肢リストを含む)
  • 最初の単体選択肢が & でない場合は無効になる

@nestを使う場合

  • @nest を使うと & ではじまらない構文でもNestingが利用できる

See the Pen css-nesting-rules / 要素タグのみ by shellme (@shellme-the-lessful) on CodePen.

プラグインでの挙動

CSS Nesting Modulesは、セレクタの入れ子を :is() に置き換えて解釈する仕組みとして考えられています。 ただ、プラグイン側では「まだ :is() へのブラウザの対応が十分ではない」という判断で、予定されているブラウザの解釈とは少しちがった出力結果をデフォルトとしているようです。

/* 構文 */
a, b {
  & c { color: blue; }
}

/* 予定されているブラウザの解釈 */
:is(a, b) c { color: blue; }

/* プラグイン利用時の出力結果 */
a c,
b c {
  color: blue
}

また、CodePen上ではプラグインのバージョンがちがうのか@nestの構文はまだ使用できないようです。@nest も使いたい場合は、開発環境をつくるか、プラグイン公式のplaygroundを使うと動作が確認できます。

https://preset-env.cssdb.org/playground/

やってみた感想

既存の環境や構成を見直すきっかけになる

CSSのスコープが定義できる環境だと、Sassを使わなくてもCSS Nesting Moduleだけで十分やりたいことができる世界が実現できそうだなという期待感がありました。

ただ、Sassの & のように「参照した親要素の名前を子要素のclass名に出力」はできないので、BEMやFLOCSSでよく使う &__ を使った子要素の命名は多少書きづらくなりそうです。

// SassでBEMルールを使用
.sample {
  color: red;
  &__item {
    color: blue;
  }
}
  // .sample { color: red; }
  // .sample__item { color: blue; }

// CSS Nesting ModuleでBEMルールを使用
.sample {
  color: red;
  & .sample__item {
    color: blue;
  }
}
  // .sample { color: red; }
  // .sample__item { color: blue; }

そのため、今回のブログテーマの作成では試しにrscssの命名ルールを参考にしました。

// rscssの場合
.sample {
  color: red;
  & > .item {
    color: blue;
  }
}
  // .sample { color: red; }
  // .sample > item { color: blue; }

グローバルCSSが必要な環境の場合はSassがないとまだ大変な場面もありそうですが、使える機能によって開発環境や命名規則などを再考する良い機会になりました。

公式ドキュメントをしっかり読むきっかけになる

CSS Nesting Moduleはセレクタの入れ子を :is() に置き換えて解釈するので詳細度が高くなる傾向があり、記述する順番や入れ子の深さによって意図しない動作が起きやすい…など、現時点のW3Cのドラフトの注意事項をきちんと読むきっかけにもなりました。

https://www.w3.org/TR/css-nesting-1/#nest-selector

postcss-preset-envのように新機能が一覧化されていると主要な新機能がもれなくチェックでき、ドキュメントと挙動を照らし合わせながら学習できるのがとても便利でした。

最後に

node-sassからDart Sassに移行しようとした際もそうでしたが、実務でいきなり新しいツールや機能を使おうとしても、予想外の挙動をしたり、学習にそれなりに時間がかかってしまいがちです。事前に小規模な環境で試しておくと、このプロダクトならこうしよう/ここを気をつけよう、という検討がより具体的にできるメリットがありました。

今年の6月にはIE11のサポートが公式に終了してさらに新しい機能が増えていくはずですし、今回予習した内容のうち、いまのブラウザ環境で導入できそうなものからプロダクト開発に役立てていこうと思います💪