React Bootstrapで始めるUI開発|デザイン初心者でも美しいサイトを

React Bootstrapを使ってプロ級のUIを簡単に作成する方法を解説。デザイン初心者でも美しいレスポンシブサイトが作れるコンポーネントと実装例を紹介

Learning Next 運営
64 分で読めます

Reactでサイトを作りたいけど、デザインが苦手だと悩んでいませんか?

「プロのような見た目のサイトを作りたい」って思いませんか? 「デザインセンスがないから、きれいなUIが作れない」と諦めていませんか?

そんなあなたに朗報です。 React Bootstrapを使えば、デザイン知識がなくても簡単にプロ級のサイトが作れるんです。

この記事では、React Bootstrapを使って美しいUIを作る方法を詳しく解説します。 基本的な使い方から実践的なコンポーネントまで、すぐに使える内容をお伝えします。

React Bootstrapとは

React Bootstrapは、人気のCSSフレームワークBootstrapをReact向けに最適化したライブラリです。

簡単に言うと、美しいコンポーネントがすぐに使えるツールキットのことです。 ボタンやカード、フォームなどがすでに作られているので、それを組み合わせるだけでプロっぽいサイトができあがります。

従来のBootstrapとの違い

まず、従来のBootstrapとの違いを理解しましょう。

// ❌ 従来のBootstrap(jQueryベース)
<div class="modal fade" id="exampleModal">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">モーダルタイトル</h5>
        <button type="button" class="close" data-dismiss="modal">
          <span>&times;</span>
        </button>
      </div>
      <div class="modal-body">
        モーダルの内容
      </div>
    </div>
  </div>
</div>

// JavaScript(jQuery)
$('#exampleModal').modal('show');

従来のBootstrapでは、HTMLとjQueryを組み合わせる必要がありました。 ちょっと複雑ですよね。

// ✅ React Bootstrap(React向け)
import { Modal, Button } from 'react-bootstrap';

function ExampleModal() {
  const [show, setShow] = useState(false);

  return (
    <>
      <Button variant="primary" onClick={() => setShow(true)}>
        モーダルを開く
      </Button>

      <Modal show={show} onHide={() => setShow(false)}>
        <Modal.Header closeButton>
          <Modal.Title>モーダルタイトル</Modal.Title>
        </Modal.Header>
        <Modal.Body>
          モーダルの内容
        </Modal.Body>
      </Modal>
    </>
  );
}

React Bootstrapなら、Reactらしい書き方で簡単にモーダルが作れます。 状態管理もuseStateで統一できて、とても分かりやすいですね。

React Bootstrapの主な特徴

React Bootstrapが選ばれる理由を見てみましょう。

Reactらしい記述

状態管理やイベント処理がReactの書き方で統一されます。

// 状態管理がReactっぽい
function NavigationExample() {
  const [activeTab, setActiveTab] = useState('home');

  return (
    <Tabs activeKey={activeTab} onSelect={setActiveTab}>
      <Tab eventKey="home" title="ホーム">
        <p>ホームページの内容</p>
      </Tab>
      <Tab eventKey="profile" title="プロフィール">
        <p>プロフィールページの内容</p>
      </Tab>
    </Tabs>
  );
}

activeTabという状態で、どのタブが選択されているかを管理しています。 ReactのuseStateを使っているので、とても自然な書き方ですね。

豊富なコンポーネント

50以上のコンポーネントが提供されています。

// 様々なコンポーネントが利用可能
import { 
  Button, Card, Form, Table, Alert, 
  Modal, Dropdown, Spinner, Badge,
  Navbar, Nav, Container, Row, Col
} from 'react-bootstrap';

必要なコンポーネントを個別にインポートできるので、バンドルサイズも最適化されます。

TypeScriptサポート

型定義が充実しており、開発効率が向上します。

// TypeScriptで型安全な開発
interface User {
  id: number;
  name: string;
  email: string;
}

function UserCard({ user }: { user: User }) {
  return (
    <Card style={{ width: '18rem' }}>
      <Card.Body>
        <Card.Title>{user.name}</Card.Title>
        <Card.Text>{user.email}</Card.Text>
      </Card.Body>
    </Card>
  );
}

TypeScriptを使っている場合、型エラーを事前に防げるので安心ですね。

他のUIライブラリとの比較

React Bootstrapと他のライブラリを比較してみましょう。

// React Bootstrap(学習コストが低い)
<Button variant="primary" size="lg">
  ボタン
</Button>

// Material-UI(Googleのデザイン言語)
<Button variant="contained" color="primary" size="large">
  ボタン
</Button>

// Ant Design(エンタープライズ向け)
<Button type="primary" size="large">
  ボタン
</Button>

React Bootstrapは、最も学習コストが低いのが特徴です。 既存のBootstrapの知識を活用できるので、初心者にもおすすめです。

インストールと基本設定

React Bootstrapを実際に使ってみましょう。

パッケージのインストール

必要なパッケージをインストールします。

# React Bootstrapとスタイル
npm install react-bootstrap bootstrap

# または yarn
yarn add react-bootstrap bootstrap

# アイコンも使いたい場合
npm install react-bootstrap-icons

react-bootstrapがメインのライブラリで、bootstrapがCSSスタイルです。 アイコンは必要に応じて追加してください。

基本的な設定

プロジェクトの設定を行います。

// src/index.js または src/main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

// Bootstrap CSSをインポート
import 'bootstrap/dist/css/bootstrap.min.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

bootstrap.min.cssをインポートすることで、Bootstrapのスタイルが適用されます。 これを忘れると、見た目が正しく表示されないので注意してください。

基本的なレイアウト

最初のコンポーネントを作成してみましょう。

// src/App.jsx
import { Container, Row, Col, Button } from 'react-bootstrap';

function App() {
  return (
    <Container>
      <Row className="justify-content-center">
        <Col md={8}>
          <h1 className="text-center my-4">
            React Bootstrap入門
          </h1>
          <p className="text-center">
            美しいUIを簡単に作成できます
          </p>
          <div className="text-center">
            <Button variant="primary" size="lg">
              今すぐ始める
            </Button>
          </div>
        </Col>
      </Row>
    </Container>
  );
}

export default App;

Containerでページ全体を包んで、RowColでレイアウトを作ります。 md={8}は、中サイズの画面で8カラム分の幅を指定しています。

グリッドシステム

Bootstrapの強力なグリッドシステムを活用します。

function GridExample() {
  return (
    <Container>
      {/* 基本的なグリッド */}
      <Row>
        <Col md={6}>
          <div className="bg-light p-3 border">
            左側のコンテンツ
          </div>
        </Col>
        <Col md={6}>
          <div className="bg-light p-3 border">
            右側のコンテンツ
          </div>
        </Col>
      </Row>

      {/* レスポンシブグリッド */}
      <Row className="mt-4">
        <Col xs={12} md={4}>
          <div className="bg-primary text-white p-3 mb-3">
            モバイル: 全幅<br />
            PC: 1/3幅
          </div>
        </Col>
        <Col xs={12} md={4}>
          <div className="bg-success text-white p-3 mb-3">
            モバイル: 全幅<br />
            PC: 1/3幅
          </div>
        </Col>
        <Col xs={12} md={4}>
          <div className="bg-danger text-white p-3 mb-3">
            モバイル: 全幅<br />
            PC: 1/3幅
          </div>
        </Col>
      </Row>

      {/* 複雑なレイアウト */}
      <Row className="mt-4">
        <Col md={8}>
          <div className="bg-info text-white p-3">
            メインコンテンツエリア
          </div>
        </Col>
        <Col md={4}>
          <div className="bg-warning p-3">
            サイドバーエリア
          </div>
        </Col>
      </Row>
    </Container>
  );
}

グリッドシステムは、画面サイズに応じて自動的にレイアウトが変わります。 xsはスマホ、mdはタブレット・PCでの表示を指定しています。

基本的なコンポーネント

よく使われるコンポーネントの実装例を紹介します。

ボタンコンポーネント

様々なスタイルのボタンを作成できます。

import { Button, ButtonGroup, DropdownButton, Dropdown } from 'react-bootstrap';

function ButtonExamples() {
  return (
    <Container>
      <h2>ボタンの種類</h2>
      
      {/* 基本的なボタン */}
      <div className="mb-3">
        <Button variant="primary" className="me-2">Primary</Button>
        <Button variant="secondary" className="me-2">Secondary</Button>
        <Button variant="success" className="me-2">Success</Button>
        <Button variant="danger" className="me-2">Danger</Button>
        <Button variant="warning" className="me-2">Warning</Button>
        <Button variant="info" className="me-2">Info</Button>
        <Button variant="light" className="me-2">Light</Button>
        <Button variant="dark" className="me-2">Dark</Button>
      </div>

      {/* アウトラインボタン */}
      <div className="mb-3">
        <Button variant="outline-primary" className="me-2">
          Outline Primary
        </Button>
        <Button variant="outline-secondary" className="me-2">
          Outline Secondary
        </Button>
        <Button variant="outline-success" className="me-2">
          Outline Success
        </Button>
      </div>

      {/* サイズ違いのボタン */}
      <div className="mb-3">
        <Button variant="primary" size="lg" className="me-2">
          Large Button
        </Button>
        <Button variant="secondary" className="me-2">
          Default Button
        </Button>
        <Button variant="success" size="sm" className="me-2">
          Small Button
        </Button>
      </div>

      {/* ボタングループ */}
      <ButtonGroup className="mb-3">
        <Button variant="outline-primary">Left</Button>
        <Button variant="outline-primary">Middle</Button>
        <Button variant="outline-primary">Right</Button>
      </ButtonGroup>

      {/* ドロップダウンボタン */}
      <DropdownButton id="dropdown-basic-button" title="ドロップダウン">
        <Dropdown.Item href="#/action-1">Action</Dropdown.Item>
        <Dropdown.Item href="#/action-2">Another action</Dropdown.Item>
        <Dropdown.Item href="#/action-3">Something else</Dropdown.Item>
      </DropdownButton>
    </Container>
  );
}

