Content Descriptionは、非テキストコンテンツのテキストによる説明を支援技術に伝えるアクセシビリティプロパティです。iOSではUIViewのaccessibilityHint属性、AndroidではXMLマークアップ内のcontentDescriptionです。W3C WCAG 2.2、2023によると、非テキストコンテンツに対するテキスト代替の欠如は、モバイルアプリケーションにおける最も一般的なアクセシビリティ違反の1つです。適切に入力された説明は、VoiceOverやTalkBackを使用する視覚障害者にとってアプリをアクセシブルにします。
重要なポイント
Content Descriptionは、視覚コンテンツのテキスト表現を支援技術に提供するUI要素の文字列プロパティです。スクリーンリーダー(iOSのVoiceOver、AndroidのTalkBack)は、要素を視覚的に認識しようとする代わりに、説明を音声で読み上げます。説明は、テキストレイヤーのない画像、アイコン、グラフ、カスタムコントロール、および非テキスト要素に適用されます。
Google Material Design、2024によると、contentDescriptionのない要素はWCAG 1.1.1(Non-text Content)に違反します。Accessibility Scannerのチェックでは、ショッピングアプリのアイコンの最大40%に説明がありません。VoiceOverユーザーは、具体的な情報なしに「画像」または「ボタン」としか聞こえず、そのようなインターフェースはナビゲーションに使用できなくなります。
Content Descriptionは、要素の表示テキストを置き換えるものではありません。ボタンに「送信」というテキストラベルが含まれている場合、追加の説明を設定する必要はありません。スクリーンリーダーがテキストを読み上げます。画像、アイコン、入力フィールドについては、説明が必須です。
Accessibility Scanner(Android)およびXcode Accessibility Inspector(iOS)ツールは、自動的に説明の存在をチェックします。リリース前にすべての画面でこれらのチェックを実行することを推奨します。
視覚障害のあるユーザーは、インターフェースを理解するためにVoiceOverに依存しています。ショッピングカートのアイコンに説明がない場合、彼らは「ボタン」としか聞こえません。ボタンの機能を知るためには、目をつぶってタップするしかなく、取り返しのつかないアクションのリスクがあります。「カートからアイテムを削除」のような説明は、1秒でこの問題を解決します。
一時的な制約のあるユーザー(屋外の強い日差し、割れた画面)もVoiceOverを使用します。Apple Accessibility Report、2023によると、VoiceOverユーザーの約20%は永続的な視覚障害がなく、状況に応じて機能をオンにしています。
WCAG 1.1.1(レベルA)は、すべての非テキストコンテンツにテキストによる代替を提供することを要求しています。例外:装飾目的のみで使用され、情報を伝えない視覚的プレゼンテーションのコンテンツ。装飾性のテスト:要素を削除した場合、ページの意味は変わりますか?変わらない場合は、スクリーンリーダーから非表示にできます。
Accessibility Label(iOSのaccessibilityLabel)は、フォーカス時にスクリーンリーダーが発声する要素名です。Content Description(iOSのaccessibilityHint)は、名前の後に読み上げられる追加の説明で、アクションの結果を伝えます。
違いは「カート」ボタンの例で明確です。Label:「カート」。Description:「チェックアウト画面を開きます」。VoiceOver:「カート。チェックアウト画面を開きます」。Labelのみが設定されている場合、ユーザーはタップ後に何が起こるかわかりません。
| プロパティ | iOS | Android | 目的 |
|---|---|---|---|
| Label | accessibilityLabel | contentDescription | 要素名(ボタン、フィールド、画像) |
| Description | accessibilityHint | contentDescription(拡張) | アクションや意味の説明 |
| Trait | accessibilityTraits | role / className | 要素の役割(ボタン、見出し) |
ルール:Labelは「これは何ですか?」に答え、Descriptionは「何が起こりますか?」に答えます。AndroidではcontentDescriptionが両方の役割を果たせますが、実際には「[名前]、[説明]」のように連結して分離することをお勧めします。
複雑なジェスチャー(スワイプして削除、長押しでコンテキストメニュー)の場合、accessibilityHintは必須です。VoiceOverユーザーは、説明がない限り隠れたジェスチャーを知りません。要素のhintに「左にスワイプして削除」と指定します。
iOSプラットフォームでは、accessibilityHintはUIViewまたはNSObjectの同名プロパティを介して設定されます。値は最大80文字の文字列です。VoiceOverは、詳細説明モードが有効な場合(VoiceOver設定の「Verbosity」)、ラベルの後にhintを読み上げます。
カスタムボタンのhint設定例:
import UIKit
class CustomButton: UIButton {
override func awakeFromNib() {
super.awakeFromNib()
self.accessibilityLabel = "お気に入りに追加"
self.accessibilityHint = "アイテムをお気に入りリストに保存します"
}
}
テキストコンテンツのないUIImageViewの場合は、isAccessibilityElement = trueとaccessibilityHintを設定する必要があります:
let imageView = UIImageView(image: UIImage(named: "chart-sales"))
imageView.isAccessibilityElement = true
imageView.accessibilityHint = "直近四半期の売上グラフ"
VoiceOverの読み上げ:「直近四半期の売上グラフ」。hintが空の場合は「画像」のみ。Apple HIG、2024は、hintに「タップ」や「押す」などの動詞を使用しないことを推奨しています。VoiceOverが自動的にジェスチャー指示を追加します。
SwiftUIでは、hintはチェーン修飾子を介して設定します:
Image(systemName: "trash")
.accessibilityLabel("削除")
.accessibilityHint("選択したアイテムを完全に削除します")
SwiftUIは自動的に複合ビューの修飾子を結合します。ImageがButton内にある場合、SwiftUIはボタンのラベルを主要なaccessibilityLabelとして使用します。
Androidでは、contentDescriptionはXMLマークアップまたはプログラムでsetContentDescription()を介して設定します。TalkBackは要素にフォーカスが当たると説明を読み上げます。
XMLの例:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_search"
android:contentDescription="商品を検索" />
動的要素のプログラムによる設定:
binding.iconSearch.contentDescription =
"検索。フィルター付きの検索画面を開きます"
装飾的な画像(区切り線、背景、装飾アイコン)の場合は、contentDescription = "@null"またはsetContentDescription(null)を設定します。TalkBackはこれらの要素をスキップします。XMLでは:android:contentDescription="@null"。空の文字列""は機能しません。TalkBackは引き続き「画像」を読み上げます。
ImageButtonの場合は、常にcontentDescriptionを設定します。TalkBackは画像のテキストを認識しません。CheckBoxの場合は、説明を動的に変更する必要があります。「選択済み」/「未選択」のように、静的な説明ではなく、状態リスナーでsetContentDescriptionを使用します。
情報量 — 説明は外観ではなく意味を伝える必要があります。「チェックマーク付きの青いアイコン」ではなく、「アイテムがカートに追加されました」。スクリーンリーダーは色に関心がなく、結果に関心があります。
簡潔さ — 最適な長さは2~4語(最大80文字)です。長い説明はナビゲーションを遅くします。VoiceOverは順次読み上げ、各単語はユーザーの時間の1秒です。Apple WWDC 2023、「Accessibility by Design」によると、5秒以上かかるフレーズは認知フローを中断します。
一意性 — 同じ画面に同じ説明を持つ2つの要素があってはなりません。ユーザーは、最初の要素と2番目の要素にフォーカスした場合の結果を区別できません。複数の「購入」ボタンがある場合は、識別子を追加します:「iPhone 15を購入」、「iPhone 15 Proを購入」。
ローカライゼーション — Content Descriptionはアプリがサポートするすべての言語に翻訳する必要があります。説明のローカライゼーションエラーは、App StoreでAccessibility Reviewに失敗する一般的な原因の1つです。
Nielsen Norman Group、2024の調査によると、スクリーンリーダーに最適な説明の長さは3~5語(最大50文字)です。それ以上の長い説明は、ユーザーが次のステップの前に読み上げの終了を待たなければならないため、ナビゲーション速度が30%低下します。
冗長性 — 説明が表示テキストを重複しています。ボタンに「送信」というテキストが含まれている場合、accessibilityHint =「送信ボタン」と設定しないでください。VoiceOverが自動的にテキストを読み上げ、hintは不要なノイズを追加します。
Labelとの混同 — テキストボタンにラベルの代わりにcontentDescriptionを使用すること。iOSでは、accessibilityLabelはボタンのテキストと一致する必要があり(テキストがすでに表示されている場合は空でも可)、hintはアクションのみを説明する必要があります。Google Testing Blog、2024によると、Play Storeでレビューされたアプリの23%に重複した説明があります。
動的な変更の無視 — 状態が変化しても説明が更新されません。たとえば、「Wi-Fi」トグルの説明がオンにした後も「Wi-Fiを有効にする」のままです。正しい方法:状態を監視して説明を動的に「Wi-Fiを無効にする」に変更します。
デザインの更新(アイコンの変更、要素の並べ替え)後、Content Descriptionはしばしば失われます。理由:デザイナーが画像を置き換え、開発者が新しいアセットのアクセシビリティプロパティを確認しないため。解決策:コードレビューでアクセシビリティチェックを必須ステップにします。チェックリスト項目に「Content Descriptionは更新されましたか?」を追加します。
func testContentDescriptionExists() {
let app = XCUIApplication()
app.launch()
let image = app.images["chart-sales"]
XCTAssertNotNil(image.label)
XCTAssertGreaterThan(image.label.count, 0)
}
よくある質問
VoiceOverまたはTalkBackは、目的を指定せずに単に「画像」または「ボタン」と読み上げます。これはWCAG 1.1.1に違反し、視覚障害者がアプリを利用できなくなります。
いいえ。ボタンにテキストラベルがある場合、VoiceOverは自動的にそれを読み上げます。タップの結果を説明するために説明(accessibilityHint)を追加することはできますが、Labelは必要ありません。
iOSではisAccessibilityElement = falseを設定します。AndroidではcontentDescription = "@null"を設定します。スクリーンリーダーはこれらの要素を完全にスキップし、音声も出力しません。
iOSではaccessibilityHintにNSLocalizedStringを使用し、Androidでは@string/を介した文字列リソースを使用します。サポートするすべての言語での説明の翻訳が必須です。
すべてのImageView要素に説明が存在することを確認するUIテストを追加します。iOSではXCUIApplication、AndroidではEspressoのAccessibilityCheckRuleを使用します。Accessibility ScannerはコマンドラインからCIで実行できます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。