Reactのスタイリング手法まとめ in 2023

# はじめに

こんにちは！
私はツクリンクでWebアプリケーションエンジニアとして働いているいわまさです。

ツクリンクでは現在、[フロントのリアーキテクチャ](https://note.com/iwamasamasa/n/n61d9a7438481)を検討しています。

そこで、今回は筆頭候補のReactでのスタイリング手法についてまとめました。

# 候補一覧

Googleで調べたり、ChatGPTに聞いてみたりしていくつか候補を出してみました。

1. CSS Modules
1. Sass/SCSS
1. CSS-in-JS
1. Inline Styles
1. CSS Frameworks

# CSS Modules

CSS Modulesは、CSSのモジュール化とカプセル化を実現するための技術です。
CSS Modulesを使用するとスタイルシートがコンポーネント単位でカプセル化され、スタイルの競合や名前空間の問題を回避できます。

### [主な特徴と利点]

1. **ローカルスコープ**：各コンポーネントに属するスタイルがローカルスコープ内で適用されるため、同じクラス名を異なるコンポーネントで使用してもスタイルが競合しない

1. **名前衝突の回避**：通常のCSSではクラス名がグローバルスコープで定義されるため、名前の衝突が起きる可能性があるが、CSS Modulesは自動的に一意のクラス名を生成し名前衝突を回避できる

1. **スタイルの再利用**：CSS Modules内でスタイルを定義し、異なるコンポーネントで再利用できる。これにより、コードの重複を減らし、保守性を向上させることが可能

1. **クリーンなコード**：スタイルとコンポーネントが近接して定義されるため、コードが読みやすくなり、スタイルの目的や意図を理解しやすくなる

### [実装例]

```css:CSS Modules
.button {
  background-color: blue;
  color: white;
}
```

```react: React Component
import React from 'react';
import styles from './styles.module.css';

const MyButton = () => {
  return (
    <button className={styles.button}>
      Click Me
    </button>
  );
}

export default MyButton;
```

## Sass/SCSS

Sass（Syntactically Awesome Style Sheets）またはSCSS（Sassy CSS）を使用してスタイリングを行う方法は通常のCSSを拡張することができ、効率的なスタイル記述が可能になります。

### [主な特徴と利点]

1. **変数の使用**: 変数を定義してスタイルプロパティやカラーコードを格納でき、同じ値を複数の場所で使用する場合に便利&スタイルの一貫性を保ちやすくなる

2. **ネスト**: スタイルのネストをサポートしているため、親要素内にネストされた子要素のスタイリングを簡潔に記述でき、CSSの階層構造を保つのが容易になり読性が向上

3. **ミックスイン**: 共通のスタイルセットを抽象化して必要な場所で再利用でき、コードの重複を減らして保守性が向上

4. **演算**: 算術演算をサポートしており、スタイルプロパティの計算が可能

5. **インポート**: スタイルシートファイルを分割し、部分ファイルをインポートすることができ、プロジェクト内のスタイルのモジュラリティと再利用性を高めることが可能

6. **規模に対応**: 大規模なプロジェクトでSass/SCSSを使用することは、スタイルの整理と管理を容易にし、チームで協力して作業するのに役立つ

7. **リアルタイムコンパイル**: 開発時にSass/SCSSファイルをリアルタイムでコンパイルできるツールが豊富に提供されており、変更を即座に確認でき、開発プロセスがスピーディになる

8. **拡張性**: CSSに対する拡張として提供されるため、既存のCSSコードと統合しやすく、徐々に導入することが可能

### [実装例]

```scss:Scss
.custom-button {
  background-color: #007bff;
  color: #fff;
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  cursor: pointer;

  &:hover {
    background-color: darken(#007bff, 10%);
  }
}
```

```react: React Component
import React from 'react';
import './Button.module.scss';

const Button = () => {
  return (
    <button className="custom-button">Click Me</button>
  );
};

export default Button;
```

# CSS-in-JS

CSS in JSは、JavaScriptのコード内でCSSスタイルを定義し、適用するためのアプローチです。
従来のCSSファイルを使う代わりにCSSスタイルをJavaScriptのオブジェクトとして定義し、
コンポーネントベースのアプリケーションやフレームワークでこれらのスタイルを適用します。

実現するためにはいくつか方法があるので、今回は代表的なものをピックアップします。

ChatGPTが候補上げたもの
- Styled-components
- Emotion
- JSS(JavaScript Style Sheets)
- Glamorous
- Aphrodite
- Linaria

※npm trandsより

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199056/1f316d33-c59f-67c6-4de7-469639226342.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199056/ad607ec7-2f6f-5040-e0a4-06def1db8ce1.png)