variantプロパティで、ボタンの色を指定します。 sizeプロパティで、ボタンのサイズを変更できます。

ButtonGroupを使うと、ボタンをグループ化できます。 DropdownButtonなら、クリックでメニューが表示されます。

カードコンポーネント

情報を整理して表示するカードを作成します。

import { Card, Button, Row, Col } from 'react-bootstrap';

function CardExamples() {
  const products = [
    {
      id: 1,
      name: 'プロダクト A',
      price: '¥12,000',
      image: 'https://via.placeholder.com/300x200',
      description: 'これは素晴らしいプロダクトです。'
    },
    {
      id: 2,
      name: 'プロダクト B',
      price: '¥8,500',
      image: 'https://via.placeholder.com/300x200',
      description: 'こちらも魅力的なプロダクトです。'
    },
    {
      id: 3,
      name: 'プロダクト C',
      price: '¥15,800',
      image: 'https://via.placeholder.com/300x200',
      description: '高品質で人気のプロダクトです。'
    }
  ];

  return (
    <Container>
      <h2 className="mb-4">商品一覧</h2>
      
      <Row>
        {products.map(product => (
          <Col md={4} key={product.id} className="mb-4">
            <Card>
              <Card.Img variant="top" src={product.image} />
              <Card.Body>
                <Card.Title>{product.name}</Card.Title>
                <Card.Text>{product.description}</Card.Text>
                <div className="d-flex justify-content-between align-items-center">
                  <span className="h5 text-primary">{product.price}</span>
                  <Button variant="primary">購入する</Button>
                </div>
              </Card.Body>
            </Card>
          </Col>
        ))}
      </Row>

      {/* 特別なカード */}
      <Row className="mt-4">
        <Col md={6}>
          <Card className="bg-primary text-white">
            <Card.Body>
              <Card.Title>特別オファー</Card.Title>
              <Card.Text>
                今だけ限定の特別価格でご提供中!
              </Card.Text>
              <Button variant="light">詳細を見る</Button>
            </Card.Body>
          </Card>
        </Col>
        
        <Col md={6}>
          <Card border="success">
            <Card.Header className="bg-success text-white">
              <strong>おすすめ商品</strong>
            </Card.Header>
            <Card.Body>
              <Card.Title>人気No.1商品</Card.Title>
              <Card.Text>
                多くのお客様に選ばれている人気商品です。
              </Card.Text>
              <Button variant="success">今すぐ購入</Button>
            </Card.Body>
          </Card>
        </Col>
      </Row>
    </Container>
  );
}

Card.Imgで画像を表示し、Card.Bodyで本文を囲みます。 Card.TitleCard.Textで、タイトルと説明文を表示します。

特別なカードでは、bg-primaryでプライマリカラーの背景にしています。 border="success"で、緑色の枠線を付けることもできます。

フォームコンポーネント

美しいフォームを簡単に作成できます。

import { Form, Button, Row, Col, Alert } from 'react-bootstrap';
import { useState } from 'react';

function FormExamples() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    message: '',
    newsletter: false,
    category: ''
  });
  const [showAlert, setShowAlert] = useState(false);

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('送信データ:', formData);
    setShowAlert(true);
    setTimeout(() => setShowAlert(false), 3000);
  };

  const handleChange = (e) => {
    const { name, value, type, checked } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: type === 'checkbox' ? checked : value
    }));
  };

  return (
    <Container>
      <h2 className="mb-4">お問い合わせフォーム</h2>
      
      {showAlert && (
        <Alert variant="success" dismissible onClose={() => setShowAlert(false)}>
          メッセージを送信しました!
        </Alert>
      )}

      <Form onSubmit={handleSubmit}>
        <Row>
          <Col md={6}>
            <Form.Group className="mb-3">
              <Form.Label>お名前 *</Form.Label>
              <Form.Control
                type="text"
                name="name"
                value={formData.name}
                onChange={handleChange}
                placeholder="田中太郎"
                required
              />
            </Form.Group>
          </Col>
          
          <Col md={6}>
            <Form.Group className="mb-3">
              <Form.Label>メールアドレス *</Form.Label>
              <Form.Control
                type="email"
                name="email"
                value={formData.email}
                onChange={handleChange}
                placeholder="example@mail.com"
                required
              />
            </Form.Group>
          </Col>
        </Row>

        <Form.Group className="mb-3">
          <Form.Label>カテゴリー</Form.Label>
          <Form.Select
            name="category"
            value={formData.category}
            onChange={handleChange}
          >
            <option value="">選択してください</option>
            <option value="general">一般的な質問</option>
            <option value="support">サポート</option>
            <option value="sales">営業</option>
            <option value="other">その他</option>
          </Form.Select>
        </Form.Group>

        <Form.Group className="mb-3">
          <Form.Label>メッセージ *</Form.Label>
          <Form.Control
            as="textarea"
            rows={5}
            name="message"
            value={formData.message}
            onChange={handleChange}
            placeholder="お問い合わせ内容をご記入ください"
            required
          />
        </Form.Group>

        <Form.Group className="mb-3">
          <Form.Check
            type="checkbox"
            name="newsletter"
            checked={formData.newsletter}
            onChange={handleChange}
            label="ニュースレターを購読する"
          />
        </Form.Group>

        <div className="d-grid gap-2">
          <Button variant="primary" type="submit" size="lg">
            送信する
          </Button>
        </div>
      </Form>
    </Container>
  );
}

Form.Groupで各入力項目をグループ化します。 Form.Labelでラベル、Form.Controlで入力フィールドを作成します。

Form.Selectでセレクトボックス、Form.Checkでチェックボックスが作れます。 Alertコンポーネントで、送信完了のメッセージを表示しています。

ナビゲーションコンポーネント

プロフェッショナルなナビゲーションを作成しましょう。

基本的なナビバー

レスポンシブなナビゲーションバーを実装します。

import { Navbar, Nav, Container, NavDropdown } from 'react-bootstrap';

function NavigationExample() {
  return (
    <Navbar bg="dark" variant="dark" expand="lg" sticky="top">
      <Container>
        <Navbar.Brand href="#home">
          <img
            alt=""
            src="/logo.svg"
            width="30"
            height="30"
            className="d-inline-block align-top"
          />{' '}
          My Website
        </Navbar.Brand>
        
        <Navbar.Toggle aria-controls="basic-navbar-nav" />
        
        <Navbar.Collapse id="basic-navbar-nav">
          <Nav className="ms-auto">
            <Nav.Link href="#home">ホーム</Nav.Link>
            <Nav.Link href="#about">会社概要</Nav.Link>
            
            <NavDropdown title="サービス" id="basic-nav-dropdown">
              <NavDropdown.Item href="#service1">
                ウェブ開発
              </NavDropdown.Item>
              <NavDropdown.Item href="#service2">
                アプリ開発
              </NavDropdown.Item>
              <NavDropdown.Item href="#service3">
                コンサルティング
              </NavDropdown.Item>
              <NavDropdown.Divider />
              <NavDropdown.Item href="#service4">
                その他のサービス
              </NavDropdown.Item>
            </NavDropdown>
            
            <Nav.Link href="#contact">お問い合わせ</Nav.Link>
          </Nav>
        </Navbar.Collapse>
      </Container>
    </Navbar>
  );
}

Navbarでナビゲーションバーを作成します。 bg="dark"で背景色、variant="dark"で文字色を指定しています。

Navbar.Toggleは、スマホでハンバーガーメニューを表示するボタンです。 Navbar.Collapseの中に、実際のメニュー項目を配置します。

タブナビゲーション

コンテンツを切り替えるタブを実装します。

import { Tabs, Tab, Container } from 'react-bootstrap';
import { useState } from 'react';

function TabsExample() {
  const [activeTab, setActiveTab] = useState('overview');

  return (
    <Container>
      <h2 className="mb-4">プロダクト情報</h2>
      
      <Tabs
        activeKey={activeTab}
        onSelect={(k) => setActiveTab(k)}
        className="mb-3"
      >
        <Tab eventKey="overview" title="概要">
          <div className="p-4 bg-light">
            <h3>プロダクト概要</h3>
            <p>
              このプロダクトは革新的な技術を使用して開発されました。
              ユーザーフレンドリーなインターフェースと高いパフォーマンスを実現しています。
            </p>
            <ul>
              <li>高速な処理速度</li>
              <li>直感的な操作性</li>
              <li>豊富な機能</li>
            </ul>
          </div>
        </Tab>
        
        <Tab eventKey="features" title="機能">
          <div className="p-4 bg-light">
            <h3>主要機能</h3>
            <Row>
              <Col md={6}>
                <h4>基本機能</h4>
                <ul>
                  <li>データ管理</li>
                  <li>レポート生成</li>
                  <li>ユーザー管理</li>
                </ul>
              </Col>
              <Col md={6}>
                <h4>高度な機能</h4>
                <ul>
                  <li>API連携</li>
                  <li>自動化</li>
                  <li>分析機能</li>
                </ul>
              </Col>
            </Row>
          </div>
        </Tab>
        
        <Tab eventKey="pricing" title="料金">
          <div className="p-4 bg-light">
            <h3>料金プラン</h3>
            <Row>
              <Col md={4}>
                <Card>
                  <Card.Body className="text-center">
                    <Card.Title>ベーシック</Card.Title>
                    <Card.Text>
                      <span className="h2">¥1,000</span>/月
                    </Card.Text>
                    <Button variant="outline-primary">選択</Button>
                  </Card.Body>
                </Card>
              </Col>
              <Col md={4}>
                <Card>
                  <Card.Body className="text-center">
                    <Card.Title>プロ</Card.Title>
                    <Card.Text>
                      <span className="h2">¥2,500</span>/月
                    </Card.Text>
                    <Button variant="primary">選択</Button>
                  </Card.Body>
                </Card>
              </Col>
              <Col md={4}>
                <Card>
                  <Card.Body className="text-center">
                    <Card.Title>エンタープライズ</Card.Title>
                    <Card.Text>
                      <span className="h2">¥5,000</span>/月
                    </Card.Text>
                    <Button variant="outline-primary">選択</Button>
                  </Card.Body>
                </Card>
              </Col>
            </Row>
          </div>
        </Tab>
      </Tabs>
    </Container>
  );
}

