この課題のねらい
この演習のテーマは「Next.js での CSS Modules の基本を、自分の手でちゃんと通すこと」です。
ポイントは次の3つです。
CSS Modules用のファイルを作るclassName でコンポーネントにスタイルを当てる
ホバー時(マウスを乗せたとき)のスタイルも CSS Modules で書いてみる
「なんとなく inline style」で済ませるのを卒業して、
「コンポーネントごとにスタイルを分けて管理する」感覚をつかんでもらいます。
CSS Modulesでスタイル適用(ファイルの作り方と使い方)
CSS Modulesって何か
CSS Modules は、
コンポーネントごとに CSS を「モジュール」として分けて書ける仕組みです。
通常の CSS だと、
同じクラス名が他のページでかぶったり、
古いスタイルが思わぬところに影響したりしがちです。
CSS Modules を使うと、
Button.module.css の .rootCard.module.css の .root
は別物として扱われます(内部的には自動でユニークなクラス名に変換される)。
そのおかげで「コンポーネント単位でスタイルを閉じ込める」ことができます。
例:ボタン用の CSS Modules ファイルを作る
まずはボタンコンポーネントを例にします。app/components/Button.tsx と app/components/Button.module.css を用意します。
CSS ファイルから作ってみましょう。
/* app/components/Button.module.css */
.root {
padding: 8px 16px;
border-radius: 9999px;
border: none;
background-color: #2563eb;
color: white;
font-size: 14px;
cursor: pointer;
}
ここでは .root というクラスにスタイルをまとめています。
クラス名自体は好きな名前で構いませんが、
「このコンポーネントのメイン要素」という意味で .root はよく使われます。
コンポーネント側でCSS Modulesを読み込む
次に、Button.tsx でこの CSS を読み込んで使います。
// app/components/Button.tsx
"use client";
import type { ReactNode } from "react";
import styles from "./Button.module.css";
type ButtonProps = {
children: ReactNode;
};
export default function Button({ children }: ButtonProps) {
return <button className={styles.root}>{children}</button>;
}
TSXここで大事なポイントは 2 つです。
import styles from "./Button.module.css";
CSS Modules のファイルを読み込むと、「クラス名のマップ」として styles オブジェクトが渡されます。
className={styles.root}
CSS 側で定義した .root を styles.root として指定します。
このとき、HTML 上では class="Button_root__xxxx" のようなユニークな名前に変換されます(自分で意識する必要はありません)。
これで、
<Button>クリック</Button> を使うとButton.module.css の .root のスタイルが当たったボタンが表示される
という状態になります。
className設定(実際に画面で使ってみる)
ページ側からButtonコンポーネントを使う
さっき作った Button をトップページから使ってみましょう。
// app/page.tsx
import Button from "./components/Button";
export default function HomePage() {
return (
<>
<h1>CSS Modules の練習</h1>
<p>共通ボタンコンポーネントにスタイルを当てています。</p>
<div style={{ marginTop: "16px" }}>
<Button>クリックしてね</Button>
</div>
</>
);
}
TSXブラウザで確認すると、
青い角丸ボタン
白い文字
ホバー時にマウスカーソルが pointer
になっているはずです(pointer は CSS で指定しました)。
ここまでで、
CSS Modules ファイルを作る
コンポーネントで import styles from "..." するclassName={styles.クラス名} でスタイルを当てる
という一連の流れを一度通せています。
classNameは複数組み合わせることもできる
少し先取りになりますが、className は 1 個だけでなく複数も組み合わせられます。
例えば、CSS 側でこう定義したとします。
/* Button.module.css */
.root {
padding: 8px 16px;
border-radius: 9999px;
}
.primary {
background-color: #2563eb;
color: white;
}
.outline {
background-color: white;
color: #2563eb;
border: 1px solid #2563eb;
}
TypeScript 側でこう書けば、
<button className={`${styles.root} ${styles.primary}`}>送信</button>
TSXroot と primary の両方のスタイルが適用されます。
「ベースのスタイル(root)+バリエーション(primary / outline)」というパターンは、実務でもよく使います。
ホバー時のスタイル追加(:hoverでインタラクティブに)
CSS Modulesでも普通に:hoverが使える
挑戦課題は「ホバー時のスタイル追加」です。
これは CSS Modules でも通常の CSS と同じように :hover を使えばOKです。
先ほどの Button.module.css を少し拡張します。
/* app/components/Button.module.css */
.root {
padding: 8px 16px;
border-radius: 9999px;
border: none;
background-color: #2563eb;
color: white;
font-size: 14px;
cursor: pointer;
transition: background-color 0.15s ease, transform 0.1s ease;
}
.root:hover {
background-color: #1d4ed8; /* 少し濃くする */
transform: translateY(-1px); /* ちょっと浮かせる */
}
ここでやっているのは、
通常時は background-color: #2563eb
ホバー時は少し濃い #1d4ed8 に変える
おまけで transform: translateY(-1px) でちょっとだけ浮かせる
という視覚的フィードバックです。
transition を書いているので、
色と位置の変化がスッと滑らかになります。
この状態でページをリロードして、
ボタンにマウスを乗せると「ふわっと強調される」感じになるはずです。
もう少しだけ実務っぽいホバーパターン
実務では、ホバー時に次のような変化をよく使います。
背景色を少し暗くする/明るくする
枠線や影(box-shadow)を強調する
opacity を少し下げて「押せます感」を出す
例えば影を付ける場合はこんな感じです。
.root {
/* 省略 */
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.12);
}
.root:hover {
background-color: #1d4ed8;
box-shadow: 0 4px 6px rgba(15, 23, 42, 0.2);
}
これだけで「プロダクト感」がぐっと出ます。
まとめ:Next.js × CSS Modulesでつかんでほしいこと
この課題で身につけてほしいポイントを整理します。
CSS Modules は「コンポーネント専用の CSS」を書ける仕組みで、クラス名の衝突を気にしなくてよくなる。import styles from "./◯◯.module.css"; として読み込み、className={styles.クラス名} でスタイルを当てる。:hover などの疑似クラスも普通の CSS と同じように書けて、ホバー時のインタラクションも簡単に付けられる。
ここが分かっていれば、
カードコンポーネントの枠線や影
リストアイテムのホバー時ハイライト
ヘッダーのナビゲーションリンクのホバー時アンダーライン
など、「ちょっとした UI の気持ちよさ」をコードで表現できるようになります。
もし余力があれば、
講座カードコンポーネント(タイトル+説明+ボタン)を作るCard.module.css を用意して、ホバー時に影が強くなるスタイルを付ける
といった“小さなコンポーネント+CSS Modules”も試してみてください。
