# 取り消し線だけで示す元の価格と削除した語

Source: https://easeweb.dev/learn/struck-through-prices
Topics: ページの構造 > 取り消し線、追加、強調表示のテキストが、その意味を伝える (WCAG 1.3.1)
The fix: 価格のそばに言葉を書きます。ページに表示する（「通常価格 40ドル、セール価格 28ドル」）か、デザインを保ったまま視覚的に隠したテキストにします。元の価格をsでマークすれば意味は支援技術にも伝わりますが、それだけでは、削除されたテキストだと読み上げるスクリーンリーダーでしか分かりません。
Test with: screen reader, styles off
References: https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships.html https://www.w3.org/WAI/WCAG22/Techniques/failures/F2 https://www.w3.org/WAI/WCAG22/Techniques/general/G117 https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-s-element https://www.w3.org/TR/html-aam-1.0/

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

## 場面

あるショップの商品一覧で、リネンのトートがセール中です。商品名の下には、取り消し線の入った小さな灰色の40ドルと、太字の28ドルが並んでいます。カードを見れば、40ドルだったトートが今は28ドルだと、すぐに分かります。

スクリーンリーダーで一覧を読んでいくと、「リネンのトート、40ドル、28ドル」と聞こえます。40ドルの取り消し線はCSSで描いたもので、テキストには含まれないため、二つの価格は同じように読まれます。次のホーローのマグは「ホーローのマグ、18ドル」なので、最初のカードは、ただ価格が二つある商品に聞こえます。どちらが適用されるかは、推測するか、かごに入れてみるまで分かりません。

## 確認できる問題

達成基準1.3.1「情報及び関係性」はレベルAです。見せ方で伝えている情報（ここでは、どちらが元の価格か）は、コードからも判別できるか、テキストでも得られなければなりません。W3Cの失敗例F2は、まさにこの状態を示しています。文字の見せ方の変化が意味を持つのに、それを伝えるマークアップもテキストもない状態です。

取り消し線はCSSのテキスト装飾で、マークアップではありません。Chromiumのアクセシビリティツリーでは、`text-decoration: line-through`を付けた「40ドル」のspanは、隣の「28ドル」と同じただのテキストです。線は太字と同じく文字の書式として伝わるだけで、たとえばNVDAは、初期設定では取り消し線などのフォント属性を読み上げません。スクリーンリーダーは、渡されたものしか読めません。W3Cの十分な達成方法G117は、同じ情報をテキストでも伝える方法で、ここで示す最初の二つの修正がこれにあたります。

## 利用者への影響

オンラインで買い物をする人は、かごの中だけでなく、一覧ページで価格を比べます。セール価格が商品カードにしか出ていないなら、その違いはカードで聞き取れなければなりません。

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

HTMLは正しく、元の価格に使った灰色もコントラストが足りています。axeには、テキスト装飾を調べるルールがありません。EaseWebの診断（`ew:struck-price-not-marked`）は、CSSだけで取り消し線を引いた価格を探し、元の価格だと示す言葉が、表示でも非表示でも周りにないものを報告します。価格は通貨で見分けるため、取り消し線を引いたToDoの項目は対象外です。太字、色、マーカーなど、ほかの見せ方が言葉を必要とする意味を持つかどうかは判断できません。

## 修正前：CSSで元の価格に取り消し線を引く

```html
<li class="product">
  <img src="linen-tote.jpg" alt="">
  <h3>リネンのトート</h3>
  <p class="price">
    <span class="old">40ドル</span>
    <span class="now">28ドル</span>
  </p>
</li>
```

```css
.price .old {
  color: #6b6f7b;
  text-decoration: line-through;
}
```

線はCSSにしかないため、価格のテキストは「40ドル 28ドル」です。マークアップにも言葉にも、どちらが元の価格かを示すものはありません。

## 修正後：通常価格とセール価格をページに書く

```html
<li class="product">
  <img src="linen-tote.jpg" alt="">
  <h3>リネンのトート</h3>
  <p class="price">
    通常価格 <span class="old">40ドル</span>
    セール価格 <span class="now">28ドル</span>
  </p>
</li>
```

```css
.price .old {
  color: #6b6f7b;
  text-decoration: line-through;
}
```

短い言葉が、線と同じことを伝えます。スクリーンリーダーは「通常価格 40ドル、セール価格 28ドル」と読み、読み上げツールも同じように読みます。線の意味を知らない人も、見て分かります。線は残るため、カードの見た目はほとんど変わりません。

## 修正後：デザインを保つ、視覚的に隠した言葉

```html
<li class="product">
  <img src="linen-tote.jpg" alt="">
  <h3>リネンのトート</h3>
  <p class="price">
    <span class="visually-hidden">通常価格</span>
    <span class="old">40ドル</span>
    <span class="visually-hidden">、セール価格</span>
    <span class="now">28ドル</span>
  </p>
</li>
```

