🐣

Next.js で外部スタイルシートを layer 指定で import する

2023/07/15に公開

Next.js で外部スタイルシートを使う必要がある場合、通常 entry (に近い) js[ts] file で読み込むと思います。
app router の場合は app/layout.tsx、pages router の場合は pages/_app.js でインポートすることが公式ドキュメントでも推奨されています。

https://nextjs.org/docs/app/building-your-application/styling/css-modules#external-stylesheets
https://nextjs.org/docs/pages/building-your-application/styling/css-modules#external-stylesheets

ただ、この方法だと、css の @import ではできるカスケードレイヤーの指定ができません。(もしかしたら将来的にはできるようにはなるかもしれませんが)

モダンブラウザによるカスケードレイヤーのサポートが進んでる今、panda css のようなカスケードレイヤーの機能を使用したライブラリが登場してきてることもあり、ウェブアプリケーションでカスケードレイヤーを使用することが多くなってきてると思います。そんな折、レイヤーを割り当てずに読み込んだ外部スタイルシートはレイヤー外宣言となり、アプリ内で宣言したレイヤーよりも優先されるようになり、外部スタイルシートの上書きが難しくなるという側面があります。

devtool でレイヤーの優先順位を確認

!important を使えば上書きできるにはできますが、そんなことは普通したくないと思います。アプリ内で当てるスタイルのレイヤーよりも優先度の低いレイヤーに割り当てて外部スタイルシートをインポートする方がベターです。

ということで、Next.js で外部スタイルシートをレイヤーに割り当てつつ読み込む方法を。

結論

css file 内で @import で読み込みつつ postcss-import を使います。

global.css
/* e.g. */
@layer external, app;

@import 'some-pkg/index.css' layer(external);
postcss.config.cjs
module.exports = {
  plugins: {
    'postcss-import': {},
  },
}

で、entry js file で該当の css file (↑の例だとglobal.css) を読み込めばOKです。

issue にあるように、Next.js では css file 内でのレイヤー指定での @import がサポートされていません。なので、postcss-import を通して外部スタイルシートの読み込みを展開する必要があります。

next.config.js で webpack config を変更して css file のコンパイル方法をいじる手段もあるかもしれませんが、rule がブラックボックスで自分にはできそうになかったので、素直に postcss を通すやり方にしています。

Discussion