Tabsでタブコンテナを作成し、Tabで各タブを定義します。 activeKeyで現在選択されているタブを管理しています。

onSelectで、タブがクリックされた時の処理を指定します。 各タブの中身は、通常のReactコンポーネントとして自由に作成できます。

ブレッドクラム

現在位置を表示するブレッドクラムを実装します。

import { Breadcrumb, Container } from 'react-bootstrap';

function BreadcrumbExample() {
  return (
    <Container>
      <Breadcrumb>
        <Breadcrumb.Item href="/">ホーム</Breadcrumb.Item>
        <Breadcrumb.Item href="/products">プロダクト</Breadcrumb.Item>
        <Breadcrumb.Item href="/products/category">カテゴリー</Breadcrumb.Item>
        <Breadcrumb.Item active>商品詳細</Breadcrumb.Item>
      </Breadcrumb>
      
      <h1>商品詳細ページ</h1>
      <p>ここに商品の詳細情報が表示されます。</p>
    </Container>
  );
}

Breadcrumb.Itemで、パンくずリストの各項目を作成します。 最後の項目にはactiveを付けて、現在のページであることを示します。

実践的なページレイアウト

実際のWebサイトで使えるページレイアウトを作成しましょう。

ランディングページ

魅力的なランディングページを作成します。

import { 
  Container, Row, Col, Button, Card, 
  Navbar, Nav, Jumbotron 
} from 'react-bootstrap';

function LandingPage() {
  return (
    <>
      {/* ナビゲーション */}
      <Navbar bg="white" variant="light" expand="lg" className="shadow-sm">
        <Container>
          <Navbar.Brand href="#home" className="fw-bold">
            My Service
          </Navbar.Brand>
          <Navbar.Toggle aria-controls="basic-navbar-nav" />
          <Navbar.Collapse id="basic-navbar-nav">
            <Nav className="ms-auto">
              <Nav.Link href="#features">機能</Nav.Link>
              <Nav.Link href="#pricing">料金</Nav.Link>
              <Nav.Link href="#contact">お問い合わせ</Nav.Link>
            </Nav>
          </Navbar.Collapse>
        </Container>
      </Navbar>

      {/* ヒーローセクション */}
      <div className="bg-primary text-white py-5">
        <Container>
          <Row className="align-items-center">
            <Col lg={6}>
              <h1 className="display-4 fw-bold">
                あなたのビジネスを<br />
                次のレベルへ
              </h1>
              <p className="lead">
                革新的なソリューションで、効率性と生産性を向上させます。
                今すぐ始めて、違いを実感してください。
              </p>
              <div className="d-grid gap-2 d-md-flex justify-content-md-start">
                <Button variant="light" size="lg" className="me-md-2">
                  無料で始める
                </Button>
                <Button variant="outline-light" size="lg">
                  詳細を見る
                </Button>
              </div>
            </Col>
            <Col lg={6}>
              <img
                src="https://via.placeholder.com/600x400"
                alt="Hero Image"
                className="img-fluid rounded"
              />
            </Col>
          </Row>
        </Container>
      </div>

      {/* 機能セクション */}
      <Container className="py-5">
        <Row>
          <Col lg={12} className="text-center mb-5">
            <h2 className="display-5 fw-bold">主要機能</h2>
            <p className="lead">
              あなたのニーズに応える強力な機能を提供します
            </p>
          </Col>
        </Row>
        
        <Row>
          <Col md={4} className="mb-4">
            <Card className="h-100 border-0 shadow-sm">
              <Card.Body className="text-center">
                <div className="mb-3">
                  <i className="fas fa-rocket fa-3x text-primary"></i>
                </div>
                <Card.Title>高速処理</Card.Title>
                <Card.Text>
                  最新の技術を使用して、驚くほど高速な処理を実現
                </Card.Text>
              </Card.Body>
            </Card>
          </Col>
          
          <Col md={4} className="mb-4">
            <Card className="h-100 border-0 shadow-sm">
              <Card.Body className="text-center">
                <div className="mb-3">
                  <i className="fas fa-shield-alt fa-3x text-success"></i>
                </div>
                <Card.Title>セキュリティ</Card.Title>
                <Card.Text>
                  企業レベルのセキュリティで、あなたのデータを保護
                </Card.Text>
              </Card.Body>
            </Card>
          </Col>
          
          <Col md={4} className="mb-4">
            <Card className="h-100 border-0 shadow-sm">
              <Card.Body className="text-center">
                <div className="mb-3">
                  <i className="fas fa-users fa-3x text-info"></i>
                </div>
                <Card.Title>チーム協力</Card.Title>
                <Card.Text>
                  チーム全体で効率的に作業できる協力機能
                </Card.Text>
              </Card.Body>
            </Card>
          </Col>
        </Row>
      </Container>

      {/* 料金セクション */}
      <div className="bg-light py-5">
        <Container>
          <Row>
            <Col lg={12} className="text-center mb-5">
              <h2 className="display-5 fw-bold">料金プラン</h2>
              <p className="lead">
                あなたに最適なプランをお選びください
              </p>
            </Col>
          </Row>
          
          <Row>
            <Col md={4} className="mb-4">
              <Card className="h-100">
                <Card.Body className="text-center">
                  <Card.Title>スターター</Card.Title>
                  <div className="mb-3">
                    <span className="display-4 fw-bold">¥0</span>
                    <span className="text-muted">/月</span>
                  </div>
                  <ul className="list-unstyled">
                    <li>基本機能</li>
                    <li>5GB ストレージ</li>
                    <li>メールサポート</li>
                  </ul>
                  <Button variant="outline-primary" className="w-100">
                    始める
                  </Button>
                </Card.Body>
              </Card>
            </Col>
            
            <Col md={4} className="mb-4">
              <Card className="h-100 border-primary">
                <Card.Header className="bg-primary text-white text-center">
                  <strong>人気</strong>
                </Card.Header>
                <Card.Body className="text-center">
                  <Card.Title>プロ</Card.Title>
                  <div className="mb-3">
                    <span className="display-4 fw-bold">¥2,900</span>
                    <span className="text-muted">/月</span>
                  </div>
                  <ul className="list-unstyled">
                    <li>全機能</li>
                    <li>100GB ストレージ</li>
                    <li>優先サポート</li>
                  </ul>
                  <Button variant="primary" className="w-100">
                    選択する
                  </Button>
                </Card.Body>
              </Card>
            </Col>
            
            <Col md={4} className="mb-4">
              <Card className="h-100">
                <Card.Body className="text-center">
                  <Card.Title>エンタープライズ</Card.Title>
                  <div className="mb-3">
                    <span className="display-4 fw-bold">¥9,900</span>
                    <span className="text-muted">/月</span>
                  </div>
                  <ul className="list-unstyled">
                    <li>カスタム機能</li>
                    <li>無制限ストレージ</li>
                    <li>専任サポート</li>
                  </ul>
                  <Button variant="outline-primary" className="w-100">
                    相談する
                  </Button>
                </Card.Body>
              </Card>
            </Col>
          </Row>
        </Container>
      </div>

      {/* CTAセクション */}
      <div className="bg-dark text-white py-5">
        <Container>
          <Row>
            <Col lg={12} className="text-center">
              <h2 className="display-5 fw-bold mb-4">
                今すぐ始めませんか?
              </h2>
              <p className="lead mb-4">
                無料トライアルで、すべての機能をお試しください
              </p>
              <Button variant="light" size="lg">
                無料で始める
              </Button>
            </Col>
          </Row>
        </Container>
      </div>
    </>
  );
}

