Skip to content

スタイリングとコンポーネント

公開日:December 10, 2024更新日:December 10, 2024
NextjsTypeScriptCoding📄

この章では、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を指定しているところです。stylesButton.module.cssをインポートした際の変数名で、.buttonButton.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.tsxglobals.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が推奨されます。