Supercharge Screen Readers with an Invisible Header Link!

The Screen Reader Accessibility Problem

By default, screen readers read from left to right, top to bottom. With my menu in the right sidebar, I had an accessibility problem. Since my main content came before my menu, how could I make it quick and easy for screen reader users to access my menu when they wanted to? Default behavior was not good enough. The solution was to create a “jump to menu” link.

I could have moved my menu to the top or the sidebar on the left. Either solution would solve the problem. However, I wanted my navigation menu to stay on the right side. The menu is near the vertical scrollbar, so a mouse user would not have to move far to get from one to the other. Even better, the menu stays in view on the right no matter how far down one scrolls. It is very efficient, if you can use a mouse.

To skip over a top or left menu, my theme had a “skip to content” hidden link just for screen readers and keyboard-only users. You could skip the menu if you wanted to. You would not know the shortcut link was there unless your text-to-speech software read it to you or you tabbed to it, at which point it would become visible. That link did not have much to skip if the content came before the menu; just my logo and site title, which were themselves links.

Apparently, my theme, which had an option to put the menu on the right, lacked a quick way for keyboard-only users to jump there. To support my stubbornness, I needed a bit of PHP code. I suspect there’s a plugin for modifying headers that can do the same thing, but it’s such a small amount of code that I saw no reason to search for a plugin.

The Goals

There were two basic things I needed to accomplish:

  1. Put the link at the top left of the page.
  2. Make the link visible only to screen readers and those who navigate by keyboard (at the point where they have selected the link. Naturally, it would be quite unfriendly to allow people to select a link without showing them what has been selected.)

WordPress Hooks to the Rescue

WordPress has a number of hooks that allow you to insert code into a number of places during WordPress’ rendering of your page. One of these is the “wp_head” action hook, whereby you can do whatever you want just before WordPress displays the header section.

Update: I asked ChatGPT4 if “wp_head” was the best action hook for skipping to a sidebar or menu on the right side of the page. Here is what it said:

While wp_head hook could technically be used to add a “skip to sidebar” link, it isn’t the most semantic or accessible location. The wp_head hook is typically used to add meta tags, scripts, and other elements to the head section of a webpage, which isn’t displayed in the webpage’s content.

A better hook to use would be get_header or wp_body_open. The get_header hook fires after the opening HTML document tag and after the head section but before the body section. The wp_body_open hook is fired just after the opening body tag.

ChatGPT4 in conversation with me on May 31, 2023.

Therefore, I have updated this article to use the “wp_body_open” hook. The syntax for adding this action hook is this:

add_action('wp_body_open', 'name_of_my_function');

where ‘name_of_my_function’ should be replaced by a more descriptive function name. I called it ‘mjb_go_to_menu’ (rather than just ‘go_to_menu’ to lessen any potential conflict with a plugin or theme).

Of course, inside my function I needed to put the HTML that would make my link appear:

function mjb_go_to_menu()
{   
  echo '<a href="#menu-main-1">Go to Menu</a>';
}

All that the function is doing is echoing HTML code for a link to another element on the page, in this case, to the menu with the CSS ID, “menu-main-1”. With that and the previous code in my child theme’s functions.php file, the page now shows the link and correctly jumps me to the right spot on the page, but it is not hidden yet.

Most WordPress themes includes a class just for hiding text from sight while showing it to screen readers: “screen-reader-text”. All I had to do was give my anchor tag (“<a>”) this class, so the code now looks like this:

function mjb_go_to_menu() {
      echo '<a class="screen-reader-text" href="#menu-main-1">Go to Menu</a>'; 
}
add_action('wp_body_open', 'mjb_go_to_menu');

The code works!

(If yours doesn’t, make sure the <a> link tag has the “screen-reader-text” class on it rather than on a different HTML tag. Links get focus; other tags normally do not. Although you can force them to get focus using the “tabindex” attribute, that can introduce other accessibility problems.)


Need an experienced coder to help? Contact me!

Leave a Comment

TOC