CSS モジュール

Next.js は .module.css 拡張子を使用した CSS モジュールをビルトインでサポートしています。

CSS モジュールは、一意のクラス名を自動的に生成することで CSS をローカルスコープ化します。これにより、異なるファイルで同じクラス名を使用しても衝突を心配する必要がありません。この動作により、CSS モジュールはコンポーネントレベルの CSS を含める理想的な方法となっています。

例えば、components/ フォルダ内の再利用可能な Button コンポーネントを考えてみましょう:

まず、components/Button.module.css を作成し、以下の内容を記述します:

Button.module.css
/*
他の `.css` や `.module.css` ファイルとのクラス名(.error など)の衝突を心配する必要はありません!
*/
.error {
  color: white;
  background-color: red;
}

次に、components/Button.js を作成し、上記の CSS ファイルをインポートして使用します:

components/Button.js
import styles from './Button.module.css'

export function Button() {
  return (
    <button
      type="button"
      // インポートした `styles` オブジェクトのプロパティとして "error" クラスにアクセスしていることに注目
      className={styles.error}
    >
      Destroy
    </button>
  )
}

CSS モジュールはオプション機能であり、.module.css 拡張子を持つファイルに対してのみ有効です。 通常の <link> スタイルシートやグローバル CSS ファイルも引き続きサポートされています。

本番環境では、すべての CSS モジュールファイルは自動的に多数の最小化されたコード分割された .css ファイルに結合されます。 これらの .css ファイルはアプリケーションのホットな実行パスを表しており、アプリケーションの描画に必要な最小限の CSS が読み込まれることを保証します。

グローバルスタイル

アプリケーションにスタイルシートを追加するには、CSS ファイルを pages/_app.js 内でインポートします。

例えば、styles.css という名前の次のスタイルシートを考えてみましょう:

styles.css
body {
  font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', 'Helvetica',
    'Arial', sans-serif;
  padding: 20px 20px 60px;
  max-width: 680px;
  margin: 0 auto;
}

まだ存在しない場合は pages/_app.js ファイル を作成します。 次に、styles.css ファイルを import します。

pages/_app.js
import '../styles.css'

// このデフォルトエクスポートは新しい `pages/_app.js` ファイルで必要です。
export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

これらのスタイル (styles.css) はアプリケーションのすべてのページとコンポーネントに適用されます。 スタイルシートのグローバルな性質と衝突を避けるため、スタイルシートは pages/_app.js 内でのみインポートできます

開発環境では、この方法でスタイルシートを表現すると、編集時にスタイルをホットリロードできます。つまり、アプリケーションの状態を保持したままスタイルを変更できます。

本番環境では、すべての CSS ファイルは自動的に単一の最小化された .css ファイルに結合されます。CSS が結合される順序は、_app.js ファイルにインポートされる順序と一致します。独自の CSS を含むインポートされた JS モジュールに特に注意してください。JS モジュールの CSS は、インポートされた CSS ファイルと同じ順序規則に従って結合されます。例えば:

import '../styles.css'
// ErrorBoundary の CSS は styles.css のグローバル CSS に依存しているため、
// styles.css の後にインポートします。
import ErrorBoundary from '../components/ErrorBoundary'

export default function MyApp({ Component, pageProps }) {
  return (
    <ErrorBoundary>
      <Component {...pageProps} />
    </ErrorBoundary>
  )
}

外部スタイルシート

Next.js では、JavaScript ファイルから CSS ファイルをインポートできます。 これは、Next.js が import の概念を JavaScript 以外にも拡張しているため可能です。

node_modules からのスタイルのインポート

Next.js 9.5.4 以降、node_modules からの CSS ファイルのインポートがアプリケーションの任意の場所で許可されています。

bootstrapnprogress のようなグローバルスタイルシートの場合、ファイルを pages/_app.js 内でインポートする必要があります。例えば:

pages/_app.js
import 'bootstrap/dist/css/bootstrap.css'

export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

サードパーティコンポーネントに必要な CSS をインポートする場合、コンポーネント内で行うことができます。例えば:

components/example-dialog.js
import { useState } from 'react'
import { Dialog } from '@reach/dialog'
import VisuallyHidden from '@reach/visually-hidden'
import '@reach/dialog/styles.css'

function ExampleDialog(props) {
  const [showDialog, setShowDialog] = useState(false)
  const open = () => setShowDialog(true)
  const close = () => setShowDialog(false)

  return (
    <div>
      <button onClick={open}>Open Dialog</button>
      <Dialog isOpen={showDialog} onDismiss={close}>
        <button className="close-button" onClick={close}>
          <VisuallyHidden>Close</VisuallyHidden>
          <span aria-hidden>×</span>
        </button>
        <p>Hello there. I am a dialog</p>
      </Dialog>
    </div>
  )
}

追加機能

Next.js には、スタイルの追加を改善するための追加機能が含まれています:

  • next dev でローカル実行する場合、ローカルのスタイルシート(グローバルまたは CSS モジュール)は Fast Refresh を利用して、編集が保存されると即座に変更を反映します。
  • next build で本番ビルドする場合、CSS ファイルはネットワークリクエストの数を減らすために、より少ない数の最小化された .css ファイルにバンドルされます。
  • JavaScript を無効にしても、本番ビルド (next start) ではスタイルが引き続き読み込まれます。ただし、next devFast Refresh を有効にするには JavaScript が必要です。