# 現在のステップを見た目だけで示すステップ表示

Source: https://easeweb.dev/learn/form-steps
Topics: フォーム > 複数ステップのフォームで、今どのステップかわかる (WCAG 1.3.1)
The fix: どのステップが現在で、どれが終わったかを、画面上だけでなくコードでも示します。現在のステップにaria-current="step"を、終わった各ステップに視覚的に隠した「完了」のテキストを付け、同じ目印から見た目を設定するか、ステップの見出しに「ステップ2（全4）：配送」のように番号とステップを書きます。見出しだけで足りるのは、ステップを必ず順に進む場合に限られます。
Test with: screen reader, keyboard, forced colors
References: https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships.html https://www.w3.org/WAI/WCAG22/Understanding/headings-and-labels.html https://www.w3.org/WAI/tutorials/forms/multi-page/ https://www.w3.org/TR/wai-aria-1.2/#aria-current https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current https://www.w3.org/WAI/WCAG22/Techniques/general/G130

よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。

## 場面

あるショップのチェックアウトは、「購入手続き」という一つの見出しの下に、カート、配送、支払い、確認の四つのステップとしてデザインされています。各ステップは番号の入った円で、線で次の円とつながっています。ページは落ち着いたまま、進み具合がひと目で分かるデザインです。今いるステップは青く塗りつぶした円で名前が太字、終わったステップにはチェックが付き、これからのステップは灰色の輪郭だけです。配送のステップにいる買い物客は、半分まで来たことがすぐに分かります。

同じページをスクリーンリーダーで読むと、「購入手続き、見出し」の後にリストが続きます。「カート、リンク」「2 配送」「3 支払い」「4 確認」。今いるのが配送だとも、カートが終わったとも伝わりません。チェックは描かれているだけで、言葉になっていません。見出しはどのステップでも「購入手続き」なので、そこからも分かりません。利用者は入力欄まで読み進めて今の場所を知り、再読み込みや戻る操作の後には、またそれを繰り返します。

## 確認できる問題

ステップ表示は関係を示しています。このステップが現在のもの、これらは終わったもの、これらはこれからのもの、という関係です。WCAG 1.3.1「情報及び関係性」は、見た目で示した情報をコードかテキストでも伝えることを求めています。この例では、その情報が見た目にしかありません。塗りは `current` クラス、チェックは `done` クラスによるもので、クラス名はブラウザーにとって意味がないため、支援技術に伝わるものがありません。チェック自体もスクリーンリーダーから隠したアイコンで、代わりの言葉がありません。

見出しは基準を満たしています。WCAG 2.4.6「見出し及びラベル」は、見出しが主題や目的を説明していることを求めており、「購入手続き」はページを説明しています。ステップ番号までは求めていません。それでも、見出しでステップを示すのは、今どこにいるかを誰にでも伝える最も分かりやすい方法です。そのため修正の一つにしています。現在のステップをテキストで示すので、1.3.1が求めることを満たします。

見た目そのものは基準を満たしています。現在のステップは塗りつぶした円と太字の名前で示しており、色の変化だけに頼っていないため、1.4.1「色の使用」を満たします。どの円の枠線も白いページに対して3:1以上のコントラストがあり（これからのステップは3.03:1、ほかは6.84:1）、チェックは淡い塗りに対して5.49:1で、1.4.11「非テキストのコントラスト」の求めるとおりです。ステップをコードで示すことは、達成方法ARIA26にも当たります。これは、一連のページの中で今どこにいるかが分かることを求めるレベルAAAの達成基準2.4.8「現在位置」の十分な達成方法です。

## 利用者への影響

ステップに分かれたチェックアウト、会員登録、申し込み、予約は、どれもこうした表示を使います。マークアップより見た目のほうが多様で、線でつないだ円、番号付きのタブ、山括弧でつないだ言葉の列などがあります。どう描いても、現在のステップがスタイルだけなら、そのスタイルが見えない人は今の場所を見失います。

## 自動チェックとAIの限界

自動チェックは、短いテキストの正しい順序付きリストとして合格にします。`current`、`active`、`is-complete` といったクラス名には意味がないため、一つの項目が現在のものとして描かれていることは分かりません。ステップが変わったときに目印が移るかも確認できません。EaseWebの診断は、クラスや名前でステップと示されたリストのうち、一つの項目に `current` や `active` のようなクラスがあり、ほかと違って描かれ、`aria-current` も隠したテキストもないものを、ページの見出しもページタイトルもステップを示していない場合に問題として報告します。ほかの項目と違って描かれているのにコードに理由のないステップのリストや、見出しかページタイトルがステップを示すページにある目印のないリストは、人が確認する項目として送ります。AIによるコード生成では、現在のステップに `aria-selected="true"` や `role="tab"` を付けることがあります。これらはタブやリストボックスのためのもので、リストの項目では無視されるか誤って伝わります。表示を `role="progressbar"` に変え、値の2が「2パーセント」と読まれる例もあります。二つの別のステップで表示を聞いて確かめてください。

