ARIA-Barriers

NVDA のブラウズモードで「幅0・高さ0」のコントロールが一貫して読めるようになる変更

2026年02月15日

この記事は24motz が執筆しました。

スクリーンリーダー NVDA 2026.1 以降では、ウェブブラウザのブラウズモードにおいて、視覚的な幅または高さが 0 のコントロールを、もう「非表示」として扱わないようになります。

この変更により、スクリーンリーダー向けにだけ見せたい(視覚的には隠したい)コンテンツを、幅0・高さ0で実装しているサイトでも、NVDA のブラウズモードでアクセスできるようになります。

このページには、NVDA で実際に操作できるデモがあります。 以下の「体験コーナー」で、ブラウズモードの挙動を試してみてください。変更の対象は Firefox のブラウズモード(gecko_ia2)です。

変更の概要

これまで何が起きていたか

これまでの NVDA では、ウェブページ上で「アクセシビリティツリーには出ているが、描画上の幅または高さが 0 で、かつ子要素がない」ようなコントロールを、非表示とみなしてブラウズモードの仮想バッファから除外していました。

一方で、多くのサイトでは次のような実装が使われています。

ブラウザはこうした要素もアクセシビリティツリーに載せており、JAWS など他スクリーンリーダーでは読めていました。NVDA だけが「幅0・高さ0」を理由に除外していたため、他では動くコンテンツが NVDA ではブラウズモードでアクセスできないという相互運用性の問題が起きていました。

PR の説明にもあるとおり、この挙動は「ウェブがずっとシンプルだった昔」に実装されたもので、今日では「ブラウザが明示的にツリーに載せたものを信頼する」方向に寄せることが、NVDA ユーザー全体の利益になると判断されての変更です。

体験コーナー

以下は、いずれも視覚的には幅0・高さ0(またはオフスクリーン)で配置されたコントロールです。Firefox でこのページを開き、NVDA のブラウズモードで下矢印キーを押しながら進んでみてください。


デモ1: 幅0・高さ0のラジオボタン(カスタムUIでよくあるパターン)

見た目用のラベルだけ表示し、実際のラジオボタンは width: 0; height: 0 で隠しています。ブラウズモードで「オプション A」「オプション B」「オプション C」のラジオボタンとして読めるか、選択できるかを試してください。

メンテナンスドローンを選択


<div role="group" aria-labelledby="zerodemo-group-label">
  <p id="zerodemo-group-label">メンテナンスドローンを選択</p>
  <span>
    <input type="radio" name="zerodemo-drone" id="zerodemo-r1" value="a"
      style="width:0;height:0;margin:0;padding:0;border:0;
             position:absolute;clip:rect(0,0,0,0);"
      aria-label="オプション A">
    <label for="zerodemo-r1">オプション A</label>
  </span>
  <!-- オプション B, C も同様 -->
</div>

デモ2: スクリーンリーダー専用の「署名の代わりに入力」ボタン

署名欄などでよくある「署名(キャンバス)の代わりに名前を入力」するための、視覚的に隠したボタンです。ブラウズモードで探して Enter で押してみてください。押すとメッセージが表示されます。

署名(キャンバス)の代わりに:


<button type="button"
  style="width:0;height:0;margin:0;padding:0;border:0;
         position:absolute;clip:rect(0,0,0,0);
         overflow:hidden;display:block;"
  aria-label="名前を入力する">名前を入力する</button>

デモ3: 値が 0 のプログレスバー(幅0)

進捗 0% のため、CSS で幅 0 になっているプログレスバーです。ブラウズモードで「プログレスバー、0%」のように読まれるか試してください。

読み込み中(0%)


<div role="progressbar"
  aria-labelledby="zerodemo-pb-label"
  aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"
  style="width:0%; height:8px; background:#333; border-radius:4px;">
</div>

検証時の読み上げ例

NVDA 2026.1 日本語ベータ版 + Firefox

2026年2月に、Firefox でこのページを開き、NVDA 2026.1 日本語ベータ版(ブラウズモード)で下矢印キーを押しながら取得した読み上げの一例です。いずれも幅0・高さ0のコントロールがブラウズモードで読まれています。

環境: Windows 11、Mozilla Firefox (147.0.3)、NVDA 2026.1 日本語ベータ(260211s ポータブル)、ブラウズモードで下矢印のみ使用。

NVDA 2025.3.2 日本語版 + Firefox

同じページを NVDA 2025.3.2jp(ポータブル)で検証した結果です。

デモ1で「飛ばされない」理由の考察

NVDA が従来「非表示」とみなして除外する条件は、記事にあるとおり 「描画上の幅または高さが 0 で、かつ子要素がない」 コントロールです。デモ2・デモ3は 2025 で飛ばされた一方、デモ1のラジオボタンだけは 2025 でもブラウズモードで読めました。考えられる理由は次のとおりです。

いずれにしても、同じ「幅0・高さ0」のコントロールでも、ブラウザの a11y ツリーの構造次第で飛ばされる/飛ばされないが変わるため、2026.1 以降は「幅0・高さ0を非表示扱いしない」方針に統一することで、デモ2・デモ3のようなケースも含めて一貫して読めるようになります。

Firefox の開発者ツールのアクセシビリティパネルでデモ1のラジオボタン(オプション A)を確認すると、radio: ノードの直下に label:text leaf: が子としてあり、いずれも「オプション A」を持っていることが分かります。この「子ノードがある」構造のため、従来の「子要素がない」条件を満たさず、2025 でも飛ばされなかったと説明できます。


関連する話題:aria-hidden と「フォーカス時の修復」

issue #13897 のスレッドでは、aria-hidden の「修復」にも言及されています。

開発者が aria-hidden="true" を付けた場合でも、ユーザーがフォーカスした要素については、ブラウザがその属性を無視してアクセシビリティツリーに曝す実装が、Chromium 系(Edge など)にはあります。この「フォーカスされた要素に対する aria-hidden の無視」は、WAI-ARIA 1.2 仕様で明示的に規定されている動きです。

その結果、「視覚的には隠れている(あるいは幅0・高さ0の)要素」を、スクリーンリーダー側で安易に「非表示」として除外しないことが、仕様やブラウザの実装と整合的になってきています。今回の「幅0・高さ0を非表示扱いしない」変更は、その流れに沿ったものとも言えます。

開発者への示唆:「スクリーンリーダーだけに読ませる」実装のリスク

今回の NVDA の変更は、width: 0; height: 0 で隠した要素を「読める」ようにするものですが、そもそもスクリーンリーダーにだけ読ませることを前提にした実装は、検証漏れやバグの温床になりやすい点にも触れておきます。

ちなみに:この変更は Firefox だけ?

NVDA の対応は Gecko IA2(Firefox ブラウズモード)に限られますが、Chromium 系(Google Chrome・Microsoft Edge など)や Safari でも幅0・高さ0要素は既にアクセシビリティツリーに載っており、他スクリーンリーダー(JAWS、VoiceOver など)によっては以前から読めていました。

今回の修正により主要ブラウザ間で残っていた仕様の食い違いのひとつが解消されます。

まとめ

詳細や経緯は上記の issue と PR を参照してください。

追記

この記事は Cursor や Claude Code などの AI を使って執筆しました。

途中で行った実験は、いま私が開発している「NVDAを MCP (Model Context Protocol) 経由で AI エージェントから操作する」ツールの検証を兼ねて行いました。

この仮称 nvda-remote-mcp は、こういう技術検証をもうしばらく行い、完成度が上がった段階で紹介したいと考えています。