Material DesignでWebアプリを設計する方法|画面設計・実装・改善を徹底解説
Material Designを取り入れたWebアプリ設計では、見た目を整えるだけでなく、利用者が迷わず操作できる情報構造、状態の分かりやすさ、端末ごとの表示最適化まで一貫して考える必要があります。ボタンの色やカードの影だけを模倣しても、画面全体の優先順位や操作結果が分かりにくければ、Material Designの強みを十分に生かすことはできません。
重要なのは、視覚表現、操作方法、画面遷移、入力支援、アクセシビリティを別々に扱わず、一つの設計方針として統合することです。特に業務用Webアプリや会員向けサービスでは、利用者が長時間操作することも多いため、装飾性よりも予測可能性、読みやすさ、作業効率を優先しなければなりません。
本記事では、Material Designを活用したWebアプリの作り方を、設計から実装、検証、継続的な改善まで順番に解説します。HTML、CSS、JavaScriptによるコード例も掲載し、表面的なデザインの再現ではなく、実際の開発で使える設計方法を具体的に整理します。
1. Material Designとは
Material Designとは、画面上の要素を意味のある層として整理し、色、形、余白、動き、操作結果を一貫させるためのデザインシステムです。Webアプリに導入する場合は、見た目の統一だけでなく、利用者が次に何をすべきかを理解できる構造を作ることが中心になります。
1.1 Material Designとはどのような設計手法か
Material Designでは、ボタン、カード、入力欄、画面上部の操作領域などを、役割を持った部品として扱います。それぞれの部品には、通常時、選択時、押下時、無効時、エラー時といった状態があり、状態ごとの見え方や反応をあらかじめ決めておくことが重要です。
単純に部品を並べるのではなく、重要な情報を前面に出し、補助的な情報を控えめに表示することで、利用者の視線を自然に誘導します。この優先順位が明確であれば、説明文を大量に追加しなくても、画面の目的や操作方法を理解しやすくなります。
1.2 Webアプリに適している理由
Webアプリでは、一覧表示、検索、入力、編集、保存、通知といった共通操作が繰り返し登場します。Material Designは、こうした操作に適した部品と状態表現を体系化しやすいため、画面数が多いサービスでも統一感を維持できます。
利用者にとっても、同じ形や位置の部品が同じ役割を持っていれば、画面が変わるたびに操作方法を覚え直す必要がありません。管理画面、予約システム、顧客管理システムなど、反復作業が多いWebアプリでは特に大きな効果があります。
1.3 視覚的な階層が果たす役割
視覚的な階層とは、情報の重要度を大きさ、色、余白、位置、影などによって表現する考え方です。主要な見出し、中心となる操作、補助情報を同じ強さで表示すると、利用者はどこから確認すべきか判断できません。
例えば、保存ボタンを強調色で表示し、キャンセル操作を文字だけの控えめなボタンにすれば、主要操作と副次操作の違いが伝わります。ただし、すべての操作を強調すると優先順位が消えるため、一画面で最も重要な操作を絞り込む必要があります。
1.4 一貫性が操作性に与える影響
一貫性のあるWebアプリでは、同じ操作に同じ色、形、文言、配置が使われます。ある画面では青色が保存を意味し、別の画面では削除を意味するような設計は、利用者の判断を遅らせ、誤操作の原因になります。
部品の見た目だけでなく、処理完了後の通知方法やエラーの表示位置も統一することが重要です。保存後は常に画面下部へ通知を表示する、入力エラーは該当欄の直下に表示するといった規則を作ることで、利用者は画面の反応を予測できます。
1.5 導入前に決めておく範囲
Material Designを導入する前に、対象となる画面、共通部品、配色、文字、余白、状態表現の範囲を決めます。全画面を一度に変更しようとすると、既存機能への影響が大きくなり、部品ごとの品質確認も難しくなります。
最初はボタン、入力欄、カード、通知、画面上部の操作領域など、使用頻度が高い部品から整備すると効果的です。その後、一覧表、検索条件、モーダル画面、グラフ表示などへ段階的に対象を広げると、設計と実装の負担を管理しやすくなります。
2. 情報設計と画面構造を整理する
Material Designを適用する前に、Webアプリ内の情報と操作を整理する必要があります。画面構造が複雑なまま色や部品だけを変更しても、利用者の迷いは解消されないため、最初に目的、情報、操作の関係を明確にします。
2.1 画面ごとの目的を一つに絞る
一つの画面に検索、登録、分析、設定、通知確認などの機能を詰め込みすぎると、中心となる操作が分かりにくくなります。画面を設計するときは、その画面で利用者が完了すべき主要な目的を一つ決めることが重要です。
主要目的が商品登録であれば、入力欄と登録操作を中心に配置し、履歴確認や詳細設定は別画面または補助領域へ分離します。目的を明確にすることで、見出し、説明文、ボタンの優先順位も自然に決まります。
2.2 利用者の行動順序を可視化する
Webアプリの画面は、開発側のデータ構造ではなく、利用者が作業する順序に合わせて並べる必要があります。利用者が顧客を検索し、詳細を確認し、内容を編集して保存するのであれば、その順序に沿って画面遷移と操作を設計します。
行動順序を整理すると、どの段階で戻る操作が必要か、どこで確認画面を表示すべきかも判断できます。途中で作業を中断した場合の復帰方法まで想定すると、実際の利用環境に耐えられる画面設計になります。
2.3 情報を重要度別に分類する
画面に表示する情報は、主要情報、補助情報、詳細情報に分けて整理します。すべてを最初から表示すると情報量が増え、利用者が重要な項目を探す時間も長くなります。
注文管理画面であれば、注文番号、顧客名、金額、状態を主要情報として目立たせ、住所や備考を補助情報として配置できます。操作頻度が低い詳細情報は、展開領域や詳細画面へ移動させることで、一覧性を保てます。
2.4 画面遷移を減らしすぎない
操作回数を減らすために一画面へ機能を集約しすぎると、かえって画面が複雑になります。画面遷移の少なさだけを目標にするのではなく、利用者が現在地と操作結果を理解できるかどうかを基準に判断する必要があります。
関連性の高い編集操作は同じ画面にまとめ、目的が異なる設定や履歴は別画面に分ける方法が有効です。画面を分ける場合でも、戻る位置や保存状態を維持すれば、利用者の負担を抑えられます。
2.5 情報構造をHTMLへ反映する
見た目だけでなく、HTMLの構造にも情報の階層を反映させることが重要です。画面の主要部分にはmain、案内領域にはnav、独立した内容にはsectionやarticleを使い、意味のある構造を作ります。
適切なHTML構造は、検索エンジンによる内容理解だけでなく、読み上げ機能やキーボード操作にも影響します。装飾目的で無意味な要素を重ねるのではなく、情報の役割に合わせて要素を選択します。
実装例:意味を持たせた画面構造
<header class="app-header">
<h1>注文管理</h1>
</header>
<nav class="side-navigation" aria-label="主要メニュー">
<a href="/orders" aria-current="page">注文一覧</a>
<a href="/customers">顧客一覧</a>
<a href="/settings">設定</a>
</nav>
<main class="main-content">
<section aria-labelledby="order-list-title">
<h2 id="order-list-title">注文一覧</h2>
<p>注文状況を確認し、必要な処理を実行できます。</p>
</section>
</main>
3. 配色とテーマを設計する
配色はWebアプリの印象を決めるだけでなく、操作の優先順位や状態を伝える役割を持ちます。強調色を増やしすぎず、背景、文字、境界線、状態色を体系的に定義することで、画面全体の一貫性を維持できます。
3.1 主要色と補助色を使い分ける
主要色は、Webアプリを象徴する色として、主要ボタン、選択中の項目、重要な強調部分に使用します。利用頻度が高い色だからこそ、背景色との明度差や文字の読みやすさを確認しなければなりません。
補助色は、主要色だけでは区別しにくい状態や情報を表現するために使います。ただし、装飾目的で多数の補助色を追加すると統一感が崩れるため、明確な役割を与えたうえで限定的に使用します。
3.2 背景色と表面色を分ける
Webアプリ全体の背景と、カードや入力領域などの表面を同じ色にすると、情報のまとまりが認識しにくくなります。わずかな明度差や境界線を使い、背景と操作領域を区別する必要があります。
影を強く付けるだけで階層を表現すると、画面が重く見える場合があります。背景色、表面色、余白、境界線を組み合わせ、必要な場所だけに控えめな影を使用すると、落ち着いた画面になります。
3.3 状態を色だけで伝えない
成功、警告、エラー、処理中といった状態には、それぞれ適切な色を設定します。ただし、赤色だけでエラーを示す設計では、色の違いを認識しにくい利用者へ十分な情報を伝えられません。
状態色には、記号、短い説明文、枠線、背景の変化を組み合わせます。例えば入力エラーでは、赤い枠線だけでなく、該当欄の直下に具体的な修正方法を表示することで、問題を理解しやすくなります。
3.4 明るい表示と暗い表示を準備する
明るい表示と暗い表示では、単純に白と黒を反転させるだけでは十分ではありません。暗い背景では、純粋な白を広範囲に使うとまぶしく感じられるため、少し明度を抑えた文字色や表面色を選びます。
影の見え方も背景によって変わるため、暗い表示では境界線や表面色の差を活用します。両方の表示で主要操作、入力欄、選択状態、無効状態を確認し、同じ情報階層が維持されているか検証します。
3.5 色を変数として一元管理する
色を画面ごとに直接指定すると、修正時に多数のファイルを変更する必要があります。主要色、背景色、文字色、状態色を変数として定義すれば、テーマ変更やブランド変更にも対応しやすくなります。
変数名には色そのものではなく、役割を表す名前を使う方法が有効です。blue-500のような名前だけでなく、primary、error、surfaceに相当する役割名を付けることで、用途を理解しやすくなります。
実装例:色の役割を変数で管理する
:root {
--color-primary: #4355b9;
--color-on-primary: #ffffff;
--color-surface: #ffffff;
--color-background: #f7f7fb;
--color-text: #1b1b1f;
--color-text-subtle: #5f5f67;
--color-border: #c7c7d0;
--color-error: #ba1a1a;
--color-success: #286c2f;
}
[data-theme="dark"] {
--color-primary: #bbc3ff;
--color-on-primary: #10217b;
--color-surface: #1b1b1f;
--color-background: #121216;
--color-text: #e5e1e6;
--color-text-subtle: #c7c5ce;
--color-border: #46464f;
}
4. 文字と読みやすさを整える
文字設計では、書体の選択だけでなく、見出し、本文、補足、入力値、ボタン文言の役割を明確にします。文字サイズや太さを増やしすぎず、少数の規則で画面全体を整理することが大切です。
4.1 見出しの階層を明確にする
大見出し、中見出し、小見出しの差が小さすぎると、情報のまとまりを把握しにくくなります。文字サイズだけでなく、太さ、行間、前後の余白を変え、階層を視覚的に区別します。
見出しを大きくしすぎると、業務用Webアプリでは表示できる情報量が減ります。端末幅や画面の目的を考慮し、強い見出しを必要な場所だけに使用することが重要です。
4.2 本文の行間と行長を調整する
本文の行間が狭いと上下の行が重なって見え、長文を読み進めにくくなります。反対に行間が広すぎると文章のまとまりが失われるため、文字サイズに対して適度な比率を設定します。
横幅いっぱいに長文を表示すると、視線を次の行へ移動しにくくなります。説明文やヘルプ文章には最大幅を設定し、広い画面でも一行が長くなりすぎないようにします。
4.3 ボタン文言を具体的にする
「実行」「決定」「送信」のような抽象的な文言は、押した後に何が起こるか分かりにくい場合があります。「注文を登録」「変更を保存」「請求書を送信」のように、操作対象と結果を含めると理解しやすくなります。
ただし、すべてのボタン文言を長くすると画面が窮屈になります。操作の文脈が明らかな場所では短い表現を使い、削除や送信など影響が大きい操作では具体的な文言を選びます。
4.4 補足情報を小さくしすぎない
補足説明や注記は主要情報より控えめに表示しますが、読めないほど小さくしてはいけません。利用条件、入力形式、料金、重要な注意事項などは、補足であっても十分な文字サイズと明度差を確保します。
重要度を下げる方法は、文字を極端に小さくすることだけではありません。色の強さ、配置、余白を調整することで、読みやすさを保ちながら主要情報との差を作れます。
4.5 文字規則を共通化する
見出しや本文の指定を画面ごとに作ると、少しずつ異なる文字サイズや行間が増えていきます。あらかじめ用途別の文字規則を定義し、すべての画面で同じ規則を利用することが重要です。
文字規則を共通化すると、画面全体の調整も効率化できます。本文が小さすぎると判明した場合でも、共通変数を変更するだけで複数画面へ反映できます。
実装例:文字規則をCSSで定義する
:root {
--font-family-base:
"Noto Sans JP",
"Hiragino Kaku Gothic ProN",
"Yu Gothic",
sans-serif;
--font-size-title: clamp(1.5rem, 2vw, 2rem);
--font-size-heading: 1.25rem;
--font-size-body: 1rem;
--font-size-caption: 0.875rem;
--line-height-title: 1.3;
--line-height-body: 1.75;
}
body {
font-family: var(--font-family-base);
font-size: var(--font-size-body);
line-height: var(--line-height-body);
}
.page-title {
font-size: var(--font-size-title);
line-height: var(--line-height-title);
}
.section-title {
font-size: var(--font-size-heading);
margin-block: 2rem 1rem;
}
.caption {
font-size: var(--font-size-caption);
color: var(--color-text-subtle);
}
5. 余白と配置を体系化する
余白は、要素同士の関係を示し、画面の読みやすさを支える重要な要素です。感覚だけで余白を決めるのではなく、一定の間隔規則を作り、関連する要素を近づけ、異なる内容を離して配置します。
5.1 一定の間隔単位を使用する
余白の値が画面ごとに異なると、全体が不揃いに見えます。4ピクセルや8ピクセルなどの基準単位を決め、その倍数を中心に余白を設計すると一貫性を保ちやすくなります。
すべての余白を同じ値にする必要はありません。入力欄内部の余白、部品同士の間隔、節同士の間隔など、関係性に応じて段階を作り、限られた種類の値を使い分けます。
5.2 関連する要素を近づける
入力欄の名前、入力欄本体、補足説明、エラー文は、一つのまとまりとして認識できる距離に配置します。名前と入力欄の間隔が広すぎると、どの説明がどの欄に対応しているか分かりにくくなります。
一方で、次の入力項目との間には少し広い余白を設けます。内部の余白を狭く、まとまり同士の余白を広くすることで、枠線を増やさなくても構造を伝えられます。
5.3 揃える基準を統一する
画面内の要素が異なる位置から始まると、視線の移動が増えます。見出し、本文、入力欄、ボタンの左端をできるだけ揃え、明確な縦の基準線を作ります。
数値一覧では右揃え、短い状態表示では中央揃えが適する場合もあります。内容の種類に応じた揃え方を選び、同じ列内で規則が変わらないようにします。
5.4 密度を画面の目的に合わせる
一般利用者向けサービスでは、十分な余白と大きな操作領域が安心感につながります。一方、業務用Webアプリでは、多くの情報を比較するために、ある程度高い表示密度が求められることがあります。
重要なのは、単に余白を減らすのではなく、利用者が情報を区別できる範囲で密度を調整することです。標準表示とコンパクト表示を切り替えられる仕組みを用意する方法もあります。
5.5 配置規則を変数化する
余白も色と同様に、共通変数として管理すると変更しやすくなります。小、中、大といった役割別の値を定義し、部品内部と画面全体で再利用します。
変数を利用すれば、端末幅に応じて余白を調整することも容易です。狭い画面では外側の余白を減らし、広い画面では最大幅を保ちながら余白を増やす設計ができます。
実装例:余白の段階を定義する
:root {
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 0.75rem;
--space-4: 1rem;
--space-5: 1.5rem;
--space-6: 2rem;
--space-7: 3rem;
}
.page-container {
width: min(100% - 2rem, 72rem);
margin-inline: auto;
}
.form-field {
display: grid;
gap: var(--space-2);
margin-block-end: var(--space-5);
}
.section {
margin-block: var(--space-7);
}
6. 共通部品を設計する
Webアプリの品質を安定させるには、ボタン、カード、入力欄、通知などを共通部品として設計する必要があります。画面ごとに異なる実装を作るのではなく、役割、状態、使い方を定義した部品を再利用します。
6.1 ボタンの種類を増やしすぎない
ボタンは、主要操作、副次操作、控えめな操作、危険な操作など、役割別に少数の種類へ整理します。似た見た目のボタンを多数作ると、利用者も開発者も使い分けを判断できなくなります。
一画面に強調された主要ボタンを複数配置すると、どれを選ぶべきか迷いやすくなります。画面の目的に最も近い操作だけを強く表示し、それ以外は視覚的な強さを抑えます。
6.2 カードを乱用しない
カードは、独立した情報をまとめる場合に有効です。しかし、すべての文章や入力項目をカードで囲むと、画面内に枠と影が増え、かえって情報の関係が分かりにくくなります。
一覧内の商品、案件、記事など、繰り返し表示される独立項目にはカードが適しています。一方、一つの連続した入力フォームでは、見出しと余白だけで整理した方が自然な場合があります。
6.3 状態ごとの見た目を定義する
共通部品には、通常、カーソル通過、キーボード選択、押下、無効、処理中などの状態があります。通常時の見た目だけを設計すると、実装段階で状態表現が画面ごとにばらつきます。
特にキーボード選択状態は、カーソル通過状態と区別して設計する必要があります。輪郭線や背景変化を使い、現在どの部品を操作できるか明確に示します。
6.4 部品の利用条件を明文化する
共通部品を用意しても、どの場面で使うかが決まっていなければ、誤った利用が増えます。主要ボタンは一つの領域に一個まで、警告色は取り消し困難な操作だけに使うなど、利用条件を文章で定義します。
表示例だけでなく、使用してはいけない例も共有すると効果的です。設計担当者と開発担当者が同じ基準で判断できるため、確認作業や修正回数を減らせます。
6.5 部品を独立して検証する
部品は完成した画面内だけで確認するのではなく、単独でも状態を検証します。長い文言、短い文言、エラー状態、無効状態、狭い画面など、通常とは異なる条件を試す必要があります。
部品単位で検証すれば、複数画面に組み込んだ後の修正を減らせます。共通部品の変更は多くの画面へ影響するため、早い段階で境界条件を確認することが重要です。
実装例:状態を持つボタン
<button class="button button-primary" type="button">
変更を保存
</button>
<button class="button button-secondary" type="button">
キャンセル
</button>
<button class="button button-danger" type="button">
アカウントを削除
</button>
.button {
min-height: 2.75rem;
padding: 0.625rem 1.25rem;
border: 0;
border-radius: 999px;
font: inherit;
font-weight: 700;
cursor: pointer;
transition:
background-color 160ms ease,
box-shadow 160ms ease,
transform 80ms ease;
}
.button-primary {
color: var(--color-on-primary);
background: var(--color-primary);
}
.button:hover {
box-shadow: 0 0.25rem 0.75rem rgb(0 0 0 / 16%);
}
.button:active {
transform: translateY(1px);
}
.button:focus-visible {
outline: 0.1875rem solid currentColor;
outline-offset: 0.1875rem;
}
.button:disabled {
cursor: not-allowed;
opacity: 0.48;
box-shadow: none;
}
7. ナビゲーションを分かりやすくする
ナビゲーションは、利用者が現在地を把握し、目的の機能へ移動するための仕組みです。項目数、画面幅、利用頻度に合わせて形式を選び、同じ階層の項目が同じ位置に表示されるようにします。
7.1 主要機能を絞り込む
すべての機能を主要メニューに並べると、選択肢が増えすぎて目的の項目を探しにくくなります。利用頻度と重要度を基準に主要機能を選び、それ以外は設定や追加メニューへ整理します。
管理者専用機能や低頻度の操作は、一般利用者の主要メニューに常時表示しない方が分かりやすくなります。権限に応じて表示項目を調整する場合でも、同じ権限内では配置を安定させます。
7.2 現在地を明確に表示する
利用者は、現在どの機能を開いているか常に確認できる必要があります。選択中の項目へ背景色、左側の線、文字の太さなどを追加し、他の項目と明確に区別します。
色だけに依存せず、形や文字の変化も組み合わせると認識しやすくなります。HTMLではaria-current="page"を設定し、読み上げ環境にも現在地を伝えます。
7.3 画面幅に応じて形式を変える
広い画面では左側のナビゲーションが使いやすくても、スマートフォンでは本文領域を圧迫します。狭い画面では下部ナビゲーションや折りたたみメニューへ切り替える設計が必要です。
形式を変える場合でも、項目名や並び順を大きく変更しないことが重要です。端末を切り替えた利用者が、同じ機能を同じ順序で見つけられるようにします。
7.4 階層を深くしすぎない
ナビゲーションの階層が深くなると、目的の画面へ到達するまでの選択回数が増え、現在地も把握しにくくなります。機能分類を見直し、頻繁に使う画面は浅い階層へ配置します。
深い階層が避けられない場合は、パンくず、戻る操作、親画面名を表示します。利用者が行き止まりを感じないように、現在の階層と戻り先を明確にします。
7.5 メニューの開閉状態を管理する
折りたたみメニューでは、開閉状態が視覚的にも読み上げ環境にも伝わる必要があります。開閉ボタンに状態を示す属性を設定し、メニューを閉じたときは内部の操作項目へキーボード選択が移動しないようにします。
画面遷移後にメニューを閉じるか、利用者の選択状態を維持するかも決めておきます。スマートフォンでは画面遷移後に閉じ、広い画面では開いたままにするなど、利用環境に合わせて挙動を調整します。
実装例:開閉可能なナビゲーション
<button
id="menu-button"
class="menu-button"
type="button"
aria-expanded="false"
aria-controls="main-menu"
>
メニュー
</button>
<nav id="main-menu" hidden aria-label="主要メニュー">
<a href="/dashboard">概要</a>
<a href="/orders">注文</a>
<a href="/customers">顧客</a>
</nav>
const menuButton = document.querySelector("#menu-button");
const mainMenu = document.querySelector("#main-menu");
menuButton.addEventListener("click", () => {
const isOpen = menuButton.getAttribute("aria-expanded") === "true";
menuButton.setAttribute("aria-expanded", String(!isOpen));
mainMenu.hidden = isOpen;
});
8. 入力フォームを使いやすくする
入力フォームでは、項目名、入力形式、必須条件、エラー、送信結果を明確に伝える必要があります。見た目を簡潔にするために説明を削りすぎると、入力ミスや途中離脱が増える可能性があります。
8.1 項目名を常に確認できるようにする
入力前の例を項目名の代わりに表示すると、入力後に何の項目だったか分からなくなる場合があります。項目名は入力欄の外側または入力後も確認できる位置に表示します。
入力例は、項目名とは別に補足として使います。例えば電話番号欄では、項目名を「電話番号」とし、入力例として「09012345678」を表示すれば、役割と形式の両方を伝えられます。
8.2 必須項目と任意項目を明示する
必須項目が多いフォームで、すべてに必須表示を付けると画面が騒がしくなる場合があります。その場合は、フォーム冒頭で「任意と記載のない項目は必須」と説明する方法もあります。
ただし、利用者が迷わないことを優先しなければなりません。必須と任意が混在するフォームでは、それぞれの項目に明確な表示を付け、記号だけではなく文字でも意味を示します。
8.3 入力形式を事前に説明する
入力後に初めて形式エラーを表示すると、利用者は修正のために作業をやり直す必要があります。文字数、使用可能な文字、日付形式、パスワード条件などは入力前に確認できるようにします。
説明文が長い場合は、常時表示する条件と、必要なときだけ表示する補足を分けます。最も重要な条件は入力欄の近くに表示し、詳細な説明は展開できるようにすると画面を整理できます。
8.4 エラー内容を具体的にする
「入力内容に誤りがあります」だけでは、利用者が何を直すべきか判断できません。「郵便番号は半角数字7桁で入力してください」のように、問題と修正方法を具体的に示します。
送信時に複数のエラーが発生した場合は、最初のエラー位置へ移動できるようにする方法も有効です。画面上部のエラー概要と、各入力欄直下の詳細説明を組み合わせると修正しやすくなります。
8.5 送信中の重複操作を防ぐ
通信処理に時間がかかると、利用者が送信ボタンを複数回押す場合があります。送信開始後はボタンを一時的に無効化し、処理中であることを文字や進行表示で伝えます。
ただし、長時間無効のままにすると、処理が止まったのか判断できません。一定時間を超えた場合の案内、再試行方法、入力内容の保持まで設計しておく必要があります。
実装例:入力検証と具体的なエラー表示
<form id="profile-form" novalidate>
<div class="form-field">
<label for="email">メールアドレス</label>
<input
id="email"
name="email"
type="email"
autocomplete="email"
aria-describedby="email-help email-error"
required
>
<p id="email-help">連絡を受け取れるアドレスを入力してください。</p>
<p id="email-error" class="field-error" aria-live="polite"></p>
</div>
<button id="submit-button" class="button button-primary" type="submit">
変更を保存
</button>
</form>
const form = document.querySelector("#profile-form");
const email = document.querySelector("#email");
const emailError = document.querySelector("#email-error");
const submitButton = document.querySelector("#submit-button");
form.addEventListener("submit", async (event) => {
event.preventDefault();
emailError.textContent = "";
if (!email.validity.valid) {
emailError.textContent =
"有効なメールアドレスを入力してください。";
email.focus();
return;
}
submitButton.disabled = true;
submitButton.textContent = "保存しています";
try {
await saveProfile(new FormData(form));
} catch (error) {
emailError.textContent =
"保存できませんでした。通信状態を確認して再度お試しください。";
} finally {
submitButton.disabled = false;
submitButton.textContent = "変更を保存";
}
});
9. 状態と操作結果を伝える
Webアプリでは、保存、削除、通信、読み込み、失敗など、利用者の操作に応じて状態が変化します。操作後に何も表示されなければ、処理が完了したのか判断できないため、適切な反応を返す必要があります。
9.1 読み込み中を明示する
通信開始後に画面が停止したように見えると、利用者は操作が受け付けられなかったと考えます。進行表示、読み込み中の文言、仮の表示領域などを使い、処理中であることを伝えます。
短時間の処理で進行表示を即座に出すと、画面がちらついて見える場合があります。一定時間以上かかる場合だけ表示するなど、処理時間に応じて見せ方を調整します。
9.2 完了通知を適切な場所に表示する
保存完了のような短い通知は、画面下部や操作付近へ一時的に表示できます。一方、契約完了や支払い完了など重要な結果は、専用の完了画面や明確な確認領域を使う必要があります。
通知が短時間で消える場合でも、重要な内容を見逃さないようにします。取り消し可能な操作であれば、通知内に取り消し操作を設ける方法も有効です。
9.3 エラー発生後の行動を示す
エラー通知には、問題が起きた事実だけでなく、次に何をすべきかを含めます。通信エラーなら再試行、権限不足なら管理者への問い合わせ、入力エラーなら修正箇所への移動を提示します。
開発者向けの内部情報をそのまま表示してはいけません。利用者が理解できる表現へ変換し、必要に応じて問い合わせ用の識別番号だけを表示します。
9.4 空の状態を設計する
検索結果や登録データが存在しない場合、空白だけを表示すると不具合に見えることがあります。「該当する注文はありません」のような説明と、次に実行できる操作を表示します。
初回利用でデータがない状態と、検索結果がない状態では案内内容が異なります。初回利用では登録方法を案内し、検索結果がない場合は条件の変更や解除を提案します。
9.5 楽観的な更新を慎重に使う
処理完了を待たずに画面を更新すると、操作が速く感じられます。しかし、通信に失敗した場合は表示を元へ戻し、失敗したことを明確に伝えなければなりません。
「お気に入り」の切り替えなど、元に戻しやすい操作には適しています。一方、支払い、削除、在庫変更など影響の大きい操作では、処理完了を確認してから結果を表示する方が安全です。
実装例:通知領域を表示する
<div
id="notification"
class="notification"
role="status"
aria-live="polite"
hidden
>
<span id="notification-message"></span>
<button id="notification-action" type="button" hidden>
元に戻す
</button>
</div>
const notification = document.querySelector("#notification");
const notificationMessage =
document.querySelector("#notification-message");
let notificationTimer;
function showNotification(message, duration = 5000) {
clearTimeout(notificationTimer);
notificationMessage.textContent = message;
notification.hidden = false;
notificationTimer = setTimeout(() => {
notification.hidden = true;
}, duration);
}
showNotification("変更を保存しました。");
10. 動きと画面変化を設計する
画面上の動きは装飾のためだけではなく、要素の関係や状態変化を伝えるために使います。表示場所の変化、領域の開閉、処理完了を自然につなぐことで、利用者が何が起きたか理解しやすくなります。
10.1 動きの目的を明確にする
動きを追加する前に、何を伝えるための動きかを決めます。ボタンを押した反応、一覧への項目追加、領域の展開など、操作と結果の関係を示す場合に効果があります。
目的のない回転、拡大、跳ねる表現を多用すると、作業を妨げる可能性があります。特に業務用Webアプリでは、目立たせることよりも、状態変化を短時間で理解できることを優先します。
10.2 変化の時間を短く保つ
動きが長すぎると、利用者は完了を待たなければならず、反復作業の効率が低下します。小さな状態変化は短時間にし、画面全体の切り替えでも必要以上に長くしないようにします。
すべての動きに同じ時間を使う必要はありません。小さな色変化は短く、広い領域の開閉は少し長くするなど、移動距離や変化量に応じて調整します。
10.3 開始点と終了点を自然につなぐ
詳細画面が突然別の場所から現れると、元の項目との関係が分かりにくくなります。選択したカードから詳細領域へ視線が移るように、位置や大きさの変化を連続させると理解しやすくなります。
ただし、複雑な変形を実装すると性能や保守性へ影響します。利用者が関係を理解できる範囲で、透明度や移動量を使った簡潔な表現を選びます。
10.4 動きを減らす設定へ対応する
画面の移動や拡大縮小によって、不快感を覚える利用者もいます。端末側で動きを減らす設定が有効になっている場合は、不要な動きを停止または短縮します。
情報を動きだけで伝えてはいけません。動きを無効にしても、色、文字、配置によって同じ状態変化を理解できるようにします。
10.5 性能を損なわない動きを選ぶ
大きさや位置を頻繁に再計算する動きは、画面の描画負荷を高める場合があります。可能な範囲で透明度や変形を利用し、滑らかな表示を保ちます。
多数の要素を同時に動かすと、端末性能によっては操作が重くなります。実機で確認し、必要な要素だけに動きを限定することが重要です。
実装例:動きを減らす設定に対応する
.expand-panel {
opacity: 0;
transform: translateY(-0.5rem);
transition:
opacity 180ms ease,
transform 180ms ease;
}
.expand-panel[data-open="true"] {
opacity: 1;
transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
scroll-behavior: auto !important;
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
11. 端末幅に応じて表示を最適化する
Webアプリは、スマートフォン、タブレット、ノートパソコン、大型画面など、異なる表示環境で利用されます。単に幅を縮めるのではなく、利用可能な領域に合わせて情報量、配置、操作方法を調整します。
11.1 内容を基準に切り替え位置を決める
端末名だけを基準に表示切り替え位置を決めると、中間的な幅でレイアウトが崩れる場合があります。要素が窮屈になる幅や、文章が読みにくくなる幅を確認し、内容に合わせて切り替えます。
画面幅を少しずつ変化させながら確認すると、想定外の崩れを発見できます。特定の端末だけでなく、最小幅から最大幅まで連続的に検証することが重要です。
11.2 狭い画面では優先順位を見直す
広い画面で横並びにしていた補助情報は、狭い画面では下へ移動したり、初期状態で折りたたんだりできます。ただし、重要な操作や状態まで隠すと使いにくくなります。
表示領域が狭いほど、主要情報と主要操作を先に配置する必要があります。詳細情報を省略する場合も、利用者が必要に応じて確認できる導線を残します。
11.3 操作領域を十分な大きさにする
スマートフォンでは、マウスよりも指による操作が中心になります。小さな記号を密集させると誤操作が増えるため、操作領域と要素間の間隔を十分に確保します。
見た目の記号が小さくても、押せる範囲を広く設定することは可能です。ただし、隣接する操作領域が重ならないようにし、どこを押せば反応するか視覚的にも分かる形にします。
11.4 横長の一覧表を再構成する
多くの列を持つ一覧表は、狭い画面へそのまま縮小すると読めなくなります。重要な列だけを表示し、詳細は行の展開や別画面で確認できるようにします。
横方向への移動を使う場合は、移動できることを明確に伝えます。固定列を利用して対象名を常に表示すると、数値や状態を比較しやすくなります。
11.5 画面幅だけに依存しない
部品が配置される領域の幅は、画面全体の幅と一致しない場合があります。左側ナビゲーションや補助領域があると、同じ画面幅でも本文領域は狭くなります。
可能な場合は、部品が置かれた領域の幅に応じて表示を変更する方法を利用します。これにより、同じ部品を異なる場所へ配置しても、利用可能な幅に合わせて自然に変化できます。
実装例:幅に応じて配置を変更する
.dashboard-layout {
display: grid;
grid-template-columns: 16rem minmax(0, 1fr);
min-height: 100vh;
}
.card-list {
display: grid;
grid-template-columns:
repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
gap: var(--space-5);
}
@media (max-width: 48rem) {
.dashboard-layout {
grid-template-columns: 1fr;
}
.side-navigation {
position: fixed;
inset-inline: 0;
inset-block-end: 0;
}
}
12. アクセシビリティを設計へ組み込む
アクセシビリティは、完成後に追加する機能ではなく、情報構造、配色、操作方法、部品設計へ最初から組み込む必要があります。多様な利用環境を想定することで、結果としてすべての利用者にとって分かりやすいWebアプリになります。
12.1 キーボードだけで操作できるようにする
マウスを使えない環境でも、主要機能へ移動し、入力し、送信できる必要があります。操作可能な要素には自然な順序でキーボード選択が移動し、現在位置が明確に表示されるようにします。
見た目を整えるために選択時の輪郭線を削除してはいけません。独自の輪郭線へ変更する場合でも、背景との明度差と十分な太さを確保します。
12.2 意味のあるHTML要素を使う
クリック可能な領域をすべてdivで作ると、キーボード操作や読み上げ機能へ適切な役割が伝わりません。操作にはbutton、移動にはa、入力項目名にはlabelを使うことが基本です。
標準要素には、操作方法や状態伝達の仕組みがあらかじめ備わっています。独自部品が必要な場合でも、標準要素で実現できないか最初に検討します。
12.3 文字と背景の明度差を確保する
薄い灰色の文字は洗練されて見える場合がありますが、背景との差が小さいと読みづらくなります。本文、補足、無効状態など、用途ごとに読みやすさを確認します。
無効状態を薄くしすぎると、項目自体が存在しないように見える場合があります。操作できない理由を説明し、必要に応じて有効化の条件を案内します。
12.4 画像と記号に説明を付ける
内容を伝える画像には、同等の情報を文章として設定します。装飾目的の画像は読み上げ対象から除外し、不要な説明が繰り返されないようにします。
記号だけのボタンには、操作内容が分かる名前を設定します。鉛筆の記号に「編集」、ごみ箱の記号に「注文を削除」など、対象を含めた具体的な名前を付けると理解しやすくなります。
12.5 モーダル画面の操作を制御する
モーダル画面を開いたときは、キーボード選択をモーダル内部へ移動し、背後の要素へ移動しないようにします。閉じた後は、開くために使用したボタンへ選択を戻します。
閉じるボタン、Escapeキー、背景選択など、どの方法で閉じられるかを決めます。重要な入力内容を含む場合は、誤って背景を押しただけで閉じないようにする判断も必要です。
実装例:標準ダイアログを使用する
<button id="delete-open" type="button">
注文を削除
</button>
<dialog id="delete-dialog" aria-labelledby="delete-title">
<form method="dialog">
<h2 id="delete-title">注文を削除しますか</h2>
<p>削除した注文は元に戻せません。</p>
<div class="dialog-actions">
<button value="cancel">キャンセル</button>
<button value="confirm" class="button-danger">
削除する
</button>
</div>
</form>
</dialog>
const openButton = document.querySelector("#delete-open");
const deleteDialog = document.querySelector("#delete-dialog");
openButton.addEventListener("click", () => {
deleteDialog.showModal();
});
deleteDialog.addEventListener("close", () => {
openButton.focus();
if (deleteDialog.returnValue === "confirm") {
deleteOrder();
}
});
13. Material Designと他の設計方法の違い
Material Designを採用するか判断するには、独自デザイン、簡素な部品集、端末固有の設計方法との違いを理解する必要があります。優劣だけで決めるのではなく、開発規模、利用者、ブランド要件、運用体制に合わせて選択します。
13.1 独自デザインとの違い
独自デザインでは、ブランドの世界観や独自の操作体験を細部まで表現できます。一方、部品の状態、余白、入力規則などを一から決める必要があり、設計と検証の負担が大きくなります。
Material Designでは、共通部品や状態表現の考え方を利用できるため、設計判断を効率化できます。ただし、そのまま適用すると他サービスと似た印象になる可能性があるため、色、文字、形、写真表現で独自性を調整します。
13.2 簡素な部品集との違い
簡素な部品集は、ボタンや入力欄の見た目を素早く整える用途に適しています。しかし、画面全体の情報階層、動き、状態表現、利用規則まで定義されていない場合があります。
Material Designは、個別部品だけでなく、色、文字、配置、操作結果を一貫させるための考え方を含みます。そのため、画面数が多く、複数人で継続的に開発するWebアプリに適しています。
13.3 端末固有の設計との違い
端末固有の設計方法は、その端末を使い慣れた利用者にとって自然な操作を提供できます。一方、複数の端末やブラウザへ同じWebアプリを提供する場合、端末ごとに大きく設計を変えると運用負担が増えます。
Material Designを共通の基盤として使いながら、戻る操作、入力方法、画面幅などを端末環境に合わせて調整する方法が現実的です。完全に同じ見た目へ固定するのではなく、操作環境に応じた柔軟性を残します。
13.4 主な違いを比較する
設計方法を比較するときは、見た目だけでなく、開発速度、一貫性、独自性、学習負担、保守性を確認する必要があります。短期的な制作速度だけで選ぶと、画面数が増えた段階で修正負担が大きくなる場合があります。
以下の表は一般的な傾向を示したものです。実際の結果は、担当者の経験、既存資産、利用する開発環境、部品管理方法によって変わります。
| 比較項目 | Material Design | 独自デザイン | 簡素な部品集 |
|---|---|---|---|
| 導入速度 | 共通規則を利用しやすく比較的速い | 初期設計に時間がかかる | 見た目だけなら速い |
| 画面間の一貫性 | 維持しやすい | 規則整備の品質に左右される | 部品外の領域で崩れやすい |
| ブランド独自性 | 調整しないと弱くなりやすい | 高く表現できる | 中程度 |
| 状態表現 | 体系化しやすい | 個別に定義する必要がある | 不足する場合がある |
| 保守性 | 共通部品化すれば高い | 設計規則次第 | 規模拡大時にばらつきやすい |
| 学習負担 | 規則全体の理解が必要 | 独自規則の共有が必要 | 初期負担は比較的小さい |
| 大規模開発 | 適している | 十分な体制があれば可能 | 規則追加が必要になりやすい |
13.5 採用を判断する基準
複数画面を複数人で開発し、長期的に機能を追加するWebアプリでは、Material Designの体系性が役立ちます。管理画面、予約管理、顧客管理、学習管理など、共通操作が多いサービスと相性があります。
一方、ブランド表現を最優先する特設サイトや、極めて独自性の高い操作を提供するサービスでは、そのまま採用しない方がよい場合があります。すべてを適用するのではなく、状態設計やアクセシビリティの考え方だけを取り入れる選択も可能です。
14. HTML・CSS・JavaScriptへ実装する
設計した規則は、再利用可能なHTML、CSS、JavaScriptへ落とし込む必要があります。画面ごとに同じコードを複製するのではなく、役割別の部品と共通変数を作り、変更の影響範囲を管理します。
14.1 HTMLと見た目の責務を分ける
HTMLには情報構造と操作の意味を持たせ、見た目の指定はCSSへ分離します。HTML内へ大量の直接指定を記述すると、テーマ変更や端末対応が難しくなります。
部品名も、色や位置ではなく役割を表す名前にします。blue-buttonではなくprimary-actionに相当する名前を使うことで、色が変わっても意味を保てます。
14.2 CSSを役割別に整理する
CSSは、共通変数、初期化、配置、部品、補助指定などに分けて管理します。一つの巨大なファイルへ無秩序に追加すると、同じ指定の重複や上書きが増えます。
部品内部の指定が外部へ影響しないように、適切な命名と範囲を決めます。強い詳細度や!importantへ依存すると後から変更しにくくなるため、単純な指定を維持します。
14.3 JavaScriptは状態を中心に管理する
JavaScriptでは、表示そのものよりも、開閉、選択、通信中、成功、失敗といった状態を管理します。状態が複数の場所に分散すると、表示と内部データが一致しなくなる可能性があります。
一つの状態変更に対して、表示更新、属性変更、通知をまとめて実行できる構造にします。特に通信処理では、開始、成功、失敗、終了の各段階を明確に分けます。
14.4 共通部品へ設定値を渡す
同じ通知部品でも、成功、警告、エラーによって文言や見た目が変わります。用途ごとに別部品を複製するのではなく、種類、内容、操作を設定値として渡せる構造にします。
ただし、一つの部品へ多数の役割を詰め込みすぎると、条件分岐が複雑になります。見た目と操作が大きく異なる場合は、別部品として分けた方が保守しやすくなります。
14.5 実装規則を文書化する
共通部品の名前、利用条件、設定値、禁止事項を文書として残します。コードだけでは、なぜその設計になっているのか、新しい担当者が理解できない場合があります。
文書には、通常例、長い文言の例、エラー例、狭い画面の例を掲載します。変更履歴や廃止予定の部品も明示し、古い実装が新しい画面へ増えないようにします。
実装例:再利用可能な通知処理
class AppNotification {
constructor(element) {
this.element = element;
this.messageElement =
element.querySelector("[data-notification-message]");
this.timer = null;
}
show({ message, type = "info", duration = 5000 }) {
clearTimeout(this.timer);
this.messageElement.textContent = message;
this.element.dataset.type = type;
this.element.hidden = false;
this.timer = setTimeout(() => {
this.hide();
}, duration);
}
hide() {
clearTimeout(this.timer);
this.element.hidden = true;
}
}
const notification = new AppNotification(
document.querySelector("[data-notification]")
);
notification.show({
message: "プロフィールを更新しました。",
type: "success"
});
15. 性能・SEO・運用を改善する
Webアプリは公開時点で完成するものではなく、利用状況や機能追加に合わせて継続的に改善します。表示速度、検索エンジンへの情報伝達、部品の利用状況、不具合を確認し、設計規則そのものも更新します。
15.1 初期表示を軽量化する
最初の画面に不要な画像、書体、処理を読み込むと、操作可能になるまでの時間が長くなります。初期表示に必要な内容を優先し、詳細画面や補助機能の処理は必要になった時点で読み込みます。
Material Design風の表現を作るために、多数の外部資源や巨大な部品集を読み込む必要はありません。実際に使用する部品と機能を確認し、不要なコードを配信しないようにします。
15.2 画像と記号を最適化する
大きな画像を表示サイズのまま縮小して使うと、通信量が無駄になります。表示領域に合った画像寸法を準備し、適切な形式と圧縮率を選択します。
画面上の記号も、必要な種類だけを読み込みます。巨大な記号集を丸ごと配信するのではなく、使用する記号を限定することで初期表示を軽くできます。
15.3 検索エンジンへ内容を伝える
公開ページを持つWebアプリでは、ページごとに固有のタイトルと説明文を設定します。画面内容と関係のないキーワードを詰め込むのではなく、利用者が検索結果で内容を判断できる文章を作ります。
見出し構造、本文、内部リンクも重要です。見た目の都合で見出しを飛ばしたり、すべてをJavaScript実行後にしか表示できない構造にしたりすると、内容が伝わりにくくなる場合があります。
実装例:検索向けのメタ情報
<title>
Material DesignでWebアプリを設計する方法|画面設計と実装
</title>
<meta
name="description"
content="Material Designを活用したWebアプリの設計方法を、配色、文字、部品、フォーム、レスポンシブ対応、アクセシビリティ、実装例とともに解説します。"
>
<link
rel="canonical"
href="https://example.com/material-design-web-app"
>
15.4 利用状況を数値で確認する
改善では、担当者の印象だけでなく、入力完了率、エラー発生率、離脱位置、操作時間などを確認します。利用者が頻繁に戻る画面や、同じエラーが繰り返される項目には、設計上の問題がある可能性があります。
数値だけでは理由を判断できないため、利用者への聞き取りや操作観察も組み合わせます。完了率が低い場合でも、入力項目が難しいのか、説明が不足しているのか、通信が遅いのかによって対策は異なります。
15.5 定期的に部品を整理する
機能追加が続くと、似たボタン、古い入力欄、異なる通知方法が増えます。定期的に使用中の部品を確認し、重複を統合し、使われていない部品を廃止します。
廃止する部品は突然削除せず、代替部品と移行方法を明示します。既存画面を段階的に更新し、新規画面では古い部品を使わない規則を設けることで、安全に統一できます。
実装例:画像の遅延読み込み
<img
src="/images/dashboard-summary-640.webp"
srcset="
/images/dashboard-summary-640.webp 640w,
/images/dashboard-summary-1280.webp 1280w
"
sizes="(max-width: 48rem) 100vw, 50vw"
width="1280"
height="720"
loading="lazy"
decoding="async"
alt="売上概要画面の表示例"
>
おわりに
Material Designを使ったWebアプリ設計では、色や影を似せることよりも、情報の優先順位、部品の役割、状態変化、操作結果を一貫させることが重要です。利用者が画面を見た瞬間に現在地と次の操作を理解できれば、説明を増やさなくても使いやすいWebアプリを実現できます。
設計時には、情報構造、配色、文字、余白、共通部品、ナビゲーション、フォーム、通知、動き、端末対応、アクセシビリティを一つの仕組みとして整理します。実装後も、入力エラー、離脱、表示速度、利用頻度を確認し、実際の利用状況に合わせて改善を続ける必要があります。
最初からすべてを完璧に作るのではなく、利用頻度の高い部品と主要画面から共通化し、段階的に対象を広げる方法が現実的です。設計規則と実装部品を継続的に管理することで、機能が増えても統一感と操作性を維持できるWebアプリへ成長させられます。
EN
JP
KR