Success Criterion 2.4.4 - Level A
Link Purpose (In Context)
Ensure the purpose of each link is clear. Users can request a list of links. The link and its surrounding text should indicate where you will navigate to. Clear links are useful for everyone and especially for users of assistive technologies users.
Impact
Assistive technologies can show an overview of all links on the screen. The purpose of each link should be clear immediately.
Check
“Is the purpose of each link clear?“
This can be tested without assistive technologies.
Solution
Mark links
- Android
- Jetpack Compose
- iOS
- SwiftUI
- Flutter
- React Native
- .NET MAUI
- Xamarin
Accessibility link - Android
On Android, links should be embedded inside an URLSpan
.
To create text links, you can show the span
in using the setText
method of TextView
. To support assistive technologies on lower version of Android, you need to call the ViewCompat.enableAccessibleClickableSpanSupport()
method.
The helper method ViewCompat.addLinks()
is also useful to automatically create accessible links.
Warning: you have to remove the android:autoLink
attribute from your XML to make your URLSpan
's clickable.
val textView = TextView(this)
val url = "https://appt.org"
val link = "Appt"
val spannableString = SpannableString("Learn more about $link")
val index = spannableString.indexOf(link)
spannableString.setSpan(URLSpan(url), index, index + link.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
textView.text = spannableString
textView.movementMethod = LinkMovementMethod.getInstance()
ViewCompat.enableAccessibleClickableSpanSupport(textView)
Accessibility link - Jetpack Compose
In Jetpack Compose, starting from compose-ui 1.7.0
you can use LinkAnnotation.Url
of AnnotatedString
to add an inline link to the text.
Clicking on the link will automatically open it in the default browser.
val textWithLink = buildAnnotatedString {
append("Learn more about ")
// adding clickable url
withLink(
LinkAnnotation.Url(
url = "https://appt.org",
// adding style for the url
styles = TextLinkStyles(
style = SpanStyle(textDecoration = TextDecoration.Underline, color = Color.Blue)
)
)
) {
append("Appt")
}
}
Text(textWithLink)
Important: Starting from compose-ui 1.7.0
ClickableText
and pushUrlAnnotation
will be deprecated.
Accessibility link - iOS
On iOS, links should contain the link
attribute. This attribute can be added through the addAttribute
method of NSMutableAttributedString
To create text links, you can show the attributed string
by using the the attributedText
property of UILabel
.
Depending on how your links are created, you might need to set the .link
trait as accessibilityTraits
.
guard let url = URL(string: "https://appt.org") else { return }
let link = "Appt"
let attributedString = NSMutableAttributedString(string: "Learn more about \(link)")
let range = attributedString.mutableString.range(of: link)
attributedString.addAttribute(.link, value: url, range: range)
let label = UILabel()
label.attributedText = attributedString
// Optional: add .link accessibility trait to whole label
label.accessibilityTraits = .link
Accessibility link - SwiftUI
In SwiftUI, you can create rich text that includes clickable links using the AttributedString
and its link
attribute. This approach allows you to make specific parts of your text act as hyperlinks.
let attributedTextLink: AttributedString = {
var fullText = AttributedString("Learn more about Appt")
// Find the range of the word "Appt"
if let range = fullText.range(of: "Appt") {
// Add link attribute to "Appt"
fullText[range].link = URL(string: "https://appt.org/en/")!
}
return fullText
}()
Text(attributedTextLink)
In SwiftUI, you can create a Link
view that behaves as a link
out of the box. The Link
view links the entire content of the view that it wraps, rather than just a portion of it. This means that when you use Link
to wrap a text, tapping anywhere within that view area will trigger the link.
Link("Visit Appt", destination: URL(string: "https://appt.org")!)
Accessibility link - Flutter
In Flutter, links should have the semantic property link
.
To create text links, you can use the RichText
widget. You can pass multiple TextSpan
widgets as it's children.
The url_launcher
package can be used to open links.
RichText(
text: TextSpan(
children: [
TextSpan(
text: 'Learn more about ',
),
Semantics(
link: true,
label: 'Appt',
hint: 'External link',
child: TextSpan(
text: 'Appt',
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.blue
),
recognizer: TapGestureRecognizer()..onTap = () {
final url = Uri.parse('https://appt.org')
launchUrl(url)
},
),
),
],
),
);
Accessibility link - React Native
In React Native, links should have their accessibilityRole
set to link
. You can use accessibilityLabel
or accessibilityHint
to provide additional context.
To create text links, you can embed a Text
component inside a Pressable
component.
The Linking API
can be used to open links.
<Pressable
onPress={async () => {
const supported = await Linking.canOpenURL(url);
if (supported) {
await Linking.openURL(url);
}
}}
accessibilityRole="link"
accessibilityLabel="Appt"
accessibilityHint="External link"
>
<Text>Appt</Text>
</Pressable>
Accessibility link - .NET MAUI
In MAUI, there is no built-in support to indicate content as a link.
Generally, it is more important to help users understand what will happen when they perform an action on the accessibility element. In this case, an accessibility hint could be used.
Not available, contribute!
Accessibility link - Xamarin
In Xamarin, you need to follow four steps to create links:
Set the
TextColor
andTextDecoration
properties of theLabel
orSpan
.Add a
TapGestureRecognizer
to theGestureRecognizers
collection of theLabel
orSpan
, whoseCommand
property binds to aICommand
, and whoseCommandParameter
property contains the URL to open.Define the
ICommand
that will be executed by theTapGestureRecognizer
.Write the code that will be executed by the
ICommand
.
For more information, see Xamarin Hyperlinks, it includes information how you can create your own Hyperlink
class.
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Read more about " />
<Span Text="Appt"
TextColor="Blue"
TextDecorations="Underline">
<Span.GestureRecognizers>
<TapGestureRecognizer Command="{Binding TapCommand}"
CommandParameter="https://appt.org" />
</Span.GestureRecognizers>
</Span>
</FormattedString>
</Label.FormattedText>
</Label>