この章では、Next.jsアプリケーションにスタイルを適用する方法と、再利用可能なUI部品であるコンポーネントの設計について学びます。スタイリングに関しては、CSS ModulesとGlobal CSSの使い方を解説し、コンポーネントに関しては、分割の仕方、propsの使い方、そしてスタイル設定のベストプラクティスを紹介します。
1. CSS Modules
CSS Modulesは、CSSをスコープを限定して適用するための仕組みです。クラス名がコンポーネントごとに一意になるように自動的に変換されるため、スタイルの衝突を気にせずにCSSを記述できます。
スコープを限定したスタイリング
CSS Modulesを使用すると、CSSのクラス名が他のコンポーネントのクラス名と重複する心配がなくなります。これは、大規模なアプリケーションや、複数の開発者が関わるプロジェクトで特に有効です。
CSS Modulesの設定方法
Next.jsでは、CSS Modulesをデフォルトでサポートしています。.module.css
という拡張子のファイルを作成するだけで、CSS Modulesとして認識されます。
例えば、components
ディレクトリを作成し、その中にButton.module.css
というファイルを作成してみましょう。
my-next-app/
└── components/
└── Button.module.css
Button.module.css
に以下のスタイルを記述します。
css
/* components/Button.module.css */
.button {
background-color: blue;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.button:hover {
background-color: darkblue;
}
クラス名の適用方法
CSS Modulesで定義したスタイルをコンポーネントに適用するには、まずCSSファイルをインポートします。その際、styles
などの任意の変数名でインポートします。
components
ディレクトリにButton.tsx
を作成し、以下のコードを記述します。
tsx
// components/Button.tsx
import styles from './Button.module.css';
interface ButtonProps {
children: React.ReactNode;
onClick: () => void;
}
const Button: React.FC<ButtonProps> = ({ children, onClick }) => {
return (
<button className={styles.button} onClick={onClick}>
{children}
</button>
);
};
export default Button;
ポイントは、className
属性にstyles.button
を指定しているところです。styles
はButton.module.css
をインポートした際の変数名で、.button
はButton.module.css
で定義したクラス名です。
これで、Button
コンポーネントにCSS Modulesで定義したスタイルが適用されます。
実際に使う際は、pages/index.tsx
などから次のように利用します。
tsx
import Button from '../components/Button';
// ...
<Button onClick={() => alert('Button clicked!')}>Click me</Button>
2. Global CSS
Global CSSは、アプリケーション全体に適用されるスタイルです。Next.jsでは、pages/_app.tsx
ファイルでGlobal CSSをインポートすることで、アプリケーション全体にスタイルを適用できます。
アプリケーション全体に適用するスタイル
Global CSSは、Normalize.cssやリセットCSS、共通のフォント設定、ベースとなるスタイルなど、アプリケーション全体で共有するスタイルを定義するのに適しています。
pages/_app.tsx
の役割
pages/_app.tsx
は、Next.jsの特別なファイルで、すべてのページに共通のレイアウトやコンポーネントを定義するために使用されます。このファイルでGlobal CSSをインポートすることで、アプリケーション全体にスタイルを適用できます。
Global CSSの適用方法
まず、styles
ディレクトリにglobals.css
というファイルを作成します。
my-next-app/
└── styles/
└── globals.css
globals.css
に、アプリケーション全体に適用したいスタイルを記述します。
css
/* styles/globals.css */
html,
body {
padding: 0;
margin: 0;
font-family: sans-serif;
}
a {
color: inherit;
text-decoration: none;
}
* {
box-sizing: border-box;
}
次に、pages/_app.tsx
を以下のように変更します。
tsx
// pages/_app.tsx
import '../styles/globals.css';
import type { AppProps } from 'next/app';
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}
export default MyApp;
_app.tsx
でglobals.css
をインポートすることで、アプリケーション全体にスタイルが適用されます。
3. コンポーネントの作成と再利用
コンポーネントは、UIを構築するための基本的な部品です。適切に設計されたコンポーネントは、再利用可能で、保守性の高いアプリケーションを構築する上で非常に重要です。
コンポーネントの分割
コンポーネントを適切に分割することで、コードの見通しが良くなり、再利用性が向上します。一般的には、以下のような基準でコンポーネントを分割します。
- 単一責任の原則: 1つのコンポーネントは1つの役割を持つようにする。
- 再利用性: 複数の場所で使用されるUI部品は、独立したコンポーネントにする。
- 関心の分離: UIの見た目(スタイル)とロジックを分離する。
例えば、ヘッダー、フッター、サイドバー、メインコンテンツなど、UIの大きな塊ごとにコンポーネントを分割すると良いでしょう。
propsを使用したデータの受け渡し
コンポーネントは、propsと呼ばれるデータを受け取って、それに基づいてUIをレンダリングします。propsは、親コンポーネントから子コンポーネントにデータを渡すための仕組みです。
先ほどのButton
コンポーネントの例を見てみましょう。
tsx
// components/Button.tsx
interface ButtonProps {
children: React.ReactNode;
onClick: () => void;
}
const Button: React.FC<ButtonProps> = ({ children, onClick }) => {
return (
<button className={styles.button} onClick={onClick}>
{children}
</button>
);
};
export default Button;
ButtonProps
インターフェースで、Button
コンポーネントが受け取るpropsの型を定義しています。children
はボタンのラベルとして表示するコンテンツ、onClick
はボタンがクリックされたときに実行する関数です。
コンポーネントのスタイル設定
コンポーネントにスタイルを適用するには、いくつかの方法があります。
- CSS Modules: コンポーネントごとに
.module.css
ファイルを作成し、スタイルを定義する。 - Global CSS: アプリケーション全体に適用するスタイルを
globals.css
に定義する。 - Inline Styles: JSXの
style
属性にスタイルを直接記述する。ただし、この方法はあまり推奨されません。 - Styled Components: CSS-in-JSライブラリの一つで、コンポーネントとスタイルを一緒に定義できます。
どの方法を選ぶかは、プロジェクトの規模や開発チームの好みによりますが、一般的にはCSS Modulesが推奨されます。