Build accessible apps with semantic properties
Semantics for accessibility is concerned with building experiences that make your apps inclusive for people who use technology in a wide range of environments and approach your UI with a range of needs and experiences. In many situations, legal requirements for accessibility may provide an impetus for developers to address accessibility issues. Regardless, it's advisable to build inclusive and accessible apps so that your apps reach the largest possible audience.
The Web Content Accessibility Guidelines (WCAG) are the global accessibility standard and legal benchmark for web and mobile. These guidelines describe the various ways in which apps can be made more perceivable, operable, understandable, and robust, for all.
Many user accessibility needs are met by assistive technology products installed by the user or by tools and settings provided by the operating system. This includes functionality such as screen readers, screen magnification, and high-contrast settings.
Screen readers typically provide auditory descriptions of controls that are displayed on the screen. These descriptions help users navigate through the app and provide references to controls, such as images, that have no input or text. Screen readers are often controlled through gestures on the touchscreen, trackpad, or keyboard. For information about enabling screen readers, see Enable screen readers.
Operating systems have their own screen readers with their own unique behavior and configuration. For example, most screen readers read the text associated with a control when it receives focus, enabling users to orient themselves as they navigate through the app. However, some screen readers can also read the entire app user interface when a page appears, which enables the user to receive all of the page's available informational content before attempting to navigate it.
Most screen readers will automatically read any text associated with a control that receives accessibility focus. This means that controls, such as Label or Button, that have a Text
property set will be accessible for the user. However, Image, ImageButton, ActivityIndicator, and others might not be in the accessibility tree because no text is associated with them.
.NET Multi-platform App UI (.NET MAUI) supports two approaches to providing access to the accessibility experience of the underlying platform. Semantic properties are the .NET MAUI approach to providing accessibility values in apps, and are the recommended approach. Automation properties are the Xamarin.Forms approach to providing accessibility values in apps, and have been superseded by semantic properties. In both cases, the default accessibility order of controls is the same order in which they're listed in XAML or added to the layout. However, different layouts might have additional factors that influence accessibility order. For example, the accessibility order of StackLayout is also based on its orientation, and the accessibility order of Grid is based on its row and column arrangement. For more information about content ordering, see Meaningful Content Ordering on the Xamarin blog.
Note
When a WebView displays a website that's accessible, it will also be accessible in a .NET MAUI app. Conversely, when a WebView displays a website that's not accessible, it won't be accessible in a .NET MAUI app.
Semantic properties
Semantic properties are used to define information about which controls should receive accessibility focus and which text should be read aloud to the user. Semantic properties are attached properties that can be added to any element to set the underlying platform accessibility APIs.
Important
Semantic properties don't try to force equivalent behavior on each platform. Instead, they rely on the accessibility experience provided by each platform.
The SemanticProperties class defines the following attached properties:
Description
, of typestring
, which represents a description that will be read aloud by the screen reader. For more information, see Description.Hint
, of typestring
, which is similar toDescription
, but provides additional context such as the purpose of a control. For more information, see Hint.HeadingLevel
, of type SemanticHeadingLevel, which enables an element to be marked as a heading to organize the UI and make it easier to navigate. For more information, see Heading levels.
These attached properties set platform accessibility values so that a screen reader can speak about the element. For more information about attached properties, see Attached properties.
Description
The Description
attached property represents a short, descriptive string
that a screen reader uses to announce an element. This property should be set for elements that have a meaning that's important for understanding the content or interacting with the user interface. Setting this property can be accomplished in XAML:
<Image Source="dotnet_bot.png"
SemanticProperties.Description="Cute dot net bot waving hi to you!" />
Alternatively, it can be set in C#:
Image image = new Image { Source = "dotnet_bot.png" };
SemanticProperties.SetDescription(image, "Cute dot net bot waving hi to you!");
In addition, the SetValue method can also be used to set the Description
attached property:
image.SetValue(SemanticProperties.DescriptionProperty, "Cute dot net bot waving hi to you!");
The accessibility information for an element can also be defined on another element. For example, a Label next to an Switch can be used to describe what the Switch represents. This can be accomplished in XAML as follows:
<Label x:Name="label"
Text="Enable dark mode: " />
<Switch SemanticProperties.Description="{Binding Source={x:Reference label} Path=Text}" />
Alternatively, it can be set in C# as follows:
Label label = new Label
{
Text = "Enable dark mode: "
};
Switch mySwitch = new Switch();
SemanticProperties.SetDescription(mySwitch, label.Text);
Warning
- Avoid setting the
Description
attached property on a Label. This will stop theText
property being spoken by the screen reader. This is because the visual text should ideally match the text read aloud by the screen reader. - Avoid setting the
Description
attached property on an Entry or Editor on Android. Doing so will stop Talkback actions functioning. Instead, use the Placeholder property or theHint
attached property. - On iOS, if you set the
Description
property on any control that has children the screen reader will be unable to reach the children. This is because iOS doesn't provide accessibility features that allow the navigation from a parent element into a child element.
Hint
The Hint
attached property represents a string
that provides additional context to the Description
attached property, such as the purpose of a control. Setting this property can be accomplished in XAML:
<Image Source="like.png"
SemanticProperties.Description="Like"
SemanticProperties.Hint="Like this post." />
Alternatively, it can be set in C#:
Image image = new Image { Source = "like.png" };
SemanticProperties.SetDescription(image, "Like");
SemanticProperties.SetHint(image, "Like this post.");
In addition, the SetValue method can also be used to set the Hint
attached property:
image.SetValue(SemanticProperties.HintProperty, "Like this post.");
On Android, this property behaves slightly differently depending on the control it's attached to. For example, for controls without text values, such as Switch and CheckBox, the controls will display the hint with the control. However, for controls with text values, the hint is not displayed and is read after the text value.
Warning
The Hint
property conflicts with the Entry.Placeholder
property on Android, which both map to the same platform property. Therefore, setting a different Hint
value to the Entry.Placeholder
value isn't recommended.
Heading levels
The HeadingLevel
attached property enables an element to be marked as a heading to organize the UI and make it easier to navigate. Some screen readers enable users to quickly jump between headings.
Headings have a level from 1 to 9, and are represented by the SemanticHeadingLevel enumeration, which defines None
, and Level1
through Level9
members.
Important
While Windows offers 9 levels of headings, Android and iOS only offer a single heading. Therefore, when HeadingLevel
is set on Windows it maps to the correct heading level. However, when set on Android and iOS it maps to a single heading level.
The following example demonstrates setting this attached property:
<Label Text="Get started with .NET MAUI"
SemanticProperties.HeadingLevel="Level1" />
<Label Text="Paragraphs of text go here." />
<Label Text="Installation"
SemanticProperties.HeadingLevel="Level2" />
<Label Text="Paragraphs of text go here." />
<Label Text="Build your first app"
SemanticProperties.HeadingLevel="Level3" />
<Label Text="Paragraphs of text go here." />
<Label Text="Publish your app"
SemanticProperties.HeadingLevel="Level4" />
<Label Text="Paragraphs of text go here." />
Alternatively, it can be set in C#:
Label label1 = new Label { Text = "Get started with .NET MAUI" };
Label label2 = new Label { Text = "Paragraphs of text go here." };
Label label3 = new Label { Text = "Installation" };
Label label4 = new Label { Text = "Paragraphs of text go here." };
Label label5 = new Label { Text = "Build your first app" };
Label label6 = new Label { Text = "Paragraphs of text go here." };
Label label7 = new Label { Text = "Publish your app" };
Label label8 = new Label { Text = "Paragraphs of text go here." };
SemanticProperties.SetHeadingLevel(label1, SemanticHeadingLevel.Level1);
SemanticProperties.SetHeadingLevel(label3, SemanticHeadingLevel.Level1);
SemanticProperties.SetHeadingLevel(label5, SemanticHeadingLevel.Level1);
SemanticProperties.SetHeadingLevel(label7, SemanticHeadingLevel.Level1);
In addition, the SetValue method can also be used to set the HeadingLevel
attached property:
label1.SetValue(SemanticProperties.HeadingLevelProperty, SemanticHeadingLevel.Level1);
Semantic focus
Controls have a SetSemanticFocus extension method which forces screen reader focus to a specified element. For example, given a Label named label
, screen reader focus can be forced to the element with the following code:
label.SetSemanticFocus();
Semantic screen reader
.NET MAUI provides the ISemanticScreenReader interface, with which you can instruct a screen reader to announce text to the user. The interface is exposed through the Default property, and is available in the Microsoft.Maui.Accessibility namespace.
To instruct a screen reader to announce text, use the Announce method, passing a string
argument that represents the text. The following example demonstrates using this method:
SemanticScreenReader.Default.Announce("This is the announcement text.");
Limitations
The default platform screen reader must be enabled for text to be read aloud.
Automation properties
Automation properties are attached properties that can be added to any element to indicate how the element is reported to the underlying platform's accessibility framework.
The AutomationProperties class defines the following attached properties:
ExcludedWithChildren
, of typebool?
, determines if an element and its children should be excluded from the accessibility tree. For more information, see ExcludedWithChildren.IsInAccessibleTree
, of typebool?
, indicates whether the element is available in the accessibility tree. For more information, see IsInAccessibleTree.Name
, of typestring
, represents a short description of the element that serves as a speakable identifier for that element. For more information, see Name.HelpText
, of typestring
, represents a longer description of the element, which can be thought of as tooltip text that's associated with the element. For more information, see HelpText.LabeledBy
, of type VisualElement, which enables another element to define accessibility information for the current element. For more information, see LabeledBy.
These attached properties set platform accessibility values so that a screen reader can speak about the element. For more information about attached properties, see Attached properties.
Different screen readers read different accessibility values. Therefore, when using automation properties it's recommended that thorough accessibility testing is carried out on each platform to ensure an optimal experience.
Important
Automation properties are the Xamarin.Forms approach to providing accessibility values in apps, and have been superseded by semantic properties. For more information about semantic properties, see Semantic properties.
ExcludedWithChildren
The ExcludedWithChildren
attached property, of type bool?
, determines if an element and its children should be excluded from the accessibility tree. This enables scenarios such as displaying an AbsoluteLayout over another layout such as a StackLayout, with the StackLayout being excluded from the accessibility tree when it's not visible. It can be used from XAML as follows:
<StackLayout AutomationProperties.ExcludedWithChildren="true">
...
</StackLayout>
Alternatively, it can be set in C# as follows:
StackLayout stackLayout = new StackLayout();
...
AutomationProperties.SetExcludedWithChildren(stackLayout, true);
When this attached property is set, .NET MAUI sets the IsInAccessibleTree
attached property to false
on the specified element and its children.
IsInAccessibleTree
Warning
This attached property should typically remain unset. The majority of controls should be present in the accessibility tree, and the AutomationProperties.ExcludedWithChildren
attached property can be set in scenarios where an element and its children need removing from the accessibility tree.
The IsInAccessibleTree
attached property, of type bool?
, determines if the element is visible to screen readers. It must be set to true
to use the other automation properties. This can be accomplished in XAML as follows:
<Entry AutomationProperties.IsInAccessibleTree="true" />
Alternatively, it can be set in C# as follows:
Entry entry = new Entry();
AutomationProperties.SetIsInAccessibleTree(entry, true);
Warning
On iOS, if the IsInAccessibleTree
property is true
on any control that has children the screen reader will be unable to reach the children. This is because iOS doesn't provide accessibility features that allow the navigation from a parent element into a child element.
Name
Important
The Name
attached property has been deprecated in .NET 8. Instead, use the Description
attached property.
The Name
attached property value should be a short, descriptive text string that a screen reader uses to announce an element. This property should be set for elements that have a meaning that is important for understanding the content or interacting with the user interface. This can be accomplished in XAML as follows:
<ActivityIndicator AutomationProperties.IsInAccessibleTree="true"
AutomationProperties.Name="Progress indicator" />
Alternatively, it can be set in C# as follows:
ActivityIndicator activityIndicator = new ActivityIndicator();
AutomationProperties.SetIsInAccessibleTree(activityIndicator, true);
AutomationProperties.SetName(activityIndicator, "Progress indicator");
HelpText
Important
The HelpText
attached property has been deprecated in .NET 8. Instead, use the Hint
attached property.
The HelpText
attached property should be set to text that describes the user interface element, and can be thought of as tooltip text associated with the element. This can be accomplished in XAML as follows:
<Button Text="Toggle ActivityIndicator"
AutomationProperties.IsInAccessibleTree="true"
AutomationProperties.HelpText="Tap to toggle the activity indicator" />
Alternatively, it can be set in C# as follows:
Button button = new Button { Text = "Toggle ActivityIndicator" };
AutomationProperties.SetIsInAccessibleTree(button, true);
AutomationProperties.SetHelpText(button, "Tap to toggle the activity indicator");
On some platforms, for edit controls such as an Entry, the HelpText
property can sometimes be omitted and replaced with placeholder text. For example, "Enter your name here" is a good candidate for the Entry.Placeholder
property that places the text in the control prior to the user's actual input.
LabeledBy
Important
The LabeledBy
attached property has been deprecated in .NET 8. Instead, use a SemanticProperties.Description
binding. For more information, see SemanticProperties: Description.
The LabeledBy
attached property allows another element to define accessibility information for the current element. For example, a Label next to an Entry can be used to describe what the Entry represents. This can be accomplished in XAML as follows:
<Label x:Name="label" Text="Enter your name: " />
<Entry AutomationProperties.IsInAccessibleTree="true"
AutomationProperties.LabeledBy="{x:Reference label}" />
Alternatively, it can be set in C# as follows:
Label label = new Label { Text = "Enter your name: " };
Entry entry = new Entry();
AutomationProperties.SetIsInAccessibleTree(entry, true);
AutomationProperties.SetLabeledBy(entry, label);
Important
The AutomationProperties.LabeledByProperty
is not supported on iOS.
Testing accessibility
.NET MAUI apps typically target multiple platforms, which means testing the accessibility features according to the platform. Follow these links to learn how to test accessibility on each platform:
- Test your app's accessibility on Android.
- Verifying app accessibility on iOS.
- Testing for accessibility on OS X
- Accessibility testing on Windows.
The following tools can assist with your accessibility testing:
- Accessibility Insights for Android and Windows apps.
- Accessibility Scanner for Android apps.
- Accessibility Inspector for iOS and macOS apps.
- Android Studio Layout Inspector for Android apps.
- Xcode View Debugger for iOS and macOS apps.
However, none of these tools can perfectly emulate the screen reader user experience, and the best way to test and troubleshoot your apps for accessibility will always be manually on physical devices with screen readers.
Enabling screen readers
Each platform has a different default screen reader to narrate accessibility values:
- Android has TalkBack. For information on enabling TalkBack, see Enable TalkBack.
- iOS and macOS have VoiceOver. For information on enabling VoiceOver, see Enable VoiceOver.
- Windows has Narrator. For information on enabling Narrator, see Enable Narrator.
Enable TalkBack
TalkBack is the primary screen reader used on Android. How it's enabled depends on the device manufacturer, Android version, and TalkBack version. However, TalkBack can typically be enabled on your Android device via the device settings:
- Open the Settings app.
- Select Accessibility > TalkBack.
- Turn Use TalkBack on.
- Select OK.
Note
While these steps apply to most devices, you might experience some differences.
A TalkBack tutorial opens automatically the first time you enable TalkBack.
For alternative methods of enabling TalkBack, see Turn Talkback on or off.
Enable VoiceOver
VoiceOver is the primary screen reader used on iOS and macOS. On iOS, VoiceOver can be enabled as follows:
- Open the Settings app.
- Select Accessibility > VoiceOver.
- Turn VoiceOver on.
A VoiceOver tutorial can be opened by selecting VoiceOver Practice, once VoiceOver is enabled.
For alternative methods of enabling VoiceOver, see Turn on and practice VoiceOver on iPhone and Turn on and practice VoiceOver on iPad.
On macOS, VoiceOver can be enabled as follows:
- Open the System Preferences.
- Select Accessibility > VoiceOver.
- Select Enable VoiceOver.
- Select Use VoiceOver.
A VoiceOver tutorial can be opened by selecting Open VoiceOver Training....
For alternative methods of enabling VoiceOver, see Turn VoiceOver on or off on Mac.
Enable Narrator
Narrator is the primary screen reader used on Windows. Narrator can be enabled by pressing the Windows logo key + Ctrl + Enter together. These keys can be pressed again to stop Narrator.
For more information about Narrator, see Complete guide to Narrator.
Accessibility checklist
Follow these tips to ensure that your .NET MAUI apps are accessible to the widest audience possible:
- Ensure your app is perceivable, operable, understandable, and robust for all by following the Web Content Accessibility Guidelines (WCAG). WCAG is the global accessibility standard and legal benchmark for web and mobile. For more information, see Web Content Accessibility Guidelines (WCAG) Overview.
- Make sure the user interface is self-describing. Test that all the elements of your user interface are screen reader accessible. Add descriptive text and hints when necessary.
- Ensure that images and icons have alternate text descriptions.
- Support large fonts and high contrast. Avoid hardcoding control dimensions, and instead prefer layouts that resize to accommodate larger font sizes. Test color schemes in high-contrast mode to ensure they are readable.
- Design the visual tree with navigation in mind. Use appropriate layout controls so that navigating between controls using alternate input methods follows the same logical flow as using touch. In addition, exclude unnecessary elements from screen readers (for example, decorative images or labels for fields that are already accessible).
- Don't rely on audio or color cues alone. Avoid situations where the sole indication of progress, completion, or some other state is a sound or color change. Either design the user interface to include clear visual cues, with sound and color for reinforcement only, or add specific accessibility indicators. When choosing colors, try to avoid a palette that is hard to distinguish for users with color blindness.
- Provide captions for video content and a readable script for audio content. It's also helpful to provide controls that adjust the speed of audio or video content, and ensure that volume and transport controls are easy to find and use.
- Localize your accessibility descriptions when the app supports multiple languages.
- Test the accessibility features of your app on each platform it targets. For more information, see Testing accessibility.
Feedback
https://aka.ms/ContentUserFeedback.
Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see:Submit and view feedback for