🎨

ゼロから学ぶ React, Next.js⑨【Learn Next.js】Chapter2

2024/05/25に公開

【Chapter2】 CSSスタイリング

現在、ホームページにはスタイルが適用されていません。Next.jsアプリケーションのスタイリングには、さまざまな方法があります。

この章で扱うトピック

  • 📄 グローバルCSSファイルをアプリケーションに追加する方法
  • ✏️ TailwindとCSSモジュールの2つのスタイリング方法
  • 📝 clsxユーティリティパッケージを使用してクラス名を条件付きで追加する方法

グローバルスタイル

/app/uiフォルダを見ると、global.cssというファイルがあります。このファイルを使用して、アプリケーションのすべてのルートにCSSルールを追加できます。例えば、CSSリセットルールや、リンクなどのHTML要素に対するサイト全体のスタイルなどです。

global.cssは、アプリケーションの任意のコンポーネントでインポートできますが、通常はトップレベルのコンポーネントに追加するのが良い習慣です。Next.jsでは、これはルートレイアウトになります(詳細は後述)。

/app/layout.tsxに移動してglobal.cssファイルをインポートすることで、グローバルスタイルをアプリケーションに追加します:

/app/layout.tsx
+import '@/app/ui/global.css';
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}
メモ:@マークについて

@は、Next.jsのデフォルトの設定で定義されているエイリアス(別名)を表しています。エイリアスとは、長いパスや複雑なディレクトリ構造を簡潔に表現するための記法です。

スターターサンプルでは、tsconfig.jsonにその設定があり、@./にマッピングされています。

