Skip to content

[web] Semantics text field exposes an empty value to assistive technology until focused once #194548

Open

Description

@jorgelrj

Reproduced on Flutter 3.47.4 stable (9584c67), Chrome on macOS. The code involved is unchanged on master 697012a (links below).

On the web, a semantics text field's <input> stays empty until the field has been focused once. Assistive technology reads the DOM element, so a screen reader browsing a form reads every filled field as empty until the user enters each one. The framework side is correct: the semantics tree already carries each field's value.

Steps to reproduce

  1. Run the code sample below on the web (flutter run -d chrome, or build for web and serve it).
  2. Turn semantics on, either with a screen reader or by activating the placeholder from the DevTools console:
    document.querySelector('flt-semantics-placeholder').click()
  3. Without focusing either field, read the <input> values, for example with
    [...document.querySelectorAll('input')].map((i) => `${i.getAttribute('aria-label')}=${JSON.stringify(i.value)}`).join(' ')
    and read the accessibility tree (the DevTools Accessibility pane, or CDP Accessibility.getFullAXTree).
  4. Click Load, then Reps, and read them again.

The Save button is in the sample only so that the route's default focus does not land on the first field. If it did, that field would be activated and would hide the bug for that field.

Expected results

Before any focus, Load reads value "100" and Reps reads "5". The semantics tree already carries those values. A widget test on the same sample gives:

Load: value="100"
Reps: value="5"
Widget test that prints the semantics values
import 'package:flutter_test/flutter_test.dart';
import 'package:repro/main.dart' as field; // the code sample below

void main() {
  testWidgets('field value', (tester) async {
    final h = tester.ensureSemantics();
    field.main();
    await tester.pump();
    for (final l in ['Load', 'Reps']) {
      final d = find.semantics.byLabel(l).evaluate().single.getSemanticsData();
      debugPrint('$l: value="${d.value}"');
    }
    h.dispose();
  });
}

Actual results

Both <input> elements are empty, and the accessibility tree has no value for either text box. Each field gets its value only once it has been focused, and keeps it afterwards. This happens with any number of fields, for example a grid of inputs in a real app.

Code sample

Code sample
import 'package:flutter/material.dart';

void main() => runApp(
  MaterialApp(
    home: Scaffold(
      body: Column(
        children: [
          TextButton(onPressed: () {}, child: const Text('Save')), // takes the route's default focus
          TextField(controller: TextEditingController(text: '100'), decoration: const InputDecoration(labelText: 'Load')),
          TextField(controller: TextEditingController(text: '5'), decoration: const InputDecoration(labelText: 'Reps')),
        ],
      ),
    ),
  ),
);

Screenshots or Video

Not applicable: the logs below are the evidence.

Logs

Logs

Chrome, semantics on. DOM is each <input>'s value by its aria-label; AX is the accessibility tree without generic and static-text nodes.

unfocused  DOM Load="" Reps="" | AX [ 'button "Save" focused=true', 'textbox "Load"', 'textbox "Reps"' ]
after Load DOM Load="100" Reps=""
after Reps DOM Load="100" Reps="5" | AX [
  'button "Save"',
  'textbox "Load" value="100"',
  'textbox "Reps" value="5" focused=true'
]

Cause

SemanticTextField never mirrors semanticsObject.value onto its editableElement.

This is unchanged on master: SemanticTextField.update() at 697012a97f has no write of semanticsObject.value either.

Suggested fix

In SemanticTextField.update(), when this field is not SemanticsTextEditingStrategy._instance?.activeTextField and semanticsObject.isValueDirty, set editableElement.value = semanticsObject.value ?? ''. Skip this for obscured fields, or write a masked value. Leave the active field alone, so that the editing channel stays the source of truth while the user is typing. This also narrows the window in #194186.

Related issues

I searched for SemanticTextField value, SemanticsTextEditingStrategy, semantics TextField value web empty, web semantics input value unfocused, web a11y textfield value screen reader, TextField value VoiceOver web and screen reader input value empty web flutter, and found no other match.

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.47.4, on macOS 27.0.1 26A434 darwin-arm64, locale en-GB)
    • Flutter version 3.47.4 on channel stable at ~/Development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 9584c6713b (5 weeks ago), 2026-09-10 15:25:10 -0700
    • Engine revision 06a2e2a110
    • Dart version 3.13.3
    • DevTools version 2.60.0
    • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, enable-record-use, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-arm64   • macOS 27.0.1 26A434 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 155.0.8059.82

[✓] Network resources
    • All expected network resources are available.

(Android and Xcode checks timed out on this machine and are left out; they do not apply to these web/framework reports.)

Activity

  1. suryaKommana2662 commented on Oct 19, 2026

    @suryaKommana2662
    Contributor

    @jorgelrj Thanks for the report. I reproduced this issue on Flutter Web in Chrome. The input values become available in the HTML elements only after the respective fields receive focus. routing to the team-accessibility for further investigation I observed the following results:

    Command used:

    [...document.querySelectorAll('input')]
      .map(i => `${i.getAttribute('aria-label')}=${JSON.stringify(i.value)}`)
      .join(' ')
    

    Observations:

    Before any interaction: Load="" Reps=""
    After clicking Load: Load="100" Reps=""
    After clicking Reps: Load="100" Reps="5"
    

    Flutter Doctor Output

    [✓] Flutter (Channel stable, 3.47.7, on macOS 27.0 26A428 darwin-arm64, locale en-IN) [223ms]
        • Flutter version 3.47.7 on channel stable at /Users/suryakommana/develop/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision abaf9c5237 (11 days ago), 2026-10-08 09:51:21 -0700
        • Engine revision deb287481e
        • Dart version 3.13.5
        • DevTools version 2.60.0
        • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets,
          enable-record-use, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [1,594ms]
        • Android SDK at /Users/suryakommana/Library/Android/sdk
        • Emulator version 37.1.11.0 (build_id 15917651) (CL:N/A)
        • Platform android-37.0, build-tools 36.0.0
        • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
          This is the JDK bundled with the latest Android Studio installation on this machine.
          To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
        • Java version OpenJDK Runtime Environment (build 25.0.2+-15348964-b329.117)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 27.0) [1,276ms]
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Build 27A266a
        • CocoaPods version 1.17.0
    
    [✓] Chrome - develop for the web [3ms]
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Connected device (2 available) [5.9s]
        • macOS (desktop) • macos  • darwin-arm64   • macOS 27.0 26A428 darwin-arm64
        • Chrome (web)    • chrome • web-javascript • Google Chrome 155.0.8059.84
    
    [✓] Network resources [705ms]
        • All expected network resources are available.
    
    • No issues found!
  2. added
    a: text inputEntering text in a text field or keyboard related problems
    a: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)
    platform-webWeb applications specifically
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    fyi-webFor the attention of Web platform team
    team-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)
    and removed
    in triagePresently being triaged by the triage team
    on Oct 19, 2026
  3. flutter-zl commented on Oct 21, 2026

    @flutter-zl
    Contributor
  4. added
    triaged-webTriaged by Web platform team
    P2Important issues not at the top of the work list
    on Oct 21, 2026
  5. added
    team-webOwned by Web platform team
    triaged-webTriaged by Web platform team
    and removed
    team-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)
    on Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)a: text inputEntering text in a text field or keyboard related problemshas reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-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