ランディングページは、いくつかのセクションで構成されています。

ヒーローセクションでは、大きなタイトルとボタンで注目を集めます。 機能セクションでは、カードを使って主要機能を分かりやすく紹介します。

料金セクションでは、複数のプランを比較できるよう並べて表示します。 CTAセクションでは、最後にもう一度行動を促します。

ダッシュボード

管理画面のような複雑なレイアウトを作成します。

import { 
  Container, Row, Col, Card, Table, 
  Button, Badge, ProgressBar, Nav
} from 'react-bootstrap';

function Dashboard() {
  const stats = [
    { title: '総売上', value: '¥1,234,567', change: '+12%', variant: 'success' },
    { title: '新規顧客', value: '156', change: '+8%', variant: 'info' },
    { title: '注文数', value: '89', change: '-3%', variant: 'warning' },
    { title: '完了率', value: '94%', change: '+2%', variant: 'primary' }
  ];

  const recentOrders = [
    { id: '#1234', customer: '田中太郎', amount: '¥12,000', status: '完了' },
    { id: '#1235', customer: '佐藤花子', amount: '¥8,500', status: '処理中' },
    { id: '#1236', customer: '山田次郎', amount: '¥15,800', status: '発送済' },
    { id: '#1237', customer: '鈴木一郎', amount: '¥6,200', status: '完了' }
  ];

  return (
    <Container fluid>
      <Row>
        {/* サイドバー */}
        <Col lg={2} className="bg-dark text-white p-0">
          <div className="p-3">
            <h4>Dashboard</h4>
          </div>
          <Nav className="flex-column">
            <Nav.Link href="#overview" className="text-white">
              概要
            </Nav.Link>
            <Nav.Link href="#orders" className="text-white">
              注文管理
            </Nav.Link>
            <Nav.Link href="#customers" className="text-white">
              顧客管理
            </Nav.Link>
            <Nav.Link href="#products" className="text-white">
              商品管理
            </Nav.Link>
            <Nav.Link href="#analytics" className="text-white">
              分析
            </Nav.Link>
          </Nav>
        </Col>

        {/* メインコンテンツ */}
        <Col lg={10}>
          <div className="p-4">
            <h1 className="mb-4">ダッシュボード</h1>
            
            {/* 統計カード */}
            <Row className="mb-4">
              {stats.map((stat, index) => (
                <Col md={3} key={index}>
                  <Card className="mb-3">
                    <Card.Body>
                      <Card.Title className="text-muted small">
                        {stat.title}
                      </Card.Title>
                      <div className="d-flex justify-content-between align-items-center">
                        <span className="h3">{stat.value}</span>
                        <Badge bg={stat.variant}>{stat.change}</Badge>
                      </div>
                    </Card.Body>
                  </Card>
                </Col>
              ))}
            </Row>

            <Row>
              {/* 最近の注文 */}
              <Col lg={8}>
                <Card>
                  <Card.Header>
                    <Card.Title className="mb-0">最近の注文</Card.Title>
                  </Card.Header>
                  <Card.Body>
                    <Table responsive>
                      <thead>
                        <tr>
                          <th>注文ID</th>
                          <th>顧客</th>
                          <th>金額</th>
                          <th>ステータス</th>
                          <th>アクション</th>
                        </tr>
                      </thead>
                      <tbody>
                        {recentOrders.map((order, index) => (
                          <tr key={index}>
                            <td>{order.id}</td>
                            <td>{order.customer}</td>
                            <td>{order.amount}</td>
                            <td>
                              <Badge 
                                bg={order.status === '完了' ? 'success' : 
                                   order.status === '処理中' ? 'warning' : 'info'}
                              >
                                {order.status}
                              </Badge>
                            </td>
                            <td>
                              <Button variant="outline-primary" size="sm">
                                詳細
                              </Button>
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </Table>
                  </Card.Body>
                </Card>
              </Col>

              {/* 進捗状況 */}
              <Col lg={4}>
                <Card>
                  <Card.Header>
                    <Card.Title className="mb-0">月間目標</Card.Title>
                  </Card.Header>
                  <Card.Body>
                    <div className="mb-3">
                      <div className="d-flex justify-content-between">
                        <span>売上目標</span>
                        <span>75%</span>
                      </div>
                      <ProgressBar now={75} variant="success" />
                    </div>
                    
                    <div className="mb-3">
                      <div className="d-flex justify-content-between">
                        <span>新規顧客</span>
                        <span>60%</span>
                      </div>
                      <ProgressBar now={60} variant="info" />
                    </div>
                    
                    <div className="mb-3">
                      <div className="d-flex justify-content-between">
                        <span>注文数</span>
                        <span>85%</span>
                      </div>
                      <ProgressBar now={85} variant="warning" />
                    </div>
                    
                    <div className="mb-3">
                      <div className="d-flex justify-content-between">
                        <span>顧客満足度</span>
                        <span>95%</span>
                      </div>
                      <ProgressBar now={95} variant="primary" />
                    </div>
                  </Card.Body>
                </Card>
              </Col>
            </Row>
          </div>
        </Col>
      </Row>
    </Container>
  );
}

ダッシュボードでは、サイドバーメインコンテンツに分けています。

統計カードでは、重要な数値を一目で確認できます。 Badgeコンポーネントで、前月比の変化率を分かりやすく表示しています。

テーブルでは、最近の注文情報を表形式で整理しています。 ProgressBarで、目標に対する進捗状況を視覚的に表現しています。

カスタマイズとテーマ

React Bootstrapをカスタマイズして、独自のデザインを実現しましょう。

CSSカスタマイズ

Bootstrapの変数をカスタマイズします。

// src/custom.scss
// Bootstrap変数のカスタマイズ
$primary: #007bff;
$secondary: #6c757d;
$success: #28a745;
$info: #17a2b8;
$warning: #ffc107;
$danger: #dc3545;
$light: #f8f9fa;
$dark: #343a40;

// フォントの設定
$font-family-sans-serif: 'Noto Sans JP', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
$font-size-base: 1rem;
$line-height-base: 1.6;

// コンポーネントのカスタマイズ
$border-radius: 0.5rem;
$card-border-radius: 0.75rem;
$btn-border-radius: 0.5rem;

// Bootstrapをインポート
@import '~bootstrap/scss/bootstrap';

// カスタムスタイル
.custom-card {
  transition: transform 0.2s, box-shadow 0.2s;
  
  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
  }
}

.custom-button {
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  transition: all 0.3s ease;
  
  &:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 15px rgba(0, 123, 255, 0.3);
  }
}

SCSSを使うことで、Bootstrapの変数を簡単にカスタマイズできます。 プライマリカラーやフォントファミリーを変更して、ブランドに合わせたデザインにできます。

カスタムクラスを追加することで、ホバーエフェクトなどの独自の装飾も加えられます。

テーマ切り替え

ダークテーマとライトテーマを切り替える機能を実装します。

import { createContext, useContext, useState } from 'react';
import { Container, Button, Card, Navbar, Nav } from 'react-bootstrap';

// テーマコンテキスト
const ThemeContext = createContext();

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  
  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };
  
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      <div className={`theme-${theme}`}>
        {children}
      </div>
    </ThemeContext.Provider>
  );
}

