PostCSS で CSS のネストが展開できない
ネストの展開にはプラグインが要る。
仕様準拠の postcss-nesting と Sass 風の postcss-nested は別物で、どちらを入れたかによって書ける記法が変わる。
公開:
要約
PostCSS 本体はネストを展開しません。
ネストした CSS をそのままビルドすると、対応していない環境では中のルールが丸ごと無視されます。
展開するにはプラグインを入れます。
選択肢は 2 つあり、書ける記法が違います。
# CSS Nesting 仕様に沿う
npm install -D postcss-nesting
# Sass と同じ感覚で書く
npm install -D postcss-nestedよくある原因
- プラグインが無い: PostCSS は CSS を解析する土台で、記法の変換はプラグインの担当。
ネスト用のプラグインを登録しなければ、ネストは書いたまま出力される。 - 仕様準拠のプラグインに Sass 風を書いている:
postcss-nestingは W3C の CSS Nesting 仕様の実装で、公式リポジトリも「If you want nested rules the same way Sass works you might want to use PostCSS Nested instead.」と案内している。
Sass のセレクタ結合(&__elementのような書き方)はこちらでは扱えない。 - プラグインの順序:
@importで読み込んだファイルのネストを展開するには、postcss-importが先に展開を終えている必要がある。
順序が逆だと、読み込み先のネストだけが残る。 - そもそも変換が要らない: ネイティブの CSS ネストに対応した環境だけを対象にしているなら、変換なしでも動く。
この場合は対象ブラウザの確認が先。
解決策
1. どちらのプラグインを使うか決める
仕様に沿った書き方をしたいなら postcss-nesting です。
// postcss.config.js
export default {
plugins: {
"postcss-import": {},
"postcss-nesting": {},
autoprefixer: {},
},
};Sass からの移行で、既存の記法をそのまま活かしたいなら postcss-nested を選びます。
両方を同時に入れる構成は避けてください。
2. postcss-nesting では & の要否を守る
postcss-nesting は仕様どおりの解釈をします。&:hover のように親を参照する場合と、> .bar のように結合子で始まる場合はそのまま書けます。
.card {
color: #eee;
&:hover {
color: #fff;
}
> .title {
font-weight: 700;
}
}一方、要素セレクタや型セレクタで始める場合は & が要ります。
.card {
/* NG: 展開されない書き方 */
/* a { color: red; } */
/* OK */
& a {
color: #10b981;
}
}3. import より後ろに置く
postcss-import は必ず先頭です。
ネスト系はその後ろに置きます。
export default {
plugins: {
"postcss-import": {},
"postcss-nesting": {},
},
};順序の考え方は /postcss/import-not-inlined/ にまとめてあります。
4. 出力を見て確認する
展開できていれば、出力側にネストは残りません。
npx postcss src/app.css -o dist/app.css
grep -n "&" dist/app.css& が残っていれば、そのファイルは処理されていません。
設定ファイルが読まれていない可能性もあるので、/postcss/config-not-loaded-esm/ も確認してください。
なお Tailwind CSS を使っている場合、ネストの扱いはフレームワーク側の設定に含まれていることがあります。
自分の postcss.config.js に足す前に、既に有効になっていないかを確かめてください。