上記の結果から、上位3つがメンテもされていて利用者も多そうなので今回取り上げます。
後から登場したEmotionの追い上げ具合が凄いですね。

ちなみに2021年時点での利用率をまとめたサイトがあるのですが、この時点ではStyled-componentsが1位でEmotionは4位でした。

https://2021.stateofcss.com/ja-JP/technologies/css-in-js/

※上記のサイトより転載
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199056/8379390c-f998-bd80-f35e-2d7793b65d76.png)

ここからピックアップしたものの紹介をします。

## Styled-components

Styled-componentsはJavaScriptのテンプレート文字列を使用してCSSスタイルを定義し、
Reactコンポーネントに適用するための人気のあるCSS in JSライブラリです。

https://styled-components.com/

### [主な特徴と利点]

1. **コンポーネント指向のスタイリング**: コンポーネントとスタイルを結びつけるため、コンポーネントベースのアプリケーションでスタイリングを効果的にカプセル化が可能

2. **JavaScriptを使用したスタイル定義**: CSSをJavaScript内に直接埋め込むことができ、変数や条件文を使用してスタイルを動的に変更が可能

3. **CSSの共有と再利用**: スタイルをコンポーネントとして定義することができ、再利用可能なスタイルコンポーネントとしてラップすることが可能

4. **スタイルの優先順位の管理**: スタイルの優先順位を自動的に管理し、CSSの競合や名前の衝突を防ぐことが可能

5. **パフォーマンスの最適化**: サーバーサイドレンダリングやコード分割といったパフォーマンス最適化の機能を提供。不要なスタイルが削除されるため、ページの読み込み速度が向上する

6. **自動プレフィックス**: 自動的にベンダープレフィックスを生成し、クロスブラウザの互換性を確保する

7. **デバッグ支援**: デバッグツールと連携する機能があり、開発者がスタイルの問題を特定しやすくなる

### [実装例]

```react:Styled-components
import React from 'react';
import styled from 'styled-components';

const StyledButton = styled.button`
  background-color: #007bff;
  color: #fff;
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  cursor: pointer;

  &:hover {
    background-color: #0056b3;
  }
`;

const Button = ({ label, onClick }) => {
  return (
    <StyledButton onClick={onClick}>{label}</StyledButton>
  );
};

export default Button;
```

## Emotion

EmotionはReactアプリケーションのスタイリングをサポートするパフォーマンス重視のCSS in JSライブラリです。

https://emotion.sh/docs/introduction

### [主な特徴と利点]

1. **高いパフォーマンス**: CSSスタイルをコンパイルする際に最適化された出力を生成し、パフォーマンスを重視している。生成されたスタイルはCSSの最小化や重複の排除などの最適化が施されているため、ページの読み込み速度を向上させる

2. **ダイナミックなスタイル**: JSを使用してスタイルを定義するため、動的なスタイルを簡単に扱うことが可能で条件文や変数を使用してスタイルを制御することができる

3. **コンポーネント指向のスタイリング**: コンポーネントとスタイルを結びつけ、コンポーネントベースのスタイリングを推進している(スタイリングのカプセル化)

4. **スタイルの再利用**: スタイルを再利用可能な関数やコンポーネントとして抽象化が可能なため、スタイルの共有が簡単になり、コードの重複を減らすことができる

5. **CSSプリフィクスの自動生成**: ベンダープレフィックスを自動的に生成し、クロスブラウザの互換性を確保

6. **Server-Side Rendering (SSR) のサポート**: サーバーサイドレンダリングをサポートし、初期表示のパフォーマンスを向上させる

7. **モバイルアプリケーションとの統合**: React Nativeなどのモバイルアプリケーション開発とも統合できるため、一貫したスタイリングのアプローチを提供

8. **デバッグのサポート**: デバッグツールと連携し、スタイルの問題を特定しやすくするためのデバッグ情報を提供

特徴だけ見るとかなりStyled-componentsと似ている印象。

### [実装例]

```react:Emotion
import { css } from '@emotion/react';

const buttonStyle = css`
  background-color: #007bff;
  color: #fff;
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  cursor: pointer;

  &:hover {
    background-color: #0056b3;
  }
`;

const Button = () => {
  return (
    <button css={buttonStyle}>Click me</button>
  );
};

export default Button;
```

## JSS(JavaScript Style Sheets)

JSS（JavaScript Style Sheets）は、CSS in JSライブラリの1つで、JavaScript内でスタイルを定義し、適用するためのアプローチです。

https://cssinjs.org/?v=v10.10.0

### [主な特徴と利点]


1. **動的スタイリング**: JS内でスタイルを定義するため、動的なスタイリングが容易。変数や条件文を使用して、コンポーネントの状態に応じてスタイルを変更できる

2. **コンポーネントスコープ**: スタイルをコンポーネントと結びつけ、スタイルが他のコンポーネントに影響を与えないようにしする(スタイルのカプセル化)

3. **スタイルの再利用**: スタイルを再利用可能なクラスやオブジェクトとして定義できるため、スタイルの共有とメンテナンスが容易になる

4. **サーバーサイドレンダリング（SSR）のサポート**: サーバーサイドレンダリングをサポートし、初期表示のパフォーマンスを向上できる。クライアントとサーバーで一貫したスタイルが提供される

5. **ベンダープレフィクスの自動生成**: ベンダープレフィクスを自動的に生成し、クロスブラウザの互換性を確保

6. **パフォーマンスの最適化**: スタイルを最適化し、不要なスタイルを排除するための機能を提供

7. **アニメーションのサポート**: アニメーションスタイルを定義しやすく、JSを使用してアニメーションを制御するのに役立つ

8. **デバッグのサポート**: デバッグ情報を提供し、スタイルの問題を特定しやすくするためのツールと統合することができる

### [実装例]

```react:JSS
import React from 'react';
import jss from 'jss';
import preset from 'jss-preset-default';

jss.setup(preset());

const styles = {
  button: {
    backgroundColor: '#007bff',
    color: '#fff',
    padding: '10px 20px',
    border: 'none',
    borderRadius: '5px',
    cursor: 'pointer',

    '&:hover': {
      backgroundColor: '#0056b3',
    },
  },
};

const { classes } = jss.createStyleSheet(styles).attach();

const Button = () => {
  return (
    <button className={classes.button}>Click me</button>
  );
};

export default Button;
```

# Inline Styles

Reactのインラインスタイル（Inline Styles）は、JavaScriptオブジェクトとしてスタイル情報を指定し、Reactコンポーネントに適用する方法です。
※要は直接styleを記載する

### [主な特徴と利点]

他の手法と違って再利用が難しい、パフォーマンスの問題があるなどあまり大きな利点が無いので割愛します。
(いやいや、インラインが良いよとかあればコメントください)

### [実装例]

```react:Inline Styles
import React from 'react';

const buttonStyle = {
  backgroundColor: '#007bff',
  color: '#fff',
  padding: '10px 20px',
  border: 'none',
  borderRadius: '5px',
  cursor: 'pointer',
};

const Button = () => {
  return (
    <button style={buttonStyle}>Click me</button>
  );
};

export default Button;
```

# CSS Frameworks

CSSフレームワーク（CSS Framework）は、スタイリングされたコンポーネントやユーティリティクラス、グリッドシステム、フォーム要素などのスタイリングのための一般的なパターンを提供します。

他のスタイルング手法と大きく異なる点として、コンポーネントなどで必要な機能が提供されているのでそれに則って作成する点です。
(他の手法だと自分で作成することになる)


### [主な特徴と利点]

1. **効率的な開発**: スタイリングの一般的なパターンを提供するため、新しいプロジェクトを開始する際に時間と労力を節約ができる

2. **デザインの一貫性**: 一貫したデザインスタイルを提供し、異なる部分で同じデザインの要素を再利用できるため、デザインの一貫性が向上する

3. **レスポンシブデザインのサポート**: 多くのCSSフレームワークはレスポンシブデザインのためのグリッドシステムを提供し、異なる画面サイズやデバイスに適したスタイルの適用が容易になる

4. **コミュニティとドキュメンテーション**: 一般的なCSSフレームワークは広く採用されており、多くのコミュニティサポートとドキュメンテーションが利用可能です。質問や課題に対処するのに役立つ

5. **セキュリティと品質**: セキュリティに関する最善の実践を組み込むことが一般的であり、品質保証されている

