🖼️ Images of text

Common mistake

A common mistake is embedding text inside an image, for example, a promotional banner or decorative header where the text is part of the graphic. This text cannot be scaled with the user’s font size setting, cannot be read by a screen reader, and cannot be adapted to a high-contrast or custom color scheme.

🎯 Relevant elements

This guideline applies to any image that contains readable text:

  • Promotional banners and hero images with overlaid text
  • Decorative section headers rendered as images
  • Screenshots used in place of actual code or instructional text
  • Infographics where the textual content is not duplicated elsewhere

WCAG Guideline

This guideline is based on WCAG 2.2 - 1.4.5 Images of Text (Level AA). Images of text must only be used when the presentation is essential (e.g. a logo) or when the text can be visually customised to the user’s requirements. Where possible, use real text styled with Flutter text styling instead.


Solution

Replace images that contain text with real Text widgets positioned over the image. This keeps the visual design intact while making the text accessible.

// ❌ Don't - text is baked into the image and inaccessible
Image.asset('assets/banner_with_title.png');

// ✅ Do - position real text over the image
Stack(
  alignment: Alignment.bottomLeft,
  children: [
    Image.asset(
      'assets/banner.png',
      fit: BoxFit.cover,
      semanticLabel: '', // decorative - the Text widget below carries the meaning
    ),
    Padding(
      padding: const EdgeInsets.all(16),
      child: Text(
        'Discover the world',
        style: Theme.of(context).textTheme.headlineMedium?.copyWith(
          color: Colors.white,
        ),
      ),
    ),
  ],
);

When a logo or branded image must contain text, provide a descriptive semanticLabel so screen readers can still convey the content:

// ✅ Do - essential image of text with a descriptive semantic label
Image.asset(
  'assets/company_logo.png',
  semanticLabel: 'Acme Corp',
);

Validation & Testing

See the Validation & Testing setup guide for tool configuration.

Manual review

Increase the system font size to the maximum setting and check whether text inside images scales along with the rest of the UI. If it does not, the text is likely embedded in an image.

TalkBack & VoiceOver

Navigate over each image that appears to contain text. Verify that the text content is announced correctly and not skipped.


flutter_test

testWidgets('banner uses a Text widget, not a static image for its title', (tester) async {
  await tester.pumpWidget(MaterialApp(home: const HeroBanner()));

  expect(find.text('Discover the world'), findsOneWidget);
});

🛠️ Usage baseflow-a11y-components library

🛠️ Work in progress…


This site uses Just the Docs, a documentation theme for Jekyll.