```css
.price .old {
  color: #6b6f7b;
  text-decoration: line-through;
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
```

カードはデザインどおりのまま、言葉がテキストに入るため、スクリーンリーダーは「通常価格 40ドル、セール価格 28ドル」と読みます。このクラスは、何も描かずに言葉をアクセシビリティツリーに残します。`display: none`や`aria-hidden`では、スクリーンリーダーからも隠れてしまいます。画面を見て買い物をする人のうち、線の意味を知らない人には、これまでどおり線しか届きません。

## 修正後：デザインに言葉を入れられないときはs要素

```html
<li class="product">
  <img src="linen-tote.jpg" alt="">
  <h3>リネンのトート</h3>
  <p class="price">
    <s class="old">40ドル</s>
    <span class="now">28ドル</span>
  </p>
</li>
```

```css
.price .old {
  color: #6b6f7b;
  text-decoration: line-through;
}
```

HTMLの`s`要素は、元の価格のように、もう正しくないテキストを表します。Chromiumは`s`を`deletion`ロールとして支援技術に伝えます。意味が見た目だけでなく、マークアップにも入ったことになります。ただし、削除されたテキストだと読み上げるかどうかは、スクリーンリーダーとその設定によります。読み上げない場合、カードはやはり「40ドル、28ドル」と読まれます。読み上げツールや、見て使う人の助けにもなりません。単独では使わず、言葉を加える修正と組み合わせてください。

## どの方法を選ぶか

三つとも、意味を見た目以外にも持たせます。表示する言葉を使ってください。短い言葉を二つ加えるだけで、線は見えてもその意味を知らない人を含め、すべての人に同じ情報が届きます。どうしてもデザインに言葉を入れられないときは、視覚的に隠した言葉を使います。スクリーンリーダーで聞く結果は同じです。どちらにも`s`を加えてかまいませんが、効果がスクリーンリーダー次第なので、`s`だけに頼らないでください。

## 実装の判断

もう正しくない価格には`s`を、変更履歴や書き換えの提案のような文書の編集には`del`と`ins`を使います。この二つは別のものです。`del`はテキストが削除されたことを、`s`はもう当てはまらないことを示します。変更履歴には、価格と同じ問題が二重にあります。読み上げると、削除した語と追加した語が続けて読まれてしまいます。変更箇所ごとに「削除：」「追加：」のような隠した言葉を入れます。「[確認も取り消しもできずに文章を書き換えるAIリライトボタン](/ja/learn/ai-rewrites)」のデザインの案にある、変更を示すサンプルがその例です。

言葉を`p`や`span`の`aria-label`に入れないでください。これらの要素には名前を付けられず、多くのスクリーンリーダーはそのラベルを読みません。「[読み上げられないことが多い、divやspanのaria-label](/ja/learn/aria-label-on-generic)」を参照してください。

カード全体が一つのリンクの場合、リンクの名前はその中のテキストから作られるため、価格も含まれます。言葉も名前の一部になり、「リネンのトート、通常価格 40ドル、セール価格 28ドル」となります。これが望ましい形です。

元の価格も読める濃さに保ちます。灰色にするなら4.5:1以上にします。白の上の#6b6f7bは5.02:1です。4.5:1を下回る灰色は、それ自体が別の基準を満たしません。「[ブランドカラーや写真の上でコントラストが足りない文字](/ja/learn/text-contrast)」を参照してください。

商品が多い一覧では、価格を一つのコンポーネントで表示し、毎回同じ言葉にします。そうすれば、スクリーンリーダーの利用者は同じパターンで聞けます。

## 修正の確認

1. セール中の商品をスクリーンリーダーで1行ずつ読み、次の商品に移る前に、どちらが通常価格でどちらがセール価格かが聞こえることを確認する。
2. スタイルを無効にするか、ブラウザーのリーダー表示で開き、元の価格と支払う価格が区別できることを確認する。
3. `s`や`del`を使う場合は、対応するスクリーンリーダーごとに初期設定のままで読み、それぞれが何と読み上げるかを記録する。

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

## 制限

このサンプルは、どのページでも同じ結果になることを保証するものではありません。例は元の価格ですが、検索結果の一致を示すマーカー、一つだけ大事な語を示す太字、問題を示す赤い文字など、見た目が意味を持つほかのテキストも同じです。言葉でも伝えてください。字下げのためだけに`blockquote`を使い、引用ではないのに引用として読み上げられる状態は、同じ基準の別の失敗（F43）で、ここでは扱いません。商品一覧、商品ページ、かごを、利用者が使う支援技術や道具で確認してください。

---

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