Skip to search Skip to main content

Does the <body> rule the mind or does the mind rule the <body>?

Indecisive Skip Links and their Targets – the Renaissance of the <hr> Element

Posted

Updated

Do not forget
They tried to turn you
Into a public target

Morrissey, “I am not a Dog on a Chain”

Sometimes, it is easy to identify the position of skip links. Mostly when content blocks follow with a lot of interactive elements, or just a lot of content. But what about their target? Do you always know where to skip to? Do you know what follows your widget, component or element? There are many articles about skip links, but none about their targets. Maybe this is the first…

TL;DR

  • Skip links are great for keyboard users to bypass blocks that contain a lot of interactive elements, like links, buttons, form fields and controls etc.
  • Sometimes skip links can have dynamically changing targets.
  • The <hr> Element is a perfect target for “indecisive skip links”.
  • Jump directly to the working code example.

Recently I developed a component that consisted of an extensive list of at least 20 individual linked elements and each element featured at least two corresponding buttons. So in total at least 60 interactive elements per list. For me it was immediately clear: this list needs skip links at the beginning and at the end to skip the load of interactive elements.

All of you might know about skip links as one of the key accessibility features for websites. They are one of the tools that help you ensure you provide a method to “bypass blocks”, like it is required in WCAG 2.1 success criterion 2.4.1. A lot of good stuff was already written on them by fellow authors. I recommend the following articles on skip links, if you are new to the topic and want to dive deeper:

  1. Skip Navigation Links by WebAIM
  2. Skip Links are important by Nicolas Steenhout on Knowbility
  3. How to create a “Skip to Content” Link by Paul Ryan on CSS Tricks

My colleagues asked me: “Why do we need a skip link here?” In order to make my answer a little more impressive, I always refer to the image of Stephen Hawking.

A Bunch of interactive Elements can make In-Page Navigation tedious (for some)

The prominent (recently unfortunately deceased physicist), who was dependent on a wheelchair due to his ALS (Amyotrophic Lateral Sclerosis) disease. He had a computer integrated in the wheelchair, whose voice output functioned via a switch, which Hawking controlled only via movements in the cheek muscles.

One only has to imagine how tedious it can be to skip 60 links and buttons or more with such a device to move forward in the document if you have to activate a switch 60 times via your cheek. A picture that always reminds my colleagues of the importance of these little helpers.

The technique to add skip links to certain blocks with a lot of content or interactive elements is furthermore described at W3C (World Wide Web Consortium). The special feature for my use case is: the target should be very flexible. The elements that follow the block are often unknown and can change during user interactions, so there was no fixed position for a target here. But a skip link needs a target and all users should be able to use it and not jump into a <div>– or <span/>-Nirvana.

So I asked myself:

Where do I jump to with my skip link?

A more precise specification of the target could help answer this. The target should be:

  • Flexibly placeable in the document.
  • Have a semantic background, so assistive technology like screen readers will have easy access to it as well.
  • Be accessible on :target for keyboard users to see where they just jumped.
  • Be able to work as a standalone component, easily connected to its skip link component.

And still some more questions came up here:

Why not jump to the next Element in the Flow?

As I mentioned earlier, the upcoming element in the content is not necessarily known. It may be that this changes through user settings or that elements and information are added through special interactions. Like in a form that adds fields dynamically. In a component-based environment (as in frameworks like React or Vue), this is often the case and most of the time one component is not supposed to know about the other. So the target should be able to be positioned between two components.

Why not jump to the next Skip Link itself?

This might be strange for some, because you jump between two links without knowing where you actually are in the document. The links should contain information about their position or similar then. But that feels like too much information on one element that is used for in-page navigation.

At the end of the workday I lay down in the bathtub and suddenly had the brilliant idea: Why not use a <hr> element?

Short Excursion: the <hr> Element, also known as Horizontal Rule

<hr> is a pretty old fellow among the other HTML (Hypertext Markup Language) Elements and has been part of it since the HTML 2.0 specification dating back to November 1995. The current HTML specification lists it at section 4.4.2.:

The hr element represents a paragraph-level thematic break, e.g. a scene change in a story, or a transition to another topic within a section of a reference book.

Oliver James describes a typical use case for <hr> like this:

The <hr> element is a “horizontal rule”, which represents a thematic break. The transition from one scene of a story into the next or between the end of a letter and a postscript are good examples of when a horizontal rule may be appropriate.

“Transition” sounds exactly like the thing I needed here.

Make the <hr> Element work as a Skip Link Target

So what should it look like in the Markup?

  <hr id="list-bottom" aria-label="Bottom of the list" class="skip-link-target" />
  • The id attribute for making a skip link “jump” possible. Make sure it’s unique on a document level.
  • The aria-label attribute that contains its accessible name.
  • The class attribute provides special styles for visual use. See the section about styling.

Why do I use aria-label here?

The <hr> can be visually determined as a horizontal line between content blocks. So there is no need for any more descriptive text here, except for screen reader users. It’s easier to understand for them where they are in the document when they just jumped there via a skip link.

I tested with the screen readers NVDA (NonVisual Desktop Access), JAWS (Job Access With Speech) and TalkBack (all current Version, October 2021). All browsers were uptodate.

Screen reader behaviour in different browsers
Screenreader Browser Output
NVDA Chrome “Bottom of the list
Separator”
NVDA Edge “Bottom of the list
Separator”
NVDA Firefox “Bottom of the list
Separator”
JAWS Chrome “Bottom of the list
Separator”
JAWS Edge “Bottom of the list
Separator”
JAWS Firefox “Bottom of the list
Separator”
TalkBack Chrome “Bottom of the list
Separator”
TalkBack Firefox Doesn’t recognize the <hr> at all

Short note on that: If you have information on the output in other screen reader / browser combinations I would be very happy if you let me know.

Styling the Skip Link Target

.skip-link-target {
  width: 1px;
  height: 1px;
  margin: 0 auto;
  border: 0;
  border-top: 1px solid transparent;
  background-color: transparent;
  transition: all 0.5s ease;
  transition-property: width, margin;
}

@media (prefers-reduced-motion) {
  .skip-link-target {
    transition: none;
  }
}

.skip-link-target:target {
  height: 2px;
  width: 50%;
  color: #000000;
  background-color: #000000;
  margin: 2rem auto;
}
  • width, height and border-top are important, otherwise some screen readers don’t recognize the <hr>.
  • With @media (prefers-reduced-motion) we reset the transition, because we want to respect user settings concerning animations and motion.
  • I’m adding margin-top and margin-bottom to make sure that the <hr> is visible enough at the edge of the viewport of the document, when jumped up to.

If you want an in-depth article on the styling and semantics of the <hr> element, I deeply recommend Sara Soueidan’s “Not Your Typical Horizontal Rules” where you learn how to style those elements in a truly fancy way and get to know semantic alternatives to them.

Sidenote

A perfect solution for me would have been to make the skip link visibility: hidden, and then on :target visibility: visible again. That, because I think a screen reader user only needs the information about the additional targets here if they jumped here via the corresponding skip link.

But this doesn’t work: visibility:hidden makes the <hr> completely inaccessible for screen readers and any CSS (Cascading Style Sheets) changes on :target don’t fire fast enough, so some screen readers don’t recognize the target at all, even in current :target situations.
So I decided to make the target recognizable for screen readers in advance as well and visibly recognizable only on :target, because they are mostly visibly important for keyboard only users. Sighted screen reader users might benefit here as well.

Working Example

You will “find” the skip links while pressing Tab and Enter on the skip link. Then the <hr> target will appear.


See the Pen Indecisive Skip Links and their Targets by Accessabilly (@accessabilly) on CodePen
1

Conclusion

The <hr> element might have been forgotten or got lost in the Nirvana of <span/> and <div> elements that modern templating frameworks and the developers who work with them create. It still has its justification even more than 25 years after its invention. This article shows that you can use it as a skip link target and how to handle this. I hope I have been able to show you one of the many use cases for the <hr> element and maybe one you haven’t thought of before.

Further Reading

Leave a Reply

Your email address will not be published.