## 修正前：クラスだけで描いた現在のステップ

```html
<h1>Checkout</h1>
<ol class="steps" role="list">
  <li class="done">
    <a href="/checkout/cart">
      <span class="mark"><svg aria-hidden="true" viewBox="0 0 16 16">…</svg></span>
      Cart
    </a>
  </li>
  <li class="current">
    <span class="mark">2</span>
    Delivery
  </li>
  <li>
    <span class="mark">3</span>
    Payment
  </li>
  <li>
    <span class="mark">4</span>
    Review
  </li>
</ol>
```

```css
.steps {
  display: flex;
  gap: 1.5rem;
  list-style: none;
  padding: 0;
}
.steps .mark {
  border: 2px solid #8796a5;
  border-radius: 50%;
  color: #5b6670;
}
.steps .done .mark {
  border-color: #1f5f8b;
  background: #dbe8f2;
  color: #1f5f8b;
}
.steps .current .mark {
  border-color: #1f5f8b;
  background: #1f5f8b;
  color: #fff;
}
.steps .current {
  font-weight: 700;
}
```

`current` と `done` のクラスは、ステップの見た目を変えるだけです。スクリーンリーダーは「2 Delivery」を「3 Payment」とまったく同じように読み、終わったステップも「Cart、リンク」と読みます。チェックは隠されていて、言葉がないからです。

## 修正後：現在のステップにaria-current、終わったステップに隠したテキスト

```html
<h1>Checkout</h1>
<ol class="steps" role="list">
  <li class="done">
    <a href="/checkout/cart">
      <span class="mark"><svg aria-hidden="true" viewBox="0 0 16 16">…</svg></span>
      Cart<span class="visually-hidden">, completed</span>
    </a>
  </li>
  <li aria-current="step">
    <span class="mark">2</span>
    Delivery
  </li>
  <li>
    <span class="mark">3</span>
    Payment
  </li>
  <li>
    <span class="mark">4</span>
    Review
  </li>
</ol>
```

```css
.steps {
  display: flex;
  gap: 1.5rem;
  list-style: none;
  padding: 0;
}
.steps .mark {
  border: 2px solid #8796a5;
  border-radius: 50%;
  color: #5b6670;
}
.steps .done .mark {
  border-color: #1f5f8b;
  background: #dbe8f2;
  color: #1f5f8b;
}
.steps [aria-current="step"] .mark {
  border-color: #1f5f8b;
  background: #1f5f8b;
  color: #fff;
}
.steps [aria-current="step"] {
  font-weight: 700;
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
```

`aria-current="step"` は、この項目が手続きの中の現在のステップだと支援技術に伝え、対応するスクリーンリーダーは現在のステップだと読み上げます。スタイルも属性で選ぶため、見た目とコードが一つの目印から決まり、別々のステップを示すことがありません。ARIAには終わったステップを表す状態がないため、チェックの意味はリンクの中の隠したテキストで伝えます。「Cart, completed、リンク」と読まれます。このテキストは `done` クラスを付けるのと同じテンプレートの条件で書き、ページのほかの部分と一緒に翻訳してください。デザインは変わりません。円も塗りもチェックも、描いたとおりです。

## 修正後：ステップを見出しに書く

```html
<h1><span class="step-count">Step 2 of 4</span> Delivery</h1>
<ol class="steps" role="list">
  <li class="done">
    <a href="/checkout/cart">
      <span class="mark"><svg aria-hidden="true" viewBox="0 0 16 16">…</svg></span>
      Cart
    </a>
  </li>
  <li class="current">
    <span class="mark">2</span>
    Delivery
  </li>
  <li>
    <span class="mark">3</span>
    Payment
  </li>
  <li>
    <span class="mark">4</span>
    Review
  </li>
</ol>
```

```css
.steps {
  display: flex;
  gap: 1.5rem;
  list-style: none;
  padding: 0;
}
.steps .mark {
  border: 2px solid #8796a5;
  border-radius: 50%;
  color: #5b6670;
}
.steps .done .mark {
  border-color: #1f5f8b;
  background: #dbe8f2;
  color: #1f5f8b;
}
.steps .current .mark {
  border-color: #1f5f8b;
  background: #1f5f8b;
  color: #fff;
}
.steps .current {
  font-weight: 700;
}
.step-count {
  display: block;
  color: #5b6670;
  font-size: 0.875rem;
  font-weight: 600;
}
```

こちらは普段の見た目が変わります。見出しは「Checkout」ではなくステップの名前になり、その上の小さな灰色の行が番号を示します。ページが「Step 2 of 4、Delivery」と言葉で伝えるため、ステップ表示が見えるかどうかに関係なく、誰にでも読めます。スクリーンリーダーは見出しを「Step 2 of 4 Delivery」と読み、見出しで移動する人は最初にこれを聞きます。ステップ表示自体は修正前のままで、どれが現在で、どれが終わったかは伝えません。これで足りるのは、ステップを必ず順に進む場合だけです。4ステップ中の2なら、ステップ1が終わったものでなければなりません。ステップを飛ばせる場合や、途中で離れたステップに戻れる場合は、リストにも目印が必要です。

