Repository navigation
Description
Steps to reproduce
- Run any Flutter Web app with semantics enabled, for example a page with
TextField(decoration: InputDecoration(labelText: 'Password'), obscureText: true).
Thea11y_assessmentstest app in flutter/packages works: open#/text-field-password. - Focus the text field, then move focus away or navigate to another route.
- Inspect
<flt-text-editing-host>, or run an automated accessibility checker such as axe on the page.
Expected results
The hidden autofill form that the engine keeps in the DOM is not exposed to assistive technology, and automated checkers report no unlabeled form controls.
Actual results
The dormant autofill form stays in <flt-text-editing-host> for the rest of the session, and it contains a synthetic <input> with no accessible name:
<form id="flt-af-EditableText-753320914" class="transparentTextEditing" ...>
<input tabindex="-1" class="submitBtn" type="submit" ...>
<input autocomplete="on" class="transparentTextEditing" ...>
</form>The synthetic input has no aria-label, no <label>, and no aria-hidden. It only gets a placeholder if the field has hintText. axe reports it under "Form elements must have labels" on whatever page is open afterwards, even though that page's own fields are labeled. Unlike the submit button next to it, it also has no tabindex="-1".
Reproduced on the a11y_assessments app: focus the password field on #/text-field-password, navigate to #/auto-complete, and the leftover unlabeled <input autocomplete="on"> is still in the page.
Cause
In engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart:
EngineAutofillForm.demoteFocusedToSyntheticcreates a synthetic placeholder when a field blurs in semantics mode, so the field still takes part in credential save. Added in [web] Autofill all AutofillGroup fields in semantics mode #187108.EngineAutofillForm._createFormElementAndFieldscreates synthetic elements for the non-focused fields of an autofill group.goDormant()intentionally keeps the form in the DOM so the browser can autofill and submit it later.
Neither creation site hides the synthetic elements from assistive technology.
Proposed fix
Set aria-hidden="true" and tabIndex = -1 on synthetic autofill elements at both creation sites. They exist for the browser's autofill and form submission, not as controls a user should reach. Browser autofill does not read ARIA, so autofill and credential save should be unaffected. The focused element must stay untouched; in non-semantics mode it is the real input receiving keystrokes.
Related: #190126 also changes this form's lifecycle and adds aria-hidden to the submit button, so the fix should be coordinated with it.
Code sample
Code sample
import 'package:flutter/material.dart';
void main() => runApp(const MaterialApp(home: Demo()));
class Demo extends StatelessWidget {
const Demo({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: const <Widget>[
TextField(decoration: InputDecoration(labelText: 'Password'), obscureText: true),
TextField(decoration: InputDecoration(labelText: 'Other')),
],
),
);
}
}Enable semantics, focus Password, then focus Other, then run
document.querySelector('flt-text-editing-host').innerHTML in the console.
Activity
flutter-triage-bot commentedon Oct 23, 2026
The
triaged-weblabel is irrelevant if there is noteam-weblabel orfyi-weblabel.flutter-triage-bot commentedon Oct 23, 2026
This issue is missing a priority label. Please set a priority label when adding the
triaged-weblabel.[web] Hide synthetic autofill inputs from assistive technology (flutt…
[web] Hide synthetic autofill inputs from assistive technology (flutt…