Repository navigation
Description
Steps to reproduce
- Create a Flutter web app that calls
SemanticsBinding.instance.ensureSemantics(). A real screen reader enables semantics on its own; this forces it for a deterministic repro. - Add a few controls: two buttons, a checkbox, and a
TextField(see the code sample). flutter build web, deploy, and open in a WebKit browser: iOS Safari, or macOS/iPadOS Safari. Turn on VoiceOver.
Expected results
- VoiceOver focus lands on each control at its visible position; the user can navigate and activate the buttons, the checkbox, and the field.
- Tapping the
TextFieldopens the on-screen keyboard.
Actual results
Every interactive semantic element is placed about one viewport to the right, off-screen.
- VoiceOver is broken for the whole app. The DOM node for each control is off the right edge, so VoiceOver focus rectangles land off-screen. A screen-reader user cannot reliably focus or activate any control.
- The
TextFieldcannot be typed into. The visible field is painted correctly by the canvas, but the invisible<input>is off-screen, so a tap misses it and the keyboard never opens. This is the symptom reported in [Web] Unable to type in TextField when ensureSemantics is enabled for accessibility #129324.
Confirmed cross-browser
The same deployed build, opened in different browsers. The browser engine is the only variable:
| Browser | Engine | Interactive semantic nodes off-screen |
|---|---|---|
| iOS Safari | WebKit | 4 to 5 of 5 |
| macOS Safari | WebKit | 4 of 5 |
| macOS Chrome | Blink | 0 of 5 |
| desktop Chrome | Blink | 0 of 5 |
| Android Chrome / Firefox | Blink / Gecko | 0 |
Per-node measurement on an iPhone at 430px width and devicePixelRatio 3: the text field <input> reports getBoundingClientRect().left = 446, off the 430-wide screen; the same build in Chrome reports 16. The offset is about one viewport width.
Root cause
<flt-semantics-host> is position: absolute with no left/top, so it falls back to its CSS static position. WebKit resolves that static position by flowing the host past its in-flow sibling <flt-glass-pane>, which is about one viewport wide, shifting the entire semantics subtree right by about one viewport. Blink and Gecko resolve the same static position to 0, so they are unaffected.
Suggested fix: anchor the host explicitly by setting left: 0; top: 0 in StyleManager.styleSemanticsHost (lib/web_ui/lib/src/engine/view_embedder/style_manager.dart). Blink and Gecko already resolve to 0, so it is a no-op there.
Related issues
- [Web] Unable to type in TextField when ensureSemantics is enabled for accessibility #129324 — "Unable to type in TextField when ensureSemantics is enabled." The text-input symptom of this same offset; that issue is framed narrowly as text input.
- DropdownButton touchscreen selection blanks iPhone web browser screen when SemanticsBinding.instance.EnsureSemantics() is enabled #172180 — "DropdownButton selection blanks the iPhone screen." Same root cause: selecting an item focuses a newly created semantic node, WebKit auto-scrolls to bring it into view, and because the node is about one viewport off-screen the whole page slides off. Closed as
r: fixed, but only the Android variant was fixed; the iOS case reportedly still reproduces. Same customer (castaway). - [web] on Safari for macOS using VoiceOver it is easy to make text field non-editable #147439 — "on Safari for macOS using VoiceOver it is easy to make text field non-editable." Very likely the same root cause: with macOS Safari now confirmed affected, an off-screen
<input>matches the non-editable symptom. The suggested fix should cover it.
Code sample
main.dart
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(const MyApp());
// The bug requires semantics to be enabled. A real screen reader turns this
// on automatically; ensureSemantics() forces it for a deterministic repro.
SemanticsBinding.instance.ensureSemantics();
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: HomePage());
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _checked = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ElevatedButton(onPressed: () {}, child: const Text('Alpha')),
ElevatedButton(onPressed: () {}, child: const Text('Beta')),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Checkbox(
value: _checked,
onChanged: (bool? v) => setState(() => _checked = v ?? false),
),
const Text('Check me'),
],
),
const Padding(
padding: EdgeInsets.all(16),
child: TextField(),
),
],
),
),
);
}
}Environment
flutter --version
Flutter 3.47.0-1.0.pre-134 • channel [user-branch] • [email protected]:flutter/flutter.git
Framework • revision 891cee207b (2026-07-20)
Engine • hash 82480b3ba2ddf43762fb9d24757bba63db165a03 (revision 9b105336e8) (2026-07-20)
Tools • Dart 3.14.0 (build 3.14.0-41.0.dev) • DevTools 2.60.0
- Also reproduces on stable 3.32 / 3.33 (see DropdownButton touchscreen selection blanks iPhone web browser screen when SemanticsBinding.instance.EnsureSemantics() is enabled #172180).
- Host: macOS 26.5.1 (darwin-arm64), Chrome 150.0.7871.188.
- Reproduces in any WebKit browser: iOS Safari, iOS Chrome/Firefox, macOS Safari, iPadOS Safari. Not reproducible on Blink (desktop/Android/macOS Chrome) or Gecko (Firefox).
cc @flutter-zl
Activity
flutter-triage-bot commentedon Aug 4, 2026
The
triaged-weblabel is irrelevant if there is noteam-weblabel orfyi-weblabel.[-][web] iOS Safari (WebKit) shifts the whole semantics layer off-screen when semantics is enabled, breaking VoiceOver and TextField input[/-][+][web] WebKit (iOS and macOS Safari) shifts the whole semantics layer off-screen when semantics is enabled, breaking VoiceOver and TextField input[/+][web] Point semantics-host anchor comment at flutter#190483
[web] Anchor flt-semantics-host at 0,0 to fix WebKit semantics offset (…
github-actions commentedon Sep 15, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.