結論

プロは入力欄の「安っぽさ」を、状態フィードバックと寸法・余白を具体数値で固めることで消す。ラベルはフィールド外に上揃え常時表示し、フォーカスは色だけでなく太さ+box-shadowで多層化してWCAG 3:1を満たす。高さ40〜56px・font-size 16px以上・8pxグリッドの一定リズムで「整っている=高品質」を作り、エラーは色単独でなくアイコン+テキスト+ARIAで多重化する。

01 — ラベルはフィールド外・上揃えで常時表示する

プレースホルダーをラベル代わりにすると、入力を始めた瞬間に何の欄か分からなくなり、薄いグレーはコントラスト不足でスクリーンリーダーにも届かない。ラベルはフィールド直上(top-aligned)に常時置くのが正解だ。Penzoのアイトラッキングでは視線移動(サッカード)が上揃え約50msに対し左揃えは約500msと、上揃えが最も速い。ラベルは1〜2語・センテンスケース("名")で。

メールアドレス
✗ プレースホルダーがラベル代わり → 入力すると消える
メールアドレス
you@example.com
✓ ラベルを直上に常時表示、補助だけプレースホルダー
左揃えの落とし穴:ラベルとフィールドの間に大きな白を空けて左揃えにすると、視線移動が増えグルーピングが崩れて散漫に見える。横並びは極端に長いデスクトップフォームのみ検討する。

primaryPlaceholders in Form Fields Are Harmful — NN/g

blogLabel Placement in Forms — UXmatters

02 — フォーカスは色だけでなく太さ+box-shadowで多層化する

キーボードユーザーにとってフォーカスインジケータはマウスカーソルに相当する唯一の位置手がかりだ。outline:none を代替なしで消すと操作不能になり、見た目も雑になる。WCAG SC1.4.11はボーダーもフォーカスも隣接背景に3:1以上を要求し、SC2.4.13(AAA)はフォーカス領域に2 CSS px厚の周長以上を求める。outline 3px+box-shadow 6px(白ハロー、厚みはoutlineの2倍)+ボーダー色変更の三層が汎用パターン。

outline:none のまま
✗ フォーカスが消えて今どこを編集中か不明
3px outline + 6px halo
✓ outline+ハロー+ボーダー色の三層で確実に伝わる

blogA guide to designing accessible, WCAG-conformant focus indicators — Sara Soueidan

primaryUnderstanding SC 1.4.11: Non-text Contrast — W3C WAI

03 — 高さ・文字サイズ・余白を仕様値で固める

安っぽいフォームは入力欄の高さがバラバラで、ボタンとも揃わず縦のリズムが崩れている。高さは標準56px(密度高めで40〜48px)、入力/ラベル文字16px、font-sizeはmax(16px,1em)でiOS自動ズームを防ぐ。入力欄の高さは主ボタンの高さに揃え、フィールド間は最低16px。8pxグリッドの一定リズムこそが「整っている=高品質」の核だ。

28px
44px / 文字12px
✗ 高さも余白も不揃い、文字16px未満でiOSズーム
40px / 16px
40px / 16px
✓ 全高40px・間隔16px・ボタンも同高で揃う

primaryText fields — Components — Material Design

blogDesigning Form Layout: Spacing — SitePoint

04 — エラーは色+アイコン+テキスト+ARIAで多重化する

赤枠だけに頼ると、色覚多様性のユーザーに伝わらずWCAG非適合になる。aria-invalid="true"aria-describedby でエラー文を関連付け、動的注入には role="alert" を付ける。検証は送信時の一括ではなくchange/blur時にフィールド近傍へインライン表示し、入力済みの誤り値は保持して修正させる。エラー本文テキストは4.5:1(枠線の3:1より高い)を確保する。

taro@
✗ 赤枠だけ → 何が問題か・色が見えない人に伝わらない
taro@
有効なメールアドレスを入力してください
✓ 赤枠+アイコン+テキストの三重化、ARIAで関連付け

blogUltimate Guide to Accessible Form Design — UXPin

blogInput UI design: States, anatomy, and validation patterns — Setproduct

05 — 全状態を設計する(default/hover/focus/error/disabled)

安っぽいフォームは「のっぺり」していて、押せるのか・編集中なのかが分からない。プロはdefaultだけでなくhover/focus/filled/error/disabled/successまで明示的に色と太さを定義する。状態差が見えるだけで「作り込まれている」印象が一気に出る。disabledはWCAGコントラスト要件の対象外だが、視覚的に区別できるよう薄くする。

全部おなじ見た目
✗ 1状態しか作らず、反応が読めない
DEFAULT
通常
FOCUS
編集中
DISABLED
無効
✓ 各状態を色+太さで明示(focus/disabled等)

blogInput UI design: States, anatomy, and validation patterns — Setproduct

blogUI Designer's Guide to Creating Forms & Inputs — UI Prep

実装スニペット

ベースとなる入力欄(寸法・余白・iOSズーム防止)。

.field { display: flex; flex-direction: column; gap: 8px; }
.field label { font-size: 16px; line-height: 1.4; font-weight: 600; }
.input {
  box-sizing: border-box;
  width: 100%;
  min-height: 40px;            /* 主ボタン高さに揃える(8pxグリッド) */
  padding: 8px 12px;
  font-size: max(16px, 1em);   /* iOS自動ズーム防止 */
  line-height: 1.25;
  border: 2px solid #6b7280;   /* 隣接背景に3:1以上を確保 */
  border-radius: 4px;
  background: #fff;
  transition: border-color 180ms ease-in-out, box-shadow 180ms ease-in-out;
}
.input::placeholder { color: #6b7280; } /* ラベル代わりにはしない・補助のみ */
.field + .field { margin-top: 16px; }   /* フィールド間 最低16px */

フォーカス可視化(WCAG 1.4.11 / 2.4.13 準拠の多層)。:focus-visible でキーボード操作時のみ強いリングを出す。

.input:focus-visible {
  outline: 3px solid #1a1a1a;          /* 3px outline */
  outline-offset: 0;
  box-shadow: 0 0 0 6px #fff;          /* ハロー幅 = outlineの2倍 */
  border-color: #1d4ed8;               /* 色も変える(色のみに頼らない) */
}
/* outline:none は単独で使わない。使うなら必ず上記box-shadow等で代替 */

エラー状態(色のみに頼らない・ARIA前提)。

.input[aria-invalid="true"] {
  border-color: #b91c1c;               /* 赤枠(3:1以上) */
  border-width: 2px;
}
.error-text {
  display: flex; align-items: center; gap: 6px;
  margin-top: 8px;
  color: #b91c1c;                      /* テキストは4.5:1以上 */
  font-size: 12px; line-height: 1.4;
}
.error-text::before { content: "\26A0"; }  /* アイコンを併用 */

/* HTML:
<input class="input" aria-invalid="true" aria-describedby="email-err">
<p id="email-err" class="error-text" role="alert">有効なメールアドレスを入力してください</p>
*/

全状態の定義(default/hover/filled/disabled/success)。

.input:hover { border-color: #374151; }
.input:not(:placeholder-shown) { border-color: #374151; } /* filled */
.input:disabled {
  background: #f3f4f6; color: #9ca3af;
  border-color: #e5e7eb; cursor: not-allowed;
}
/* disabledはWCAGコントラスト要件の対象外。だが識別可能に薄める */
.input--success { border-color: #15803d; }

チェックリスト

  • ラベルをフィールド外・上揃えで常時表示し、プレースホルダーをラベル代わりにしていない
  • font-sizeは `max(16px, 1em)` 以上で、iOSフォーカス時の自動ズームを防いでいる
  • 入力欄の高さ(40〜56px)が主ボタンの高さに揃い、フィールド間は最低16px空いている
  • 余白が8pxグリッドの一定リズムで、単一カラムで下方向に流れている
  • `:focus-visible` で outline+box-shadow+ボーダー色の多層フォーカスを出し、隣接背景に3:1以上ある
  • `outline:none` を代替なしで使っていない
  • エラーを赤枠だけでなくアイコン+テキストで示し、本文は4.5:1を満たす
  • `aria-invalid` / `aria-describedby` を付与し、動的エラーに `role="alert"` を使っている
  • 検証はchange/blurでインライン表示し、誤り値は保持して修正させている
  • default/hover/focus/filled/error/disabledまで各状態を視覚的に定義している
  • 郵便番号・電話・カード番号など長さが決まる項目は幅を絞り、想定入力長を示している

限界 / 出典

注意:Penzoのアイトラッキング数値(約50ms / 約500ms)は2006年の小規模研究で、傾向(上揃えが最速)は他研究と整合するが絶対値は鵜呑みにしない。Material Designの具体寸法はm1(Material 1)のもので、Material 3では数値が更新されている——56px/16px等は出発点の目安として使う。フォーカスの汎用パターン(outline 3px+shadow 6px・黒/白)は背景色に依存するため、実配色で必ず3:1(テキストは4.5:1)を測定し直すこと。WCAG SC2.4.13(Focus Appearance)はAAAであり全案件で必須ではないが、満たすと品質が上がる。「指針準拠78%vs非準拠42%」はNN/g記事内の主張で母数・条件の詳細は限定的。font-size 16px以上のiOSズーム防止はSafari挙動依存で、将来のOS更新で変わる可能性がある。バナー内の擬似入力UIは見た目の寸法・余白原則のみ流用する。

primaryPlaceholders in Form Fields Are Harmful — NN/g

primaryWebsite Forms Usability: Top 10 Recommendations — NN/g

primaryUnderstanding SC 1.4.11: Non-text Contrast — W3C WAI

blogA guide to designing accessible, WCAG-conformant focus indicators — Sara Soueidan

primaryText fields — Components — Material Design

blogCustom CSS Styles for Form Inputs and Textareas — Modern CSS

blogUltimate Guide to Accessible Form Design — UXPin

blogInput UI design: States, anatomy, and validation patterns — Setproduct

blogLabel Placement in Forms — UXmatters

blogDesigning Form Layout: Spacing — SitePoint

blogUI Designer's Guide to Creating Forms & Inputs — UI Prep

blogThe Definitive Guide to Form Label Positioning — SitePoint