## どの方法を選ぶか

どちらも今どのステップかを伝えます。終わったステップに隠したテキストを付けたうえで `aria-current="step"` を使ってください。表示そのものを直し、デザインを描いたとおりに保ち、同じ目印から見た目を設定します。見出しだけの方法は、ステップを必ず順に進む間しか満たしません。それでも、見出しのステップは併せて加える価値があります。入力欄を見ている拡大鏡の利用者のように表示を目にしない人や、数を平易な言葉で知りたい人の助けになり、デザイナーにとっては見出しの上に小さな文字を1行足すだけです。

## 実装の判断

ステップ表示とその周りのページでは、さらに判断が必要です。

- 番号のないリスト：SafariのVoiceOverでは、CSSで番号や行頭記号を消したリストからリストの役割が外れ、「リスト、4項目」と読まれないことがあります。`ol` に `role="list"` を付けて保ちます。
- 終わったステップのリンク：W3Cの複数ページのフォームのチュートリアルは、終わったステップへリンクして見直せるようにすることを勧めています。隠した「完了」のテキストはリンクの中に置き、リンク名の一部にします。これからのステップは、何も起きないリンクにせず、ただのテキストにします。
- 現在のステップにも隠したテキスト：属性は付けられずテキストなら加えられるコンポーネントでは、現在の項目の中に「、現在のステップ」を隠したテキストとして書きます。チュートリアルも、名前の前に「Current: 」を隠して置いています。クラスと同じ条件で設定し、翻訳します。
- シングルページのチェックアウト：「次へ」でページを読み込まずにステップを入れ替えるなら、ルーターが `aria-current` とフォーカスを一緒に移す必要があります。[読み上げられないSPAの画面遷移](/ja/learn/route-changes)を参照してください。切り替えが読み上げられないと、スクリーンリーダー利用者は、別のステップのものになったボタンの上に残されます。
- ページタイトル：「Step 2 of 4: Delivery – Checkout」のようにページのタイトルにステップを入れると、ページを読み込んだ直後にスクリーンリーダー利用者へ今の場所が伝わります。これは2.4.2「ページタイトル」の範囲で、[すべてのページで同じページタイトル](/ja/learn/page-title)で扱っています。
- 円ではなくバー：ステップを示すプログレスバーには `aria-valuetext="Step 2 of 4: Delivery"` が必要です。ないと値がパーセントとして読まれます。[スクリーンリーダーで読めないプログレスバーとメーター](/ja/learn/progress-bars)を参照してください。

強制配色でも現在のステップが見えるようにします。Windowsのコントラスト テーマは円の塗りをテーマの色に置き換えるため、塗りつぶした円がほかと同じに見えることがあります。太字の名前と枠線は残ります。現在のステップは太字の名前や太い輪など、塗り以外でも描き、コントラスト テーマで確かめてください。スマートフォンでは、表示を「ステップ2（全4）」という言葉に縮めるデザインがよくあり、これは満たします。点だけに縮めると満たしません。

## 修正の確認

1. コードかブラウザーの検証ツールで現在のステップを探し、`aria-current="step"` か中に隠したテキストがあること、またはステップの見出しが番号付きでステップを示していること、見た目が同じステップの値から設定されていることを確認する。
2. スクリーンリーダーでステップ表示を先頭から読み、現在のステップが現在のものとして読まれるか、見出しがどのステップかを伝えるか、終わったステップがこれからのステップと同じようには読まれないかを確認する。
3. 「次へ」と「戻る」、続いてブラウザーの戻るボタンを押し、見た目、目印、見出しがすべて新しいステップへ移ったか確認する。
4. 再読み込みやリンクから、初めて来た人のようにステップに着き、最初の入力欄より前に、ページがどのステップで全部でいくつかを伝えるか確認する。
5. Windowsのコントラスト テーマなどの強制配色をオンにし、現在のステップがほかと見分けられるか確認する。

OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。チェックアウトのステップやステップのコンポーネントを変更した際は、再度確認します。

## 制限

このサンプルは、どの手続きでも同じ結果になることを保証するものではありません。`aria-current` の読み上げ方はスクリーンリーダーによって異なり、名前の前に読むものも後に読むものもあります。対応もスクリーンリーダーとブラウザーの組み合わせで差があるため、利用者が使うもので試してください。正しいステップに目印があっても、手続き自体が分かりにくかったり、同じ情報を二度求めたりすれば、人は迷います。[同じ住所を二度入力させるチェックアウトフォーム](/ja/learn/redundant-entry)を参照してください。メニューの現在のページのリンクも、同じ属性を別の値で使います。[現在のページを見た目だけで示すナビゲーション](/ja/learn/current-page)を参照してください。

---

このガイドをコーディングエージェントで使う: MCP https://easeweb.dev/mcp（設定は https://easeweb.dev/ja/services/developers）
