💭

Next.jsのglobal.cssをAIを使って読解 (Tailwind編)

に公開

この記事ではNext.jsのcreate-next-appコマンドで自動作成されるglobal.cssについて理解を深めていきます。その中身を見ていくと、パッと見では意図が分かりづらいCSS記述が一部あるのですが、予備知識がなくてもAIコーディングツールを使えば読解を楽にしてくれます。

AIコーディングツールはソースコードを「書く」だけでなく、「読む」場面でも力を発揮します。AIを使ってコードを読むことの有用性は、Claudeの開発元であるAnthropic社による動画「Claude Code best practices」の中でも、主要な用途の一つ「Explore codebase and history」として紹介されています。

YouTube動画「Claude Code best practices」6:25付近のスクリーンショット)
6分25秒付近のスクリーンショット(一部加工)

ソースコードの読解に使うツールはClaude Codeである必要はなく、Gemini CLIでもOpenAI Codex CLIでもCursorでも、好きなものを選んでください。

Next.jsにおけるCSSの選択肢

global.cssの中身を詳細に見ていく前に、Next.jsにおけるCSS利用方法について整理しましょう。Next.jsではCSSの取り扱いに関して、様々な選択肢が提供されています。詳しくは以下の公式ドキュメントの通りです。

https://nextjs.org/docs/app/getting-started/css

  • Tailwind CSS
  • CSS Modules
  • Global CSS (global.css)
  • External Stylesheets
  • Sass
  • CSS-in-JS

これらCSSの選択肢うち「Tailwind CSSだけ」あるいは「CSS Modulesだけ」など、通常どれか一つだけを選べばいいのですが、global CSSに関してだけは異なり、他のどの選択肢を選んでも、global CSSも合わせて使うケースが多くなります。つまり「Tailwindとglobal CSSを併用」あるいは「CSS Modulesとglobal CSSを併用」といった具合です。

その理由は、どの選択肢を選んでも、CSSには「真にグローバルな」ごく一部の設定項目があるからです。公式ドキュメントにも以下のように記述されています。

We recommend using global styles for truly global CSS (like Tailwind's base styles), Tailwind CSS for component styling, and CSS Modules for custom scoped CSS when needed.

2パターンのglobal.cssがある

Next.jsのcreate-next-appコマンドで自動作成されるglobal.cssには2パターンあり、以下の質問にYesで答えるかNoで答えるかによっての中身が変わります。

✔ Would you like to use Tailwind CSS? … No / Yes

ちなみに、Next.jsのGitHub pull request #84750により、Tailwindがデフォルトの選択肢になりました。

Tailwind選択時のglobal.css

先程の質問にYesで答えると、以下のglobal.cssが自動作成されます(Noの場合はこちらの記事)。

global.cssの中身
@import "tailwindcss";

:root {
  --background: #ffffff;
  --foreground: #171717;
}

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --font-sans: var(--font-geist-sans);
  --font-mono: var(--font-geist-mono);
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #0a0a0a;
    --foreground: #ededed;
  }
}

body {
  background: var(--background);
  color: var(--foreground);
  font-family: Arial, Helvetica, sans-serif;
}

それでは各部分についてAIコーディングツールを使って読み解いていきましょう。本記事を書く際に、私はGemini CLIを使いましたが、先述の通り他のAIツールでも構いません。

Gemini CLIのスクリーンショット

一行目の@import "tailwindcss";

Tailwindに慣れていないと、global.cssの最初の一行目から戸惑ってしまいます。

@import "tailwindcss";

まずはこの行が何をしているのかAIに聞いてみましょう。

プロンプト
@app/globals.cssの以下の部分が何をしているか教えて下さい

@import "tailwindcss";
AIの回答(抜粋)
✦ @import "tailwindcss"; は、app/globals.css ファイル内で Tailwind CSS をインポート
するためのPostCSSディレクティブです。
AIの回答(全体)
✦ @import "tailwindcss"; は、app/globals.css ファイル内で Tailwind CSS をインポート
するためのPostCSS ディレクティブです。
この行は、Tailwind CSS が提供する以下の主要なレイヤーを CSS ファイルに挿入します。

1. `base`: Tailwind のプリフライトスタイル(Preflight
  styles)を挿入します。これは、ブラウザ間のスタイルの一貫性を保つための CSS リセットです。
2. `components`: Tailwind のコンポーネントクラス(例: btn, card など、Tailwind
  の設定で有効になっている場合)を挿入します。