function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme must be used within a ThemeProvider');
  }
  return context;
}

function ThemedComponent() {
  const { theme, toggleTheme } = useTheme();
  
  return (
    <>
      <Navbar bg={theme} variant={theme} className="mb-4">
        <Container>
          <Navbar.Brand>My App</Navbar.Brand>
          <Nav className="ms-auto">
            <Button
              variant={theme === 'light' ? 'dark' : 'light'}
              onClick={toggleTheme}
            >
              {theme === 'light' ? '🌙' : '☀️'}
            </Button>
          </Nav>
        </Container>
      </Navbar>
      
      <Container>
        <Card bg={theme} text={theme === 'dark' ? 'light' : 'dark'}>
          <Card.Body>
            <Card.Title>テーマ切り替えの例</Card.Title>
            <Card.Text>
              現在のテーマ: {theme === 'light' ? 'ライト' : 'ダーク'}
            </Card.Text>
            <Button variant="primary" onClick={toggleTheme}>
              テーマを切り替える
            </Button>
          </Card.Body>
        </Card>
      </Container>
    </>
  );
}

// 使用例
function App() {
  return (
    <ThemeProvider>
      <ThemedComponent />
    </ThemeProvider>
  );
}

createContextuseContextを使って、テーマ情報をアプリ全体で共有しています。 ボタンをクリックするだけで、ライトテーマとダークテーマを切り替えられます。

