できない.dev

PostCSS で CSS のネストが展開できない

ネストの展開にはプラグインが要る。
仕様準拠の postcss-nesting と Sass 風の postcss-nested は別物で、どちらを入れたかによって書ける記法が変わる。

公開:

要約

PostCSS 本体はネストを展開しません。
ネストした CSS をそのままビルドすると、対応していない環境では中のルールが丸ごと無視されます。
展開するにはプラグインを入れます。

選択肢は 2 つあり、書ける記法が違います。

# CSS Nesting 仕様に沿う
npm install -D postcss-nesting
 
# Sass と同じ感覚で書く
npm install -D postcss-nested

よくある原因

  1. プラグインが無い: PostCSS は CSS を解析する土台で、記法の変換はプラグインの担当。
    ネスト用のプラグインを登録しなければ、ネストは書いたまま出力される。
  2. 仕様準拠のプラグインに 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 のような書き方)はこちらでは扱えない。
  3. プラグインの順序: @import で読み込んだファイルのネストを展開するには、postcss-import が先に展開を終えている必要がある。
    順序が逆だと、読み込み先のネストだけが残る。
  4. そもそも変換が要らない: ネイティブの 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 に足す前に、既に有効になっていないかを確かめてください。

この記事は役立ちましたか?