Skip to content

[web] a11y focus ring rect frequently broken for plain text #146774

@yjbanov

Description

@yjbanov

Due to https://g-issues.chromium.org/issues/40875151 (I filed it against Chromium, but all browsers have it; it's a missing piece in the ARIA spec), I've been having difficulty finding a combination of DOM structure and ARIA attributes for plain text that would satisfy all screen readers. Currently, text is rendered into semantics like this:

<flt-semantics style="position: absolute;
                      width: 814px;
                      height: 809px;
                      top: 0px;
                      left: 0px;
                      pointer-events: all;">
  Hello, World!
</flt-semantics>

All screen readers are able to find this text and read it to the user correctly. However, some screen reader + browser combos, e.g. VoiceOver on macOS, ignore the size information specified on the element, and instead tightly hug the text that's inside the element:

Screenshot 2024-04-15 at 10 59 41 AM

The framework means the box containing the text to cover the whole screen with the "Hello, World!" text centered horizontally inside it. However, the DOM used to report semantics to screen readers is unaware of all this. All it gets is the rect of the box (0, 0, 814, 809) and the label ("Hello, World!"), and there does not seem to be a way to publish such box via anything DOM and ARIA provide.

Repro:

import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';

void main() {
  runApp(const MyApp());
  SemanticsBinding.instance.ensureSemantics();
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Plain text accessibility',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Text('Hello, World!', textAlign: TextAlign.center),
    );
  }
}

Methods tried before

  • Set aria-label and no DOM text inside:
  • role="text"
  • Other roles: "group", "static"
    • Sizes the ring correctly but breaks the traversal with "end of $LABEL, grou" wording after every text element.
  • Adding hidden content inside the node (to avoid "empty group")
    • Hidden content gets collapsed as if the node never had it, so it has no effect.

Links

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work lista: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)platform-webWeb applications specificallyteam-webOwned by Web platform teamtriaged-webTriaged by Web platform team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions