Skip to content

USWDS - Links: External link labels #5166

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
May 10, 2023
Merged

USWDS - Links: External link labels #5166

merged 16 commits into from
May 10, 2023

Conversation

mejiaj
Copy link
Contributor

@mejiaj mejiaj commented Mar 1, 2023

Summary

External links labeled for screen readers. Adds a label for screen readers that clearly marks external links and whether they open in a new tab or current.

Breaking change

This is not a breaking change.

Related issue

Closes #5164.

Preview link

External link test → Removed in 917b3e9

Links [story mode]

Problem statement

  1. Users of assistive technologies should be able to differentiate internal vs external link.
  2. Users of assistive technologies should be able to differentiate new tab vs current.
  3. Currently there's only a visual indicator for external links.
  4. Fixing this will bring parity to the external link component for all users.

Solution

This solution:

  • Adds a label via the ::before pseudo element. Pseudo element was chosen to allow users to easily update and add this feature into their sites.
  • Two new settings to allow developers to customize labels

⚠️ Possible limitation: Section508.gov warns against placing meaningful text in pseudo elements. We should be careful when testing this feature and implementing more hidden labels in the future.

Development Considerations

Avoid using inserted CSS content (pseudo elements ::before and ::after) to add meaningful content.

Source: https://www.section508.gov/content/guide-accessible-web-design-development

Alternatives

JavaScript could be used to inject hidden span into each external link.

Major changes

Two new settings for Link component:

Variable Value Type Description
$theme-external-link-sr-label "External link" string Removed in 94d4274. Base label indicating external link.
$theme-external-link-sr-label-tab-new "External, opens in a new tab." string Screen reader-only text for links that open in new tab.
$theme-external-link-sr-label-tab-same "External, opens in current tab." string Screen reader-only text for links that open in current tab.

End result

The following text gets announced before an external link:

// External link in current tab
"External, opens in current tab."
// External link in new tab
"External, opens in a new tab."

Testing and review

  1. Screen readers (JAWS/VoiceOver/NVDA) should read hidden label
  2. Screen reader indicates whether it opens in new tab (target="_blank") or current (fallback).
Previous test (click to expand)
  1. Screen readers (JAWS/VoiceOver/NVDA) should read the hidden label identifying external links.
  2. Need to find the most clear and obvious label:
    1. [External link]
    2. External link: [⚠️ Punctuation might negatively impact RTL languages]
    3. External link. This was found to provide the best experience across screen readers (JAWS, VoiceOver, and Narrator).

I was able to get VoiceOver to read, Option 1 ([External]) seemed like the best experience to me. Need to hear how these sound on other screen readers.

Related PRs

Updated site guidance uswds/uswds-site#2056


  • Run npm run prettier:scss to format any Sass updates.
  • Run git pull origin [base branch] to pull in the most recent updates from your base and check for merge conflicts. (Often, the base branch is develop).

@mejiaj mejiaj requested a review from amycole501 March 1, 2023 17:24
@mejiaj
Copy link
Contributor Author

mejiaj commented Mar 1, 2023

@amycole501 this is ready for your review. Here's the preview link.

Interested in hearing if these labels are read and if that experience is good.

@amycole501
Copy link

I can confirm that using JAWS the words "external link" were read on all three link examples. From a usability standpoint, the third link was best. The first link example announces the brackets first, the second one mentions a colon but the third one only says "external link" along with the link wording and that's easiest to understand.

In Narrator all three links announced the same as the third link. So if given the choice, I'd go with how you coded the third link.

@mejiaj mejiaj marked this pull request as ready for review March 6, 2023 19:13
@mejiaj mejiaj requested a review from amyleadem March 6, 2023 19:13
Copy link
Contributor

@amyleadem amyleadem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this. Feels like a straightforward solution and it works well in VoiceOver.

One thing that might be worth considering is adding a comma to the end of the default content ($theme-external-link-sr-label: "External link,"). It seems to give a tiny pause in between the pseudo text and the link text, which I found helpful. But it should be fine to move forward as-is.

Tested on VoiceOver in Chrome, Safari, Firefox, and Edge.

Also, the preview link is broken in the description. It looks like you removed the test story, so I went ahead and tested just on the main link component story.

@mejiaj
Copy link
Contributor Author

mejiaj commented Mar 9, 2023

@amyleadem thanks for the reminder on the preview link, I've added a comment and a new preview.

I was hesitant to add any punctuation to affect RTL sites. That said, we don't have data on how common this use case is. Open to adding comma.

@mejiaj mejiaj requested a review from thisisdano March 9, 2023 18:23
Copy link

@amycole501 amycole501 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do hear "external link". The only note I'd add is if the external link opens the visitor to a new window. That does also need to be announced. If it opens the external link in the same window nothing additional needs to be announced.

Copy link

@amycole501 amycole501 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things to consider:

  1. If someone is implementing the external link feature and the link opens in a new window, the person who adds the link needs to add some sort of way for a screen reader to announce it opens in a new window. Some guidance is here https://www.w3.org/TR/WCAG20-TECHS/G201.html
  2. Consider also if someone is implementing this link feature using a CMS-driven environment. Not all WYSIWYG editors allow the user to add link help text or descriptive hints that say "link opens in a new window". Not sure of the solution but wanted to raise it as a potential scenario.

@mejiaj mejiaj requested review from amycole501 and amyleadem April 7, 2023 18:24
</p>

<p>
This is a link that opens in a <em>new</em> tab and goes to an <a class="usa-link usa-link--external" rel="noreferrer noopener" target="_blank" href="https://i.giphy.com/media/WPzQF6ruiIIVzHNlwX/source.gif">external website</a>.
Copy link
Contributor Author

@mejiaj mejiaj Apr 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've explicitly added rel="noreferrer noopener" as a best practice; even though most modern browsers implicitly add it.

image
MDN Browser compatibility →

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a best practice, would it be beneficial to include guidance on noreferrer noopener in the documentation?

Copy link
Contributor Author

@mejiaj mejiaj Apr 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've kept noreferrer since only one is needed in [e348c59], but it might not be needed at all since modern browsers add it implicitly.

Either way, I've added it in guidance on site:
uswds/uswds-site#2056

Copy link

@amycole501 amycole501 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Listened in JAWS and used ANDI to verify the external link text was announced. Sounded good, clear, and was easy to understand.

Copy link
Contributor

@amyleadem amyleadem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this addition. The technical solution feels clean and the readout is helpful. I like that it doesn’t require any extra user action when setting up a link and that the readout copy is customizable.

Confirming that the VoiceOver readout is “link, external link, opens in current tab [link text]” or “link, external link, opens in new tab [link text]”, depending on the link target.

Added a few comments but no action is needed.

  • Confirm that customizing the new theme settings updates the text as expected
  • Confirm that VoiceOver identifies external links
  • Confirm that VoiceOver identifies if the link opens in a new window

</p>

<p>
This is a link that opens in a <em>new</em> tab and goes to an <a class="usa-link usa-link--external" rel="noreferrer noopener" target="_blank" href="https://i.giphy.com/media/WPzQF6ruiIIVzHNlwX/source.gif">external website</a>.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a best practice, would it be beneficial to include guidance on noreferrer noopener in the documentation?

@@ -123,6 +123,11 @@ $theme-in-page-nav-margin-left: 4 !default;
$theme-in-page-nav-margin-top: 2.5 !default;
$theme-in-page-nav-top: 4 !default;

// Link
$theme-external-link-sr-label: "External link" !default;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No action is required on this, but wondering if we can reduce some audio redundancy by removing the word “link” here so that it is just “External”. In Voiceover, that would mean the readout is “link, external, opens in a new tab [link text]”. I am not sure if other screen readers announce “link” in the same order though, so this might just reflect a VoiceOver bias.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amycole501 did you notice this issue on NVDA/JAWS? If so, I can shorten it to just "External".

@@ -2,7 +2,13 @@

<p>This is <a class="usa-link usa-color-text-visited" href="javascript:void(0);">a visited link</a>.</p>

<p>This is a link that goes to an <a class="usa-link usa-link--external" href="https://i.giphy.com/media/WPzQF6ruiIIVzHNlwX/source.gif">external website</a>.</p>
<p>
This is a link that opens in <em>current</em> tab and goes to an <a class="usa-link usa-link--external" href="https://i.giphy.com/media/WPzQF6ruiIIVzHNlwX/source.gif">external website</a>.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No action needed, just noting that opening source.gif is still a surprise every time

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that @amyleadem mentions it yes, it does say "link" twice (which is tricky to discern since some of the links say "link" in them.

Additionally, I hear JAWS trying to say the word "tab" which runs into the phrase "external website" both in ANDI and in JAWS. I'm attaching how it looks in ANDI so you can get an idea of how it sounds. Like a run-on sentence.

external link text

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amycole501 @amyleadem I've added the following changes:

  • Simplified the CSS
  • Removed the base variable $theme-external-link-sr-label.
  • Added punctuation to the label ex: "External, opens in a new tab." to prevent screen readers from jumbling the words together.

@mejiaj mejiaj requested a review from amycole501 April 10, 2023 13:57
James Mejia added 2 commits April 10, 2023 09:12
- Remove base variable `$theme-external-link-sr-label`
- Use punctuation to prevent run-on sentences in screen readers
@mejiaj mejiaj requested a review from amyleadem April 11, 2023 17:22
Copy link

@amycole501 amycole501 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds much better; the words aren't jumbled together and it's clear when listening in JAWS that the links open either in the same/current tab or a new tab.

Copy link
Contributor

@amyleadem amyleadem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good improvements!

FYI - I made a small commit (a00a4ed) to add a missing "the" to a sentence in the twig file. I also updated the PR description to reflect the new default values and descriptions for $theme-external-link-sr-label-tab-new and $theme-external-link-sr-label-tab-same.

Copy link

@amycole501 amycole501 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good

@mejiaj mejiaj requested a review from amycole501 April 13, 2023 15:07
@thisisdano
Copy link
Contributor

I'm going to draw up a changelog PR for this one

@mejiaj
Copy link
Contributor Author

mejiaj commented May 10, 2023

I'm going to draw up a changelog PR for this one

@thisisdano I tried to get a head start by creating a draft PR in site USWDS - Links: Update external link guidance #2056.

@thisisdano thisisdano merged commit 413f1db into develop May 10, 2023
@thisisdano thisisdano deleted the jm-external-link-sr branch May 10, 2023 21:18
@thisisdano thisisdano mentioned this pull request Jun 6, 2023
@aduth
Copy link
Contributor

aduth commented May 29, 2024

I'm curious about the choice to announce the label before the link text. Most guidance I've seen (including WCAG G201) announces the label after the link text, which makes sense to me because it's a supplementary detail, where the primary detail is the link text itself. And I'd worry it might be slightly disorienting to announce that something will open in a new tab before even knowing what it is that'll be opened in a new tab.

In terms of backwards-compatibility, I found my way here after realizing that our external links were announcing "opens in new tab" twice to screen readers, since we had already implemented this type of label before USWDS, so now we have a redundant label. This was somewhat unexpected. Related to my next point, we may just end up disabling the setting by setting it to an empty string, though this seems to work only by accident rather than being fully supported.

Lastly, this seems to assume a site is English-only. Our site supports multiple languages, and it's not obvious how we'd be expected to use these labels. In our case, we may just "disable" the setting by configuring it to an empty string and continuing to use our custom implementation. The only alternative I could imagine is creating language-specific stylesheets, each with the Sass variable assigned to the label to be used in that language.

@mejiaj
Copy link
Contributor Author

mejiaj commented May 29, 2024

@aduth good points. I've created #5942 to capture your suggestions.

It makes sense to place the label after and allow devs to opt out.

Another potential alternative is to use the attr() - MDN to allow users to pass their own strings via CSS. The only downside is it'd have to be manually added per link. We hope to address this type of feature the web component implementation.

Initially, this was added to allow basic support of announcing links with further enhancements based on feedback. @jaclinec have we tested or are planning to test links?

@jaclinec
Copy link

@mejiaj we tested links in 2021 (see research findings), but the research did not include participants who use screen readers so it may not be useful to this conversation. We don't have immediate plans to test links for accessibility but it is in the backlog.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

External links are not indicated on screen readers
6 participants