6. **カスタマイズ可能性**: 多くのCSSフレームワークはカスタマイズが可能で、プロジェクトのニーズに合わせて調整できる。必要に応じてフレームワークを拡張し、スタイルをオーバーライドすることが可能

7. **高速なプロトタイピング**: アプリケーションやウェブサイトのプロトタイプを迅速に作成できる

8. **クロスブラウザの互換性**: クロスブラウザの互換性を確保するためのスタイルの正確な適用をサポート

特に7の **アプリケーションやウェブサイトのプロトタイプを迅速に作成できる** はCSSフレームワークを使用する上での大きな利点ですね。

### [主なCSSフレームワーク]

- MUI(Material-UI)
- Bootstrap
- Ant Design

### [実装例: MUIの場合]

個人的にMUIが好きなのでこちらを例とします。

```react:MUI
import React from 'react';
import { TextField, Button, Container, Typography } from '@mui/material';

const SampleForm = () => {
  const [name, setName] = React.useState('');
  const [email, setEmail] = React.useState('');

  const handleSubmit = (event) => {
    event.preventDefault();
    // ここでフォームの値を使った何かしらの処理を実行
  };

  return (
    <Container maxWidth="sm">
      <Typography variant="h4" align="center" gutterBottom>
        Sample Form using MUI
      </Typography>
      <form onSubmit={handleSubmit}>
        <div style={{ marginBottom: '1rem' }}>
          <TextField
            label="Name"
            variant="outlined"
            fullWidth
            value={name}
            onChange={(e) => setName(e.target.value)}
          />
        </div>
        <div style={{ marginBottom: '1rem' }}>
          <TextField
            label="Email"
            variant="outlined"
            fullWidth
            value={email}
            onChange={(e) => setEmail(e.target.value)}
          />
        </div>
        <Button variant="contained" color="primary" type="submit">
          Submit
        </Button>
      </form>
    </Container>
  );
};

export default SampleForm;

```

# Tailwind CSS

Tailwind CSSは、従来のCSSフレームワークとは異なるアプローチを取るCSSユーティリティフレームワークです。

### [主な特徴と利点]

1. **ユーティリティファースト**: 単一のクラスを使用してスタイルを適用し、スタイリングを直感的かつ迅速に行うことが可能
例えば、`class="bg-blue-500"`や`class="text-xl"`のように、色やテキストサイズを直接指定することが可能

2. **カスタマイズ可能**: 柔軟でカスタマイズ可能。`tailwind.config.js`ファイルを使用して、色、フォントサイズ、余白、影、グリッドなどの様々なスタイルをカスタマイズできる。
これにより、**プロジェクトごとに独自のデザインシステムを構築することができる**

3. **低い学習コスト**: 他のCSSフレームワークと比較して、Tailwindの学習コストは比較的低い。通常のCSSとは異なるアプローチを取るため、一度基本的なクラスと構文を理解すれば、柔軟なスタイリングが可能

4. **効率的な開発**: プロジェクト全体で統一されたデザインを実現しやすく、迅速な開発が可能
スタイリングの一貫性が容易に保たれ、HTML内で直感的に読み取りやすいコードを記述できる

5. **パフォーマンス**: ビルド時に使用されるため、本番環境ではクラスの冗長な部分が削除され、最適化されたCSSが生成される

今回調査してみて、npm trendsで調べたところCSSフレームワークなのに上位に君臨しているのであえて最後に持ってきました。

※紫がTailwind CSS(npm trendsより)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199056/2a0d92a0-bb59-7cc7-12bd-a3799c5bd3a8.png)

### [実装例]

```css:index.css
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
```

```react:Tailwind CSS
import React from 'react';

const App = () => {
  return (
    <div className="bg-gray-100 h-screen flex items-center justify-center">
      <div className="bg-white p-8 rounded shadow-lg">
        <h1 className="text-2xl font-bold mb-4">Welcome to My App</h1>
        <p className="text-gray-700">This is a Tailwind CSS example in a React app.</p>
        <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mt-4">
          Click me!
        </button>
      </div>
    </div>
  );
};

export default App;
```

# まとめ

今回はReactのスタイリング手法についてまとめました。
トレンドもあると思いますが、どの手法が良いと言うよりはその組織や体制に適しているかが一番のポイントだと個人的には思っているのでそこを意識してこれから選定します。

こちらの記事の特徴やサンプルコードはChatGPTを使用しているため、間違いなどありましたらコメントでご指摘ください🙇‍♂️