tsconfig.json
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./*"]
    }
  }
}

この設定により@/*["./*"]にマッピングされ、@が現在のディレクトリを表すエイリアスとして機能します。

したがって、import '@/app/ui/global.css';は、import './app/ui/global.css';と同等のものとして機能します。

エイリアスを使用すると、相対パスを使用するよりも簡潔で読みやすいインポート文を書くことができます。また、プロジェクトのディレクトリ構造を変更した場合でも、インポート文を更新する必要がありません。

開発サーバーを実行したまま、変更を保存してブラウザでプレビューします。ホームページは次のようになっているはずです:

home-page-with-tailwind

ちょっと待ってください。CSSルールを追加していないのに、どこからスタイルが来たのでしょうか?

global.cssの中を見ると、いくつかの@tailwindディレクティブがあることに気づくでしょう:

/app/ui/global.css
@tailwind base;
@tailwind components;
@tailwind utilities;

Tailwind

Tailwindは、TSXマークアップに直接ユーティリティクラスを素早く記述できるため、開発プロセスを高速化するCSSフレームワークです。

Tailwindでは、クラス名を追加することで要素をスタイリングします。例えば、text-blue-500クラスを追加すると、<h1>テキストが青になります:

<h1 className="text-blue-500">I'm blue!</h1>

CSSスタイルはグローバルに共有されますが、各クラスは各要素に個別に適用されます。つまり、要素を追加または削除しても、別のスタイルシートを維持したり、スタイルの衝突を気にしたり、アプリケーションの規模が大きくなるにつれてCSSバンドルのサイズが大きくなることを心配する必要はありません。

create-next-appを使用して新しいプロジェクトを開始すると、Next.jsはTailwindを使用するかどうかを尋ねます。yesを選択すると、Next.jsは必要なパッケージを自動的にインストールし、アプリケーションでTailwindを設定します。

/app/page.tsxを見ると、サンプルでTailwindクラスを使用していることがわかります。

/app/page.tsx
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
import Link from 'next/link';
 
export default function Page() {
  return (
    // ここでTailwindクラスを使用しています:
    <main className="flex min-h-screen flex-col p-6">
      <div className="flex h-20 shrink-0 items-end rounded-lg bg-blue-500 p-4 md:h-52">
    // ...
  )
}

Tailwindを初めて使う場合は心配しないでください。時間を節約するために、使用するすべてのコンポーネントにはすでにスタイルが適用されています。

Tailwindで遊んでみましょう!以下のコードをコピーして、/app/page.tsx<p>要素の上に貼り付けます:

/app/page.tsx
<div
  className="h-0 w-0 border-b-[30px] border-l-[20px] border-r-[20px] border-b-black border-l-transparent border-r-transparent"
/>

クイズの時間です!
知識をテストし、学んだことを確認しましょう。

上記のコードスニペットを使用すると、どのような形状が表示されますか?

A. 黄色い星
B. 青い三角形
C. 黒い三角形
D. 赤い円

解答

C. 黒い三角形

従来のCSSルールを書くことを好むか、スタイルをJSXから分離しておくことを好む場合は、CSSモジュールが優れた代替手段になります。


CSSモジュール

CSSモジュールを使用すると、一意のクラス名を自動的に作成することで、コンポーネントにCSSのスコープを設定できます。そのため、スタイルの衝突を心配する必要もありません。

このコースではTailwindを引き続き使用しますが、CSSモジュールを使用して上記のクイズと同じ結果を達成する方法を見てみましょう。

/app/uiの中に、home.module.cssという新しいファイルを作成し、以下のCSSルールを追加します:

/app/ui/home.module.css
.shape {
  height: 0;
  width: 0;
  border-bottom: 30px solid black;
  border-left: 20px solid transparent;
  border-right: 20px solid transparent;
}

次に、/app/page.tsxファイルでスタイルをインポートし、追加した<div>のTailwindクラス名をstyles.shapeに置き換えます:

/app/page.tsx
import styles from '@/app/ui/home.module.css';
<div className={styles.shape} />

変更を保存し、ブラウザでプレビューします。以前と同じ形状が表示されるはずです。

TailwindとCSSモジュールは、Next.jsアプリケーションのスタイリングで最も一般的な2つの方法です。どちらを使用するかは好みの問題です。同じアプリケーション内で両方を使用することもできます!

クイズの時間です!
知識をテストし、学んだことを確認しましょう。

CSSモジュールを使用することの利点の1つは何ですか?

A. CSSクラスのグローバルスコープを増やし、異なるファイル間での管理を容易にする。
B. CSSクラスをコンポーネントにローカルにスコープする方法を提供し、スタイルの競合のリスクを減らす。
C. CSSファイルを自動的に圧縮および縮小して、ページの読み込みを高速化する。

解答

A. CSSクラスのグローバルスコープを増やし、異なるファイル間での管理を容易にする。
CSSモジュールは、各コンポーネントに固有のクラス名を作成するので、スタイルの衝突を心配する必要はありません。


clsxライブラリを使用してクラス名を切り替える

状態やその他の条件に基づいて要素のスタイルを条件付きで設定する必要がある場合があります。

clsxは、クラス名を簡単に切り替えることができるライブラリです。詳細についてはドキュメントを参照することをお勧めしますが、基本的な使用法は次のとおりです:

  • statusを受け取るInvoiceStatusコンポーネントを作成するとします。status'pending'または'paid'のいずれかです。
  • 'paid'の場合は色を緑に、'pending'の場合は色をグレーにしたいとします。

clsxを使用して条件付きでクラスを適用できます:

/app/ui/invoices/status.tsx
import clsx from 'clsx';
 
export default function InvoiceStatus({ status }: { status: string }) {
  return (
    <span
      className={clsx(
        'inline-flex items-center rounded-full px-2 py-1 text-sm',
        {
+          'bg-gray-100 text-gray-500': status === 'pending',
+          'bg-green-500 text-white': status === 'paid',
        },
      )}
    >
    // ...
)}

クイズの時間です!
知識をテストし、学んだことを確認しましょう。

コードエディタで「clsx」を検索します。どのコンポーネントがclsxを使用して条件付きでクラス名を適用していますか?

A. status.tsxpagination.tsx
B. table.tsxstatus.tsx
C. nav-links.tsxtable.tsx

解答

A. status.tsxpagination.tsx


その他のスタイリングソリューション

ここまで説明したアプローチに加えて、以下の方法でもNext.jsアプリケーションをスタイリングできます:

詳細については、CSSドキュメントを参照してください。


次の章

https://zenn.dev/gunjo/articles/4e7f7aa5f5bc58

Discussion