In-Page Links and Input Focus [Again]

That in-page links work and properly update the page's input focus can be crucial for users that rely on keyboard navigation, especially if they do not also use a screen reader. Often discussed in the context of "skip links", this has been something of an issue for years, the various reasons for and effects of which have been documented well enough by the likes of Jim Thatcher, Gez Lemon, Mike Cherim, WebAIM, and others.

To have a semi-comprehensive overview of how in-page links are behaving in current browsers, with and without screen readers, I threw together a quick test. Much of this should be familiar, but I figure it's always nice to have something to refer to.

It should be noted that Internet Explorer is not the only browser that had or has issues with different in-page link markup, as the results below demonstrate. It's also the case that how a browser behaves with internal page links is not necessarily the same when a screen reader is thrown into the mix. Wouldn't it be grand if we could simply add an id to an element and thereby use it as an anchor in all browsers and screen readers?

The Test

The page used for the test implements the following types of in-page anchors:

  1. a element with @name
  2. a element with @name in div with height
  3. a element with @name and tabindex="-1"
  4. a element with @id
  5. a element with @id in div with height
  6. a element with @id and tabindex="-1"
  7. a element with @name and @id
  8. a element with @name and @id in div with height
  9. a element with @name, @id and tabindex="-1"
  10. heading with @id
  11. heading with @id in div with height
  12. heading with @id and tabindex="-1"

Each of the a elements in the test page contain text, but I did also perform all of the tests with empty a elements as well, and there was only one minor instance where the results were different: SAToGo in IE8 will not properly update focus where an in-page link targets an empty a element with an id attribute and tabindex="-1".

Where a target anchor is found within a "div with height," this means it is wrapped in a div styled with height="100%" in order to set hasLayout in Internet Explorer, which is needed for IE to properly update the input focus position. The same effect is also caused using tabindex="-1".

The browsers tested were Internet Explorer 8, Firefox 3.6, Safari 4.0.3, and Opera 10.53. Each of these was tested using just the keyboard. In the case of Internet Explorer and Firefox, these were also tested with JAWS 11, Window-Eyes 7.11, NVDA 2010.1. Safari was tested with VoiceOver in Snow Leopard.

The Results

Below is a (rather wide) table summarizing the results. A "yes" indicates that the in-page link works and input focus is properly updated. That is, after activating the link, pressing TAB (or the appropriate keyboard shortcut in Opera or keyboard command in VoiceOver) moves focus to the link following the relevant target anchor. A "no" indicates that this does not happen. And in Opera's case, a "partial" means that it properly updates input focus most of the time, but this depends on both the use of rather specific keyboard shortcuts, and the position of links on the page relative the browser's viewport. Be sure to see the notes following the table.

Note: It's important to remember that these results are from May 2010, so things may have changed with some of the browser behaviours since then. For instance, after these tests were performed, behaviour in some later versions of Safari and VoiceOver changed for the worse. See the update regarding Safari and VoiceOver below.

Results Table
IE and Keyboard IE and JAWS IE and Window-Eyes IE and NVDA IE and SAToGo FF and Keyboard FF and JAWS FF and Window-Eyes FF and NVDA FF and SAToGo Safari and Keyboard Safari and VoiceOver Opera and Keyboard
1. a element with @name no no yes no yes yes yes no yes no no yes partial
2. a element with @name in div with height yes yes yes yes yes yes yes no yes no no yes partial
3. a element with @name and tabindex="-1" yes yes yes yes yes yes yes no yes no no yes partial
4. a element with @id no no yes no no yes yes no yes no no yes partial
5. a element with @id in div with height yes yes yes yes no yes yes no yes no no yes partial
6. a element with @id and tabindex="-1" yes yes yes yes yes yes yes no yes no no yes partial
7. a element with @name and @id no no yes no yes yes yes no yes no no yes partial
8. a element with @name and @id in div with height yes yes yes yes yes yes yes no yes no no yes partial
9. a element with @name, @id and tabindex="-1" yes yes yes yes yes yes yes no yes no no yes partial
10. Heading with @id no no yes no no yes yes no yes no no yes partial
11. Heading with @id in div with height yes yes yes yes no yes yes no yes no no yes partial
12. Heading with @id and tabindex="-1" yes yes yes yes no yes yes no yes no no yes partial

Notes

Opera 10.53

Opera only gets a "partial yes" in each case. Opera does not implement the normal TAB and Shift+TAB keyboard functionality for navigating links on a page. This is not a problem in itself as Opera provides a number of its own browser-specific keyboard shortcuts that, truth be told, are pretty extensive and normally very useful. However, in the case of in-page links, Opera's relevant "link key" (i.e., Ctrl+down arrow) and "single-key shortcut" (i.e., A) do not respect the updated page focus after selecting any in-page link. Instead, using these keys will set focus to whatever link immediately follows the in-page link you just selected, and not the link following the destination target anchor.

Only by using Opera's "spatial navigation keys" (e.g., Shift+down arrow) will focus move properly to the link or control following the selected target anchor, but only if that link or control happens to be at the top of the browser's updated viewport after activating the in-page link. That is, if there are any links on the page between the destination anchor of an in-page link and the top of the updated viewport, pressing Shift+down arrow will move focus to the link or control nearest the top of the viewport, and not necessarily that following the selected target anchor in sequence.

To witness this in action, visit the test page in Opera and make sure the browser's viewport is at least 600px high. Then select in-page link #12 from the list of links at the top of the page. The viewport will scroll to the bottom of the page, but the target anchor for link #12, which is a heading with an id attribute and tabindex="-1", will not be at the top of the viewport. At this point, pressing Shift+down arrow will move focus to the first link at the top of the updated viewport, which is not the link following the selected target anchor and to which one would expect focus should be set.

Fortunately, Opera is aware of the situation, so we might see this behaviour corrected soon enough in an upcoming update.

Window-Eyes

In IE8, headings with tabindex="-1" register as editable controls and can be navigated by pressing C and Shift+C. On the other hand, in FF3.6, focus just always jumps to some seemingly random place on the page, so there is basically no using in-page links with Window-Eyes in Firefox.

NVDA

In IE8, and similar to Window-Eyes, headings with tabindex="-1" register as edit fields and can be navigated by pressing E and Shift+E. Additionally, NVDA enters "application" or Virtual Buffer Pass-Through mode when setting focus to one of these headings. This does not happen in FF3.6, where everything is hunky-dory.

VoiceOver

With VoiceOver running, using the TAB and ENTER keys won't fully set focus to the link's target anchor. But everything works just fine using the appropriate VoiceOver keyboard commands for navigating and activating links.

Update (January 22, 2011): It appears that while VoiceOver with Safari 4.0.3 in OS X 10.6.3 worked as expected in terms of setting focus following the activation of an in-page link, tests of VoiceOver with Safari 5.0.3 in OS X 10.6.6 reveal a problematic change in behaviour. In Safari 5.0.3, activating an in-page link and having focus move to the link's target seems to work only once on any page and only if the page has not been loaded with a fragment identifier in the URL. In effect, if focus has been moved to a location in the page specified by a fragment identifier, either on page load or from having followed an in-page link, it seems that activating a subsequent in-page link will no longer properly move focus to the link's target on the page. I have notified the Apple Accessibility team of this issue.

One Response to In-Page Links and Input Focus [Again]

  1. 1. kn33ch41:

    This is a great article!

    There is a way to force Opera to naturally use the tab key for navigating anchor tags. Define tabindex=”0″ on them all; of course, this would be best added with a script on page load.

Comments are now closed.