アニメーション追加

CSS アニメーションを追加してよりダイナミックなUIを作成します。

/* src/animations.css */
@keyframes fadeIn {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes slideIn {
  from { transform: translateX(-100%); }
  to { transform: translateX(0); }
}

@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}

.fade-in {
  animation: fadeIn 0.6s ease-out;
}

.slide-in {
  animation: slideIn 0.5s ease-out;
}

.pulse {
  animation: pulse 2s infinite;
}

.hover-lift {
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.hover-lift:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
// アニメーション付きコンポーネント
function AnimatedCards() {
  const [isVisible, setIsVisible] = useState(false);
  
  useEffect(() => {
    setIsVisible(true);
  }, []);
  
  return (
    <Container>
      <Row>
        {[1, 2, 3].map((item, index) => (
          <Col md={4} key={item}>
            <Card 
              className={`hover-lift ${isVisible ? 'fade-in' : ''}`}
              style={{ animationDelay: `${index * 0.2}s` }}
            >
              <Card.Body>
                <Card.Title>カード {item}</Card.Title>
                <Card.Text>
                  アニメーション付きのカードです。
                </Card.Text>
                <Button variant="primary" className="pulse">
                  アクション
                </Button>
              </Card.Body>
            </Card>
          </Col>
        ))}
      </Row>
    </Container>
  );
}

アニメーションを追加することで、より魅力的なUIになります。 animationDelayを使って、カードが順番に表示されるようにしています。

まとめ

React Bootstrapを使うことで、デザイン初心者でも美しいUIを簡単に作成できます。

主要なメリット

React Bootstrapの導入によって得られる主なメリットをまとめます。

  • 短時間でのUI開発: 既製のコンポーネントで開発時間を大幅短縮
  • レスポンシブデザイン: モバイルファーストの設計で全デバイス対応
  • 一貫性のあるデザイン: 統一されたデザインシステム
  • カスタマイズ性: 独自のブランドに合わせた調整が可能
  • 豊富なコンポーネント: 50以上のコンポーネントが利用可能

これらのメリットにより、開発効率が大幅に向上します。

実装時のベストプラクティス

実際にプロジェクトに導入する際のポイントを整理します。

// 1. 必要なコンポーネントのみインポート
import { Container, Row, Col, Button } from 'react-bootstrap';

// 2. カスタムCSSでブランドカラーを設定
const customTheme = {
  primary: '#007bff',
  secondary: '#6c757d',
  // ...
};

// 3. レスポンシブデザインを意識
<Row>
  <Col xs={12} md={6} lg={4}>
    {/* コンテンツ */}
  </Col>
</Row>

// 4. アクセシビリティを考慮
<Button 
  variant="primary" 
  aria-label="商品を購入する"
  onClick={handlePurchase}
>
  購入する
</Button>

活用シーン

React Bootstrapが特に有効な場面をまとめます。

  • スタートアップのMVP: 素早くプロトタイプを作成
  • 企業サイト: 信頼性の高いデザインシステム
  • ダッシュボード: 複雑なレイアウトの管理画面
  • Eコマース: 商品一覧やカートの実装
  • ブログ・メディア: コンテンツ重視のレイアウト

どんなプロジェクトでも活用できる汎用性の高さが魅力です。

今後の学習

React Bootstrapをマスターした後は、以下のステップアップを検討してください。

// より高度なカスタマイズ
import { ThemeProvider } from 'react-bootstrap';

// 他のUIライブラリとの比較
// Material-UI, Ant Design, Chakra UI など

// 独自のデザインシステム構築
// Styled Components, Emotion などと組み合わせ

React Bootstrapは、React開発において非常に実用的なライブラリです。 デザイン経験がない方でも、プロフェッショナルなUIを短時間で作成できます。

ぜひ今回紹介した実装例を参考にして、あなたのプロジェクトで美しいUIを作成してください。 継続的に学習することで、より高度なカスタマイズも可能になります。

関連記事