【中級者向け】Blade コンポーネントで作る再利用可能な UI パーツガイド
この記事で学べること
- Blade コンポーネントの基本構造と作成手順
- Props・Slot を活用した柔軟な設計方法
- 色覚特性に配慮した配色とARIAロールの指定例
- 実践的なサンプルコードとディレクトリ構成
- アクセシビリティ向上のためのチェックリスト
想定読者
- Laravel を一通り触ったことがあり、ビューの保守性を高めたい中級者
- チーム開発で一貫したUIを効率的に提供したいフロントエンドエンジニア
- アクセシビリティ対応を学びながら再利用性の高いコンポーネント設計を身につけたい方
アクセシビリティレベル:★★★★☆
色のコントラスト比検証、ARIA属性の具体例、キーボード操作への配慮を網羅
はじめに:なぜ Blade コンポーネントが必要なのか
Laravel で大規模なプロジェクトを進めると、
同じようなボタンやカード、モーダルを何度も書き直す場面に直面します。
ビューの冗長化は、保守コストやバグの温床になりがち……。
Blade コンポーネントを活用すると、一度定義した UI パーツをどこでも簡単に再利用でき、
開発効率とコードの読みやすさが飛躍的に向上します♡
- 一貫性:デザインのばらつきを防ぎ、ブランドイメージを統一
- 保守性:修正はコンポーネント一箇所だけでOK
- 可読性:ビューがシンプルになり、チームメンバーも理解しやすい
1. コンポーネントディレクトリ構成と基本ファイル
まずはディレクトリ構成から。Laravel 9以降では resources/views/components
配下が推奨です。
resources/
└── views/
└── components/
├── button.blade.php
├── card.blade.php
├── form/
│ └── input.blade.php
└── layout/
└── app.blade.php
components/
直下には汎用パーツ(ボタン、カードなど)components/form/
にはフォーム系パーツ(入力欄、ラベル付きグループ)components/layout/
にはレイアウト系(ヘッダー・フッター共通レイアウト)
ディレクトリを階層化することで、増え続けるコンポーネントも見通し良く管理できます。
2. Props と Slot の基本:パラメータ受け渡しと柔軟性
2.1 Props で外部から値を受け取る
{{-- resources/views/components/button.blade.php --}}
@props([
'type' => 'primary',
'url' => '#',
'label' => 'ボタン',
])
@php
// 色ごとにクラスを切り替え
$baseClass = 'px-4 py-2 rounded ';
$colors = [
'primary' => 'bg-blue-600 text-white hover:bg-blue-700',
'secondary' => 'bg-gray-200 text-gray-800 hover:bg-gray-300',
];
@endphp
<a href="{{ $url }}"
{{ $attributes->merge(['class' => $baseClass . ($colors[$type] ?? $colors['primary'])]) }}>
{{ $label }}
</a>
@props
で受け取るパラメータを宣言$attributes->merge()
で追加クラスやARIA属性を流し込み可能
2.2 Slot で柔軟なコンテンツ差し替え
{{-- resources/views/components/card.blade.php --}}
<div {{ $attributes->merge(['class'=>'border rounded-lg shadow-sm p-4']) }}>
{{-- カードヘッダー --}}
@if (isset($header))
<div class="border-b mb-3">
{{ $header }}
</div>
@endif
{{-- メインコンテンツ --}}
<div class="mb-3">
{{ $slot }}
</div>
{{-- フッター(任意) --}}
@if (isset($footer))
<div class="border-t pt-2 text-right">
{{ $footer }}
</div>
@endif
</div>
<x-card>
タグに囲まれた部分が{{ $slot }}
に展開- タグ属性で
header
/footer
スロットを指定可能
3. 色覚特性に配慮したカラーパレットとコントラスト
アクセシビリティ向上のため、WCAG 2.1 レベル AA を満たす コントラスト比(4.5:1以上)を意識しましょう。
色名 | HEX | コントラスト比 (白背景) |
---|---|---|
ブルー600 | #2563EB |
6.8:1 |
グレー200 | #E5E7EB |
12.5:1 |
グリーン600 | #059669 |
7.2:1 |
- オンラインツールで自動検証しながら調整
- ボタンやリンク、テキストの識別性を確保
さらに、ダークモード対応時は反転色も確認し、ARIAの prefers-color-scheme
メディアクエリを活用しましょう。
4. ARIA 属性・キーボード操作・スクリーンリーダー対応
4.1 ARIAロールの指定例
{{-- モーダルコンポーネントの一部 --}}
<div role="dialog" aria-modal="true" aria-labelledby="modal-title">
<h2 id="modal-title">{{ $title }}</h2>
{{ $slot }}
</div>
role="dialog"
:モーダルであることをスクリーンリーダーに伝達aria-modal="true"
:背景のコンテンツを無効化aria-labelledby
:タイトル要素を関連づけ
4.2 キーボード操作の配慮
- フォーカストラップ:モーダル内でTabキー移動をループ
- Escキーで閉じる:
@keydown.escape
でハンドリング - 視覚だけでなく操作性も確保しましょう♡
5. 実践サンプル:再利用可能なフォーム入力コンポーネント
{{-- resources/views/components/form/input.blade.php --}}
@props([
'id',
'label',
'type' => 'text',
'name' => $id,
'value' => old($id, ''),
'required' => false,
])
<div class="mb-4">
<label for="{{ $id }}" class="block text-gray-700 mb-1">
{{ $label }}
@if ($required)
<span aria-hidden="true" class="text-red-500">*</span>
@endif
</label>
<input id="{{ $id }}"
type="{{ $type }}"
name="{{ $name }}"
value="{{ $value }}"
@if($required) required @endif
{{ $attributes->merge(['class'=>'w-full border rounded px-3 py-2']) }}
aria-required="{{ $required }}"
aria-describedby="{{ $id }}-error">
@error($name)
<p id="{{ $id }}-error" class="text-red-600 mt-1" role="alert">
{{ $message }}
</p>
@enderror
</div>
required
フラグで必須マーク&ARIA属性自動付与aria-describedby
でエラーメッセージと連携
6. まとめ・今すぐ試せるチェックリスト
- ディレクトリ構成 を整えて一目で把握
- Props・Slot で柔軟&型安全にパーツ化
- コントラスト比検証 で色覚配慮
- ARIA属性・キーボード操作 で包括的なアクセシビリティ
- 共通コンポーネント をライブラリ化してチーム内で共有
これらを実践すれば、チーム開発でも安心・安全な UI パーツが作成できます♡
ぜひ今日から自分のプロジェクトに取り入れて、Laravel Blade のパワーを実感してみてくださいね!