0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

react-dropzoneから学ぶアクセシビリティ

Last updated at Posted at 2025-08-11

はじめに

私は実務で約2年間、フロントエンドエンジニアとしてWebアプリケーションの開発に携わっています。

現在アクセシビリティに力を入れて学んでいます。
この記事では、アクセシビリティの観点でreact-dropzoneというライブラリのコンポーネントを調べる過程で得た気づきを、自分への備忘も兼ねてまとめます。

先にこの記事のまとめを書きます。

  • インタラクティブ要素にrole="presentation"を付けるのは仕様的に避けた方が良さそう
  • インタラクティブな要素をネストするべきではない

react-dropzoneとは

react-dropzoneは、React向けのファイルアップロード用コンポーネントライブラリです。
ユーザーがファイルをドラッグ&ドロップでアップロードできるUIを簡単に実装できます。

疑問

検証ツールでDropzoneのDOM構造を調べると、Dropzoneの外側のdiv要素に、role="presentation"が付与されていました。

<div role="presentation" tabindex="0" class='dropzone'>

ソースコードを確認すると、getRootPropsという関数内で、下記のような記載があります。

propsroleが渡らない限り、外側のdiv要素にはrole="presentation"が付与されるとわかります。

react-dropzone/src/index.js L918
role: typeof role === "string" && role !== "" ? role : "presentation",

私は、Dropzoneの外側のdiv要素に、role="presentation"を付与する目的がわかりませんでした。

調査

role="presentation"とは

まずはrole="presentation"が何かを調べました。

role="presentation"は、WAI-ARIA ロールの一種です。

MDNには下記のように記されています。

presentationロールは、要素とそれに関連する子要素の意味論的意味を取り除くために使用されます。

ロールは本来、HTML要素の「意味」や「機能」をスクリーンリーダーなどの支援技術に伝えるために使用されます。

presentationロールを付与すると、それを打ち消すので、「この要素は何も役割を持っていない」 と伝えることになります。

例えば、見た目だけ表の罫線が欲しい時にtable要素を使用する場合、実際には表形式でデータを表示するという意味はないので、<table role="presentation">と指定します。

(あまりピンとこない😕)

Dropzoneの役割を考える

次に、Dropzoneの役割を考えます。

Dropzoneは、ファイルをドラッグ&ドロップでアップロードするために使用されるコンポーネントです。ユーザーがファイルをドロップできる領域が存在します。

また、react-dropzoneでは、Dropzoneにフォーカスし、Enterを押すと、ファイル選択ダイアログを開くことができます。

(ん?役割を持っているのでは?🤔)

なぜ役割があるのにも関わらず、role="presentation"を付与して、わざわざスクリーンリーダに役割がないと伝えているのでしょうか。

Issueから歴史を紐解く

結論から言うと、Dropzoneの外側のdiv要素に、role="presentation"を付与している理由は、「アクセシビリティの観点から最適ではないけれど、そうせざるを得なかった」 という解釈が正しいと思います。

react-dropzoneのIssueにこんな議論があります。

元々、Dropzoneはデフォルトでrole="button"を持っていました。そのため、その内部にさらに<button>などのインタラクティブな要素を配置すると、インタラクティブな要素が入れ子になり、アクセシビリティ的な問題が発生すると報告があったようです。

議論の末、デフォルトのrolebuttonからpresentationに書き換える変更が行われました。

このIssueから、react-dropzoneの意図を考えていきます。

インタラクティブな要素をネストしたら何が問題なのか

インタラクティブな要素とは、<button>, <a href>, <input>, <select>, <textarea> など、ユーザーがクリックや入力、フォーカスなどの操作ができる要素を指します。

ではインタラクティブな要素をネストすることが、なぜ問題なのでしょうか。

これはHTMLの仕様が原因です。

例えばbutton要素の場合、HTML Standardの「The 'in body' insertion mode」セクションに以下のような仕様が記載されています。

A start tag whose tag name is "button"

  1. If the stack of open elements has a button element in scope, then run these substeps:
    1. Parse error.
    2. Generate implied end tags.
    3. Pop elements from the stack of open elements until a button element has been popped from the stack.
  2. Reconstruct the active formatting elements, if any.
  3. Insert an HTML element for the token.
  4. Set the frameset-ok flag to "not ok".

(日本語訳)

ボタンというタグ名の開始タグ

  1. 開いている要素のスタックにbutton要素がスコープ内にある場合、次の手順を実行する:
       1. パースエラーとする
       2. 暗黙的な終了タグを生成する
       3. button要素がスタックから取り除かれるまで、要素をスタックからポップする
  2. 必要ならアクティブなフォーマット要素を再構築する
  3. このトークンに対してHTML要素を挿入する
  4. frameset-okフラグを「not ok」にセットする

例えば下記のようにbutton要素をネストして書いたとします。

<button>
    外側のボタン
    <button>内側のボタン</button>
</button>

しかし、HTMLの仕様上、途中で外側のbutton要素が自動的に閉じられ、実際には2つのbutton要素が横並びで存在する構造に変換されてしまいます。

<button>
    外側のボタン
</button>
<button>
    内側のボタン
</button>

この仕様は、アクセシビリティの観点でも問題となります。開発者が想定した「階層」や「意味」が失われてしまうため、スクリーンリーダーやキーボード操作でバグが発生する可能性があるからです。

react-dropzoneが抱えるアクセシビリティ問題

button要素がネストしてしまう問題を解消するために、react-dropzoneでは、外側のdivrole="presentation"を付与し、役割を打ち消す対策を取りました。

これにより、確かにこの問題自体は解消されました。

しかし、この対応は完璧ではありませんでした。

Dropzoneの外側のdivは本来、フォーカス可能で、ファイルをドロップできる領域を伝えるという役割を持つインタラクティブな要素です。

それにも関わらず、role="presentation"を付与してしまうと、「この領域には意味がありません」とスクリーンリーダーに伝えてしまいます。

アクセシビリティの原則は、「意味や役割を持つ要素を正しく伝えること」 です。操作可能なのに意味がない状態は、支援技術の利用者を混乱させてしまいます。

Issueにはone of the bigger accessibility crimes possible(かなり重大な“犯罪”の一つだ)とコメントされており、厳しい評価を受けているようです😢

検証

実際に、スクリーンリーダを使って、Dropzoneがどのように読み上げられるかを検証しました。
Dropzone内に表示されているテキストが読み上げられるため、読み上げ自体に問題はないと感じました。

最適なアクセシビリティではないけれど、使用する上では現状問題はないようです。

余談

アクセシビリティの仕様書WAI-ARIAによると、インタラクティブな要素にrole="presentation"を付与した場合、支援技術はこれを無視して、インタラクティブな要素として認識します。

If an element with a role of presentation is focusable, or otherwise interactive, user agents MUST ignore the normal effect of the role and expose the element with implicit native semantics, in order to ensure that the element is both understandable and operable.

(日本語訳)

presentationロールが付与された要素がフォーカス可能、または他の方法でインタラクティブな場合、ユーザーに操作可能なことを示すために、支援技術はpresentationロールの効果を無視する

この仕様があるからこそ、動作上特に問題が起きていないのだと思われます。

打ち消しの打ち消しが起きているので理解しづらいですが...

終わりに

使用頻度の高いライブラリでも、アクセシビリティが完璧ではないことを知ることができました。
UIライブラリを参考に実装するときは、実装の根拠をしっかりと調べた上で、実務に反映していきたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?