3. `utilities`: Tailwind のユーティリティクラス(例: text-blue-500, flex, p-4
  など)を挿入します。

これにより、アプリケーション全体で Tailwind CSS
のクラスを使用できるようになります。Next.js のようなフレームワークで Tailwind CSS
を使用する際の一般的な設定方法です。

「PostCSSディレクティブ」というキーワードが出てきたので、続けて聞いてみます。

プロンプト
PostCSSディレクティブとはなんですか?
AIの回答(抜粋)
✦ PostCSS ディレクティブとは、PostCSS というツールが処理する際に特別な意味を持つ、
CSS ファイル内の特殊なルールや命令のことです。

(中略)...これらは標準の CSS 仕様には含まれていないため、PostCSSがなければ単なる
無効な @ ルールとして扱われます。
AIの回答(全体)
```:AIの回答
✦ PostCSS ディレクティブとは、PostCSS というツールが処理する際に特別な意味を持つ、
CSS ファイル内の特殊なルールや命令のことです。

まず、PostCSS とは、JavaScript プラグインを使って CSS を変換するためのツールです。
CSS を直接書くのではなく、PostCSSを通すことで、より高度な機能や構文(まだ標準化され
ていないものも含む)を利用できるようになります。

そして、ディレクティブは、この PostCSS が解釈し、特定の処理を実行するための指示です。
これらは標準の CSS 仕様には含まれていないため、PostCSSがなければ単なる無効な @ ルール
として扱われます。

ディレクティブは@から始まるようなので、次の質問を投げかけます。

プロンプト
@から始まるものは全てPostCSSディレクティブですか?
AIの回答(抜粋)
✦ いいえ、`@` から始まるものがすべて PostCSS ディレクティブであるわけではありません。

@ から始まるルールには、大きく分けて以下の2種類があります。
1. 標準の CSS アットルール (At-rules):
* 例:
    * @media: メディアクエリを定義し、特定のデバイス特性に基づいてスタイルを適用します。
    * @import: 別の CSS ファイルを現在のファイルにインポートします。
    * @font-face: カスタムフォントを定義します。
    * @keyframes: CSS アニメーションのキーフレームを定義します。
    * @charset: スタイルシートの文字エンコーディングを指定します。

2. PostCSS ディレクティブ:
* 例:
  * @tailwind base;
    @tailwind components;
    @tailwind utilities; : Tailwind CSS のスタイルを生成・挿入します。
  * @apply: Tailwind CSS のユーティリティクラスをカスタム CSS ルール内で適用します。
  * @layer: Tailwind CSS や PostCSS の一部プラグインで、CSS のカスケードレイヤーを
            管理するために使用されます。

AIの回答(全体)
✦ いいえ、`@` から始まるものがすべて PostCSS ディレクティブであるわけではありません。

PostCSS ディレクティブは、PostCSS プラグインによって解釈・処理される「特別な @ ルール」です。

@ から始まるルールには、大きく分けて以下の2種類があります。

  1. 標準の CSS アットルール (At-rules):
    これらは CSS の公式仕様の一部であり、ブラウザが直接解釈できるものです。PostCSSはこれらの
    ルールを変換するのではなく、そのまま通過させるか、他のプラグインが追加の処理を行うことが
    あります。
      * 例:
          * @media: メディアクエリを定義し、特定のデバイス特性に基づいてスタイルを適用します。
          * @import: 別の CSS ファイルを現在のファイルにインポートします。
          * @font-face: カスタムフォントを定義します。
          * @keyframes: CSS アニメーションのキーフレームを定義します。
          * @charset: スタイルシートの文字エンコーディングを指定します。

  2. PostCSS ディレクティブ:
    これらは標準の CSS 仕様には含まれておらず、PostCSS プラグイン(例えば tailwindcss プラグ
    イン)が独自の機能を提供するために導入したカスタムの @ルールです。PostCSS がこれらのディレク
    ティブを検知すると、対応するプラグインが動作し、ディレクティブを実際の CSSコードに変換したり、
    他の処理を行ったりします。
      * 例:
          * @tailwind base;, @tailwind components;, @tailwind utilities;: 
                             Tailwind CSS のスタイルを生成・挿入します。
          * @apply: Tailwind CSS のユーティリティクラスをカスタム CSS ルール内で適用します。
          * @layer: Tailwind CSS や PostCSS の一部プラグインで、CSS のカスケードレイヤーを管理するために使用されます。

したがって、@ から始まるルールを見た場合、それが標準の CSS アットルールなのか、それとも PostCSS
プラグインによって導入されたカスタムディレクティブなのかを区別する必要があります。

たしかに、言われてみれば@media@keyframesはPostCSSではなく、標準CSSでもよく見かけます。しかし、@importは上記によると標準CSSであり、一方で冒頭のAIによる回答ではPostCSSディレクティブでした。

再掲
✦ @import "tailwindcss"; は、app/globals.css ファイル内で Tailwind CSS をインポート
するためのPostCSSディレクティブです。

はたして @import "tailwindcss";は標準CSSなのでしょうか?PostCSSディレクティブなのでしょうか?

プロンプト
@importは標準のCSSアットルールのはずなのに、なんでPostCSSディレクティブなのですか?
AIの回答(抜粋)
その点は非常に紛らわしいですよね。結論から言うと、@import "tailwindcss"; は、
標準の `@import` の構文を借りた、PostCSS のための特別な指示だからです。
AIの回答(全体)
✦ 素晴らしい質問です。その点は非常に紛らわしいですよね。的確なご指摘です。

結論から言うと、@import "tailwindcss"; は、標準の `@import` の構文を借りた、PostCSS のための特別な指示だからです。

以下のように整理すると分かりやすいです。

  1. 標準の `@import` の役割:
    CSS の仕様で定められた @import は、ファイルパスや URL を指定して、別の CSS ファイルを読み込むためのものです。

  1     /* これは標準のCSS。another-style.cssというファイルを読み込む */
  2     @import 'another-style.css';
  3 
  4     /* これも標準のCSS。URLからファイルを読み込む */
  5     @import url('https://fonts.googleapis.com/css?family=Roboto');
    ブラウザはこれらのパスや URL を見て、指定されたファイルを解釈しようとします。

  2. `@import "tailwindcss";` の場合:
    この行にある "tailwindcss" は、ファイル名や URL ではありません。これは Tailwind CSS
プラグインだけが理解できる「キーワード」や「識別子」のようなものです。
    もし PostCSS の処理を通さずにこの CSS を直接ブラウザで読み込もうとすると、ブラウザは "tailwindcss"
という名前のファイルを見つけられずにエラーになります。

  3. PostCSS の役割:
    tailwindcss プラグインは、CSS ファイルを処理する際に @import "tailwindcss";
という行を見つけると、これを「ファイル読み込み」として扱いません。
    代わりに、「ここに Tailwind CSS の全スタイル(base, components, utilities)を生成して挿入せよ」という特別な命令
(ディレクティブ) として解釈します。
    そして、その命令に従って、その行を何千行もの実際の CSS コードに置き換えます。

まとめ

@import というルール自体は標準の CSS ですが、"tailwindcss" という引数(読み込み対象)が非標準であり、PostCSS の tailwindcss
プラグインがこの特別な引数を解釈して独自の処理を行うため、「PostCSS ディレクティブのように機能する」と説明されます。

この構文が紛らわしいため、Tailwind CSS は @tailwind base; のような、明らかに標準 CSS
ではない独自のディレクティブも提供しています。どちらを使っても、tailwindcss プラグインが行う処理は同じです。

@import "tailwindcss";の全容

以上より、@import "tailwindcss";の全容がわかりました。ここから先はAIの回答だけでなく、Google検索で取得した情報も合わせて解説します。

Tailwindは最新のバージョンであるv4にて、以下のたった一行による指定で複数の@tailwindディレクティブ(後述)を置き換えました。

@import "tailwindcss";

Just one-line of CSS — no more @tailwind directives, just add @import "tailwindcss" and start building.

https://tailwindcss.com/blog/tailwindcss-v4#simplified-installation

それ以前のv3の指定がこちらです。3行の@tailwindディレクティブを記載することが初期設定として推奨されています。

@tailwind base;
@tailwind components;
@tailwind utilities;

https://v3.tailwindcss.com/docs/installation

つまり@import "tailwindcss";は、上記3行の@tailwindディレクティブに相当する役割を果たします。それでは、v3で使われていた、これら3つの@tailwindディレクティブの役割を理解しましょう。

プロンプト
これらはどんな役割を持っていますか?
  @tailwind base;
  @tailwind components;
  @tailwind utilities;
AIの回答
Tailwind CSS の機能としての `base`, `components`, `utilities`

Tailwind CSS は、以下の3つの主要なレイヤー(層)で構成されています。

1. `base`:
  * 役割: ブラウザ間の表示の差異をなくすためのスタイルリセット層です。Tailwind ではこれを
          Preflightと呼んでいます。例えば、見出し (h1, h2 など)のマージンやフォントサイズ
          をリセットし、画像がブロック要素として扱われるようにするなど、一貫した土台を提供
          します。
  * 指示方法: CSS ファイル内で @tailwind base; と書くことで、このレイヤーのスタイルが
              すべて挿入されます。

2. `components`:
  * 役割: 再利用可能なコンポーネントクラスを定義するための層です。例えば、btn というクラス
          に複数のユーティリティをまとめる、といった使い方をします。ただし、デフォルトでは
          このレイヤーはほとんど空です。主にユーザー自身が tailwind.config.tsで定義したり、
          Tailwind UI のようなライブラリがクラスを追加したりするために使われます。
  * 指示方法: @tailwind components; と書くことで、定義されたコンポーネントクラスが挿入
             されます。

3. `utilities`:
  * 役割: Tailwind の最も特徴的な部分で、flex, pt-4, text-red-500
          のような、単一の目的を持つ膨大な数のユーティリティクラスを提供します。これにより、
          HTMLを離れることなくスタイリングが可能になります。
  * 指示方法: @tailwind utilities; と書くことで、tailwind.config.ts
             の設定に基づいて生成されたすべてのユーティリティクラスが挿入されます。

再びV4の話に戻ると、これらに相当する役割を@import "tailwindcss";果たすわけですが、それについては、以下のリンク先に記載されています。

https://tailwindcss.com/docs/preflight

もし、なんの予備知識もなくリンク先を読んでいたら理解が難しかったでしょう。実際のCSS記述例をもとにAIと対話するという形だからこそ、スムーズにここまでたどり着くことができたと思います。

:rootでのbackground / foreground色指定

続いてこちらの部分を読み解いていきます。

プロンプト
@app/globals.cssの以下の部分が何をしているか教えて下さい

:root {
  --background: #ffffff;
  --foreground: #171717;
}
AIの回答(全体)
app/globals.css の :root ブロックは、CSS カスタムプロパティ(CSS Variables とも呼ばれます)を定義しています。

  具体的には、以下の役割を持っています。

   1. `:root` セレクタ:
      これは CSS の擬似クラスセレクタで、ドキュメントツリーのルート要素(HTML 
      ドキュメントの場合は <html> 要素)を指します。:root で定義されたカスタム
      プロパティは、そのドキュメント内のどこからでもアクセスできる「グローバル変数」
      のようなものになります。

   2. カスタムプロパティの定義:
       * --background: #ffffff;: --background という名前のカスタムプロパティ
       を定義し、その値を白色 (#ffffff) に設定しています。
       * --foreground: #171717;: --foreground という名前のカスタムプロパティ
       を定義し、その値を濃い灰色 (#171717) に設定しています。

   3. 目的:
      これらのカスタムプロパティは、アプリケーション全体で一貫した色を管理するため
      に使用されます。このブロックでは、デフォルトのテーマ(通常はライトモード)の
      背景色と前景色を定義しています。

   4. 使用例:
      この後、body セレクタなどで var(--background) や var(--foreground)
      のように参照することで、これらの定義された色を適用しています。

   1     body {
   2       background: var(--background); /* ここで --background の値が使われる */
   3       color: var(--foreground);     /* ここで --foreground の値が使われる */
   4       /* ... */
   5     }

   5. ダークモードとの連携:
      提供されたコードの続きにある @media (prefers-color-scheme: dark)ブロックでは、
      ユーザーがダークモードを好む場合に、これらのカスタムプロパティの値を上書きして、
      背景色と前景色をダークモードに適した色に変更しています。これにより、テーマの切り
      替えが容易になります。

  要するに、この :root ブロックは、アプリケーションの基本的なカラースキーム(特にライト
  モードのデフォルト)を定義し、CSS全体で再利用可能にするための中心的な場所です。

ここからはAIの回答を分解して解説しましょう。

AIの回答(抜粋)
CSSカスタムプロパティ(CSS Variables とも呼ばれます)を定義しています。

--から始まる--background--foregroundなどは、いわゆる「CSSにおける変数」であり、正式にはCSSカスタムプロパティ(CSS Variables)と呼ばれる記法です。

https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Cascading_variables/Using_custom_properties

次は:rootセレクタについてです。

AIの回答(抜粋)
1. `:root` セレクタ:
  これは CSS の擬似クラスセレクタで、ドキュメントツリーのルート要素(HTML 
  ドキュメントの場合は <html> 要素)を指します。

:rootセレクタについてはこちら。

https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:root

rootではなく、コロンから始まる:rootであることに注意してください。

ちなみにCSSカスタムプロパティを:rootに定義すべきか、別の箇所に定義すべきか?についてはこちらです。

プロンプト
CSSカスタムプロパティは:rootに定義するのが普通ですか?
✦ グローバルに(アプリケーション全体で)使用するカスタムプロパティは `:root` 
  に定義するのが最も一般的で、(中略)...コンポーネント固有の値はそのコンポーネント
  のセレクタに定義する、という使い分けが一般的です。
AIの回答(全体)
✦ はい、グローバルに(アプリケーション全体で)使用するカスタムプロパティは `:root` 
  に定義するのが最も一般的で、ベストプラクティスとされています。

  理由は以下の通りです。

   1. 継承の仕組み:
      CSS カスタムプロパティは、定義された要素とそのすべての子孫要素に継承されます。

   2. `:root` の役割:
      :root はドキュメントの最上位要素である <html> 要素を指します。ここにカスタムプロパティを定義すると、<html>
  のすべての子孫要素、つまりページ上のすべての要素がそのプロパティを継承して利用できるようになります。

  これにより、アプリケーション全体で共有したいテーマカラー、フォントサイズ、スペーシングなどの値を「グローバル変数」として一元管理
  できるため、非常に便利です。

  ---

  補足:`:root` 以外で定義する場合

  もちろん、カスタムプロパティを :root
  以外で定義することも可能です。その場合、プロパティのスコープ(有効範囲)は、定義された要素とその子孫に限定されます。

  これは、特定のコンポーネント内だけで有効な値を定義したい場合に役立ちます。

  例:特定のコンポーネント内だけで使う変数を定義する

    1 /* グローバルな変数 */
    2 :root {
    3   --primary-color: blue;
    4 }
    5 
    6 /* .alert コンポーネント内だけで使うローカルな変数 */
    7 .alert {
    8   --alert-background-color: #ffdddd;
    9   --alert-text-color: #d8000c;
   10 
   11   background-color: var(--alert-background-color);
   12   color: var(--alert-text-color);
   13   border: 1px solid var(--alert-text-color);
   14 }
   15 
   16 .alert p {
   17   /* 親から --alert-text-color を継承して利用できる */
   18   color: var(--alert-text-color);
   19 }
   20 
   21 .some-other-element {
   22   /* ここでは --alert-background-color は利用できない(スコープ外) */
   23   background-color: var(--alert-background-color); /* 無効 */
   24 }

  このように、グローバルな値は `:root`
  に、コンポーネント固有の値はそのコンポーネントのセレクタに定義する、という使い分けが一般的です。

至極真っ当な意見が返ってきているので、最終的には自分のプロジェクトに合わせて、他人の例を参考にしつつ選んでいくしかなさそうです。

以上より、以下のブロックは、

:root {
  --background: #ffffff;
  --foreground: #171717;
}

--background--foregroundという2つのCSSカスタムプロパティを、ドキュメント全体から参照可能な:rootに定義していることがわかりました。これらがどう参照され、利用されるのかは後述します。

@theme inline指定

次はこちらです。

@app/globals.cssの以下の部分が何をしているか教えて下さい

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --font-sans: var(--font-geist-sans);
  --font-mono: var(--font-geist-mono);
}
AIの回答(抜粋)
@theme ディレクティブは、Tailwind CSS が提供する PostCSS アットルールであり
(中略)...@theme で定義した CSSカスタムプロパティを(中略)...参照し、Tailwind
のユーティリティクラス(例: bg-primary, font-sans など)を動的に設定することができます。
AIの回答(全体)
  Tailwind CSS の `@theme` ディレクティブの役割

  @theme ディレクティブは、Tailwind CSS が提供する PostCSS アットルールであり、CSS カスタムプロパティ(CSS 
  Variables)を使ってデザインシステムやテーマの値を直接 CSS 内で定義・拡張するために使用されます。

  このディレクティブを使うことで、以下のことが可能になります。

   1. デザインシステムの定義:
      色、フォント、スペーシングなどのデザインに関する値を CSS 変数として一元的に管理できます。

   2. Tailwind 設定との連携:
      @theme で定義した CSS 変数を、tailwind.config.js (または tailwind.config.ts) ファイル内で参照し、Tailwind
  のユーティリティクラス(例: bg-primary, font-sans など)を動的に設定することができます。これにより、CSS
  変数を変更するだけで、Tailwind のユーティリティクラスの挙動も連動して変わるようになります。

   3. カスタム CSS との統合:
      Tailwind のユーティリティクラスだけでなく、自分で書いたカスタム CSS からもこれらの CSS 変数を参照できるため、Tailwind
  とカスタム CSS の間でデザインの一貫性を保ちやすくなります。

  このコードブロックの具体的な役割

   * `@theme inline`:
      inline というキーワードは、このテーマ定義がデフォルトまたは主要なテーマ設定であることを示唆している可能性があります。プロジェ
  クトによっては、複数のテーマ(例: dark, compact など)を定義し、それぞれに名前を付けることがあります。

   * 内部のカスタムプロパティ定義:
      このブロック内では、新しい CSS カスタムプロパティを定義し、既存のカスタムプロパティの値を割り当てています。
       * --color-background: var(--background);:
          :root で定義された --background の値を、--color-background
  というよりセマンティックな(意味が分かりやすい)名前にマッピングしています。
       * --color-foreground: var(--foreground);:
          同様に、--foreground を --color-foreground にマッピングしています。
       * --font-sans: var(--font-geist-sans);:
          --font-geist-sans の値を --font-sans にマッピングしています。
       * --font-mono: var(--font-geist-mono);:
          --font-geist-mono の値を --font-mono にマッピングしています。

  まとめ

  この @theme inline ブロックは、アプリケーションの基本的なデザイン変数(--background, --foreground, --font-geist-sans,
  --font-geist-mono)を、Tailwind CSS の設定や他のカスタム CSS
  で利用しやすいように、より汎用的でセマンティックな名前(--color-background, --font-sans
  など)にエイリアス(別名)付けしている部分です。これにより、デザインシステムの一貫性を保ちつつ、Tailwind
  の強力な機能を最大限に活用するための基盤を構築しています。

こういった@themeの使い方は、公式ドキュメントの以下の部分で説明されています。

Theme variables are special CSS variables defined using the @theme directive that influence which utility classes exist in your project.

https://tailwindcss.com/docs/theme

あるいは@themeについては、こちらのブログを見るとわかりやすいかもしれません。

https://azukiazusa.dev/blog/tailwind-css-v4-css-first-configurations/

ところで、以下の部分は:rootで定義した--background--foregroundを参照しているだけなのでわかりやすいですが、

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  ...
}

一方、以下の部分は--font-geist-sans--font-geist-monoがどこで定義されているのか見当たりません。

@theme inline {
  ...
  --font-sans: var(--font-geist-sans);
  --font-mono: var(--font-geist-mono);
}

AIに質問してみます。

プロンプト
--font-geist-sansと--font-geist-monoはどこで定義されていますか?
AIからの回答(抜粋)
--font-geist-sans と --font-geist-mono は、app/layout.tsx ファイルで定義されています。

5  const geistSans = Geist({
6    variable: "--font-geist-sans", // (2)
7    subsets: ["latin"],
8  });
9 
10 const geistMono = Geist_Mono({
11   variable: "--font-geist-mono", // (3)
12   subsets: ["latin"],
13 });
...
24       <body
25         className={`${geistSans.variable} ${geistMono.variable} antialiased`}
26       >
27         {children}
28       </body>
AIからの回答(全体)
プロンプト
✦ --font-geist-sans と --font-geist-mono は、app/layout.tsx ファイルで定義されています。

  具体的には、Next.js の組み込みフォント最適化機能である next/font/google モジュールを使用して定義されています。

    1 import { Geist, Geist_Mono } from "next/font/google"; // (1)
    2 
    3 // ...
    4 
    5 const geistSans = Geist({
    6   variable: "--font-geist-sans", // (2)
    7   subsets: ["latin"],
    8 });
    9 
   10 const geistMono = Geist_Mono({
   11   variable: "--font-geist-mono", // (3)
   12   subsets: ["latin"],
   13 });
   14 
   15 // ...
   16 
   17 export default function RootLayout({
   18   children,
   19 }: Readonly<{
   20   children: React.ReactNode;
   21 }>) {
   22   return (
   23     <html lang="en">
   24       <body
   25         className={`${geistSans.variable} ${geistMono.variable} antialiased`} // (4)
   26       >
   27         {children}
   28       </body>
   29     </html>
   30   );
   31 }

  説明:

   1. `import { Geist, Geist_Mono } from "next/font/google";`:
      ここでは、Vercel Geist フォントの Sans-serif バージョンと Monospace バージョンを Next.js
  のフォントローダーからインポートしています。

   2. `variable: "--font-geist-sans"`:
      Geist() 関数を呼び出す際に、variable オプションで --font-geist-sans という名前の CSS
  カスタムプロパティを指定しています。これにより、ロードされた Geist Sans フォントがこの CSS 変数として利用可能になります。

   3. `variable: "--font-geist-mono"`:
      同様に、Geist_Mono() 関数では --font-geist-mono という名前で Geist Mono フォントが CSS 変数として公開されます。

   4. `className={`${geistSans.variable} ${geistMono.variable}`:
      RootLayout コンポーネントの <body> タグに、geistSans.variable と geistMono.variable
  がクラス名として追加されています。next/font は、これらの variable プロパティを通じて、対応する CSS カスタムプロパティ(例:
  --font-geist-sans: 'Geist Sans', sans-serif; のような定義)を <body>
  要素に注入します。これにより、これらのフォント変数がアプリケーション全体で利用できるようになります。

  したがって、--font-geist-sans と --font-geist-mono は、app/layout.tsx で next/font/google モジュールを使って定義され、<body>
  要素に適用される CSS カスタムプロパティとして機能しています。

--font-geist-sans--font-geist-monoについては、CSS内ではなくlayout.tsxからclassName属性として指定されている事がわかりました。

Geist()関数とGeist_Mono()関数はNext.jsのnext/fontパッケージが提供する関数です。

https://nextjs.org/docs/pages/getting-started/fonts

@media (prefers-color-scheme: dark)指定

続いてはこちら。一見してダークテーマに関わる指定のようです。

プロンプト
@app/globals.cssの以下の部分が何をしているか教えて下さい

@media (prefers-color-scheme: dark) {
  :root {
    --background: #0a0a0a;
    --foreground: #ededed;
  }
}
AIからの回答(全体)
✦ app/globals.css のこの部分は、ユーザーのシステム設定に基づいてダークモードを適用するための CSS メディアクエリです。

  具体的には、以下の役割を持っています。

   1. `@media` ルール:
      これは CSS
  の標準的なアットルールで、特定の条件(メディアタイプやメディア特性)が満たされた場合にのみ、その中のスタイルを適用します。

   2. `(prefers-color-scheme: dark)`:
      これはメディア特性の一つで、ユーザーのオペレーティングシステム(OS)やブラウザの設定が「ダークテーマ」を優先しているかどうか
  を検出します。
       * dark: ユーザーがダークテーマを好む設定にしている場合。
       * light: ユーザーがライトテーマを好む設定にしている場合。

   3. `:root` ブロック:
      このメディアクエリの内部にある :root ブロックは、ユーザーがダークテーマを好む場合にのみ適用されます。
       * --background: #0a0a0a;: 背景色を非常に暗い灰色 (#0a0a0a) に上書きします。
       * --foreground: #ededed;: 前景色(テキストの色など)を明るい灰色 (#ededed) に上書きします。

  全体としての目的

  このコードブロックは、ユーザーが OS やブラウザの設定でダークモードを有効にしている場合、アプリケーションのデフォルトの背景色と前
  景色を、ダークモードに適した色(暗い背景に明るいテキスト)に自動的に切り替える役割を果たします。

  これにより、ユーザーのシステム設定に合わせた、より快適な閲覧体験を提供することができます。

ここからはAIの回答を分解して説明しましょう。

@mediaはCSSでよく見るメディアクエリですが、

AIの回答(抜粋)
1. `@media`ルール:
  これは CSSの標準的なアットルールで、特定の条件(メディアタイプや
  メディア特性)が満たされた場合にのみ、その中のスタイルを適用します。

(prefers-color-scheme: dark)あまり馴染みがない人もいると思います。

AIの回答(抜粋)
2. `(prefers-color-scheme: dark)`:
  これはメディア特性の一つで、ユーザーのオペレーティングシステム(OS)やブラウザの
  設定が「ダークテーマ」を優先しているかどうかを検出します。
    * dark: ユーザーがダークテーマを好む設定にしている場合。
    * light: ユーザーがライトテーマを好む設定にしている場合。

https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-color-scheme

上記のAI回答とMozillaのリンク先を見ると、OSやブラウザの設定であることはわかりますが、どこで設定できるものなのかはわかりません。そこでAIに聞いてみます。

プロンプト
prefers-color-schemeはChromeブラウザの場合どこで設定できますか?
AIからの回答(全体)
✦ prefers-color-scheme は、主にオペレーティングシステム(OS)の表示設定に連動しています。Chrome
  ブラウザ自体に直接この設定を変更する項目はありませんが、OS の設定を Chrome が読み取って反映します。

  1. OS の設定を変更する(一般的な方法)

  お使いの OS の設定を変更することで、Chrome の prefers-color-scheme の挙動が変わります。

   * Windows 10/11 の場合:
       1. 「設定」を開きます。
       2. 「個人用設定」→「色」に進みます。
       3. 「モードを選択してください」または「Windows の表示モードを選択」で「ダーク」または「ライト」を選択します。

   * macOS の場合:
       1. 「システム設定」(または「システム環境設定」)を開きます。
       2. 「外観」に進みます。
       3. 「ライト」「ダーク」「自動」のいずれかを選択します。「自動」の場合、時間帯によってライト/ダークが切り替わります。

   * Linux の場合:
      使用しているデスクトップ環境(GNOME, KDE, XFCE
  など)によって設定場所が異なりますが、通常は「設定」→「外観」または「テーマ」の項目でダークモード/ライトモードの設定が可能です。

  2. Chrome DevTools で一時的にシミュレートする(開発者向け)

  開発目的で、OS の設定を変更せずに prefers-color-scheme の挙動を確認したい場合は、Chrome
  の開発者ツール(DevTools)で一時的にシミュレートできます。

   1. Chrome でウェブページを開きます。
   2. F12 キーを押すか、右クリックして「検証」を選択し、開発者ツールを開きます。
   3. 開発者ツールの右上にある「︙」(3点リーダー)をクリックし、「More tools」→「Rendering」を選択します。
   4. 「Rendering」タブの中に「Emulate CSS media feature prefers-color-scheme」という項目があります。
   5. ここで「No emulation」「light」「dark」を選択することで、一時的に prefers-color-scheme の値をシミュレートできます。
AIの回答(抜粋)
✦ prefers-color-scheme は、主にオペレーティングシステム(OS)の表示設定に連動
  しています。Chromeブラウザ自体に直接この設定を変更する項目はありませんが、OS
  の設定を Chrome が読み取って反映します。

調べてみると、こちらはAIの回答が間違っていました。以下の動画のように、Chromeから設定できます。

https://youtu.be/QmshNxopsEI

AIに指摘しておきます。

プロンプト
Chromeの設定→デザイン→モードから「ダーク」「ライト」「デバイス」が選べるようですよ
AIの回答(全体)
✦ 貴重な情報ありがとうございます!私の説明が不十分でした。

  Chrome ブラウザの「設定」→「デザイン」→「モード」から「ダーク」「ライト」「デバイス」が選べるようになったのは、ユーザーがブラウザ
  内でより詳細に prefers-color-scheme の挙動を制御できるようになったことを意味します。

  それぞれの設定が prefers-color-scheme にどう影響するかは以下の通りです。

   * 「ダーク」:
      この設定を選択すると、OS の設定に関わらず、すべてのウェブサイトに対して `prefers-color-scheme: dark` 
  が適用されます。ウェブサイトはダークモードで表示されるようになります。

   * 「ライト」:
      この設定を選択すると、OS の設定に関わらず、すべてのウェブサイトに対して `prefers-color-scheme: light` 
  が適用されます。ウェブサイトはライトモードで表示されるようになります。

   * 「デバイス」:
      これがデフォルトの設定で、Chrome が OS の `prefers-color-scheme` の設定を読み取って反映します。つまり、OS
  がダークモードならウェブサイトもダークモードに、OS がライトモードならウェブサイトもライトモードになります。

  このブラウザ内の設定により、ユーザーは OS の設定とは別に、Chrome
  でのウェブサイトの表示モードを柔軟に選択できるようになっています。ご指摘いただき、ありがとうございました。

body指定

最後はこちらです。

プロンプト
body {
  background: var(--background);
  color: var(--foreground);
  font-family: Arial, Helvetica, sans-serif;
}

こちらはAIに聞くまでもなく、:rootで定義した--background, --foregroundを参照していることがわかりますね。<body>内部全体に渡って、backgroundの色と、文字色であるcolor、そしてフォントfont-familyを設定しています。

<body>内部の個別コンポーネントでこれらの設定を上書きしたい場合は、先述の@theme inlineで設定されるTailwindのユーティリティクラスを使って指定していくことになります。

https://tailwindcss.com/docs/styling-with-utility-classes

Discussion