7

I have the following requirements:

On my webpage there are anchor links for navigation (thinks like skip to content etc.). These anchors are supposed to bring the target element into view and focus it. (Focus is important, because else screenreaders don't get positioned correctly. so far my code looks like this:

<a href="#content" class="navbtn">Skip to content</a>
<!-- somewhere else...-->
<div id="content" tabindex="-1">
Lorem ipsum...
</div>
<script>

$(".navbtn").click(function(e) {

    e.preventDefault();

    $("#content").focus();
});

</script>

Please note that I'm aware this is hardcoded and I'll change that in the future, but for test purposes I left it to this.

OK, so what does this do? In this post the method above was said to focus the div element. Visually I cannot judge, but my screenreader won't move to the element (I'm using VoiceOver in Safari on an iPhone). If the target is a button, a link or any other element which has a tabindex by default, it works fine.

Any ideas?

EDIT: I got it to wolk with my braille display when pressing the left mode key. I usually use the right mode key to send a double tap event to the phone, but the right one doesn't work. The left one, however, does. I don't know why, to be honest. Double tap onscreen still doesn't work... Either way, no JavaScript needed.

TimB
  • 970
  • 8
  • 17

5 Answers5

6

I've just tested the following (with no JavaScript) on an iPhone running iOS12, with VoiceOver in Safari:

<a href="#content">Skip to content</a>
...
<div id="content" tabindex="-1">Target content...</div>

It worked as expected, with focus moving to the target content and VoiceOver announcing "Target content...". Can you describe the steps you're taking when you test in more detail?

  • My code looks exactly like yours. I navigate to the link with my braille display, then press the braille display key that equals a double tap. Focus does not move. I'll test using the screen only, however. – TimB Jan 01 '19 at 12:25
  • Even when just using the screen, it doesn't work. If I doubletap the link it says "reader available" and that's it, focus does not move (using VO, Safari, iOS 12.1.2) – TimB Jan 01 '19 at 12:31
  • Based on the fact you're hearing "Reader available", it may be that the page you're testing on is triggering Safari's [Reader feature](https://www.imore.com/how-use-reader-view-safari-iphone-and-ipad), and it's getting in the way of your interaction? – Léonie Watson Jan 02 '19 at 13:30
  • Is there some way of avoiding this? – TimB Jan 02 '19 at 13:34
  • It's a browser feature, so it'll be up to the user to dismiss it I think. – Léonie Watson Jan 04 '19 at 19:58
  • Oh geez... Well. I guess I'll just leave VO be, then... Not ideal, but I offer loads of alternative navigation. – TimB Jan 04 '19 at 21:26
5

You're doing too much work. By default, an <a> will move the focus for you. However, if the destination element is not a natively focusable element, then it must also have tabindex="-1" for some browsers (mainly Internet Explorer). See "Accessible HTML Elements" in "About Active Accessibility Support" for the reason why.

So your above example will work with simply:

<a href="#content" class="navbtn">Skip to content</a>
<!-- somewhere else...-->
<div id="content" tabindex="-1">
Lorem ipsum...
</div>

No javascript is needed. You can test it by using the keyboard to tab to the "Skip to content" link then pressing enter. If you then press tab again, the focus should move to whatever focusable element is after your <div>.

If you then shift+tab, you will not go back to the <div> (which is the behavior you want) because it has tabindex="-1" instead of tabindex="0".

I use this pattern all the time in my accessible websites.

However (and this is a big "however" and I think is the main point of your question), VoiceOver on iOS (not sure about the Mac) will not honor the focus change. That's a bug (in my opinion) with Apple. Go to any website that has in-page links and the VoiceOver focus won't move the destination element. You can see one reference to this problem at https://www.applevis.com/forum/ios-ios-app-discussion/skip-link-issue

Unfortunately, you should write your code using the simple example (no javascript required) and VoiceOver users on iOS will continue to have a problem like they have on all other sites.

slugolicious
  • 15,824
  • 2
  • 29
  • 43
  • What confuses me (and lead me to the assumption there was a way to work around this), is that on certain pages (for example SELFHTML) focus movement on Anchor links appears to work... – TimB Dec 31 '18 at 07:52
  • Hmm, that is strange. I tried wiki (https://en.wikipedia.org/wiki/Puppy) and when I selected "Development" (the first item under the table of contents), it moved my VoiceOver focus to the development section correctly. Wiki does **not** use `tabindex="-1"` so their page does **not** move the focus properly on Internet Explorer. Perhaps the `tabindex="-1"` is what's causing the problem for VoiceOver. (**Note**: If you try the wiki url in this comment from iOS, it might take you to the mobile version. Go to the last link on the page, "desktop", to go to the deskop version to test.) – slugolicious Jan 01 '19 at 19:13
  • I now have divs with and without tabindex and currently none work, regardless whether I doubletap onscreen or use my braille display. But a while ago it definitely worked (with tabindex) when I used the left mode key... – TimB Jan 01 '19 at 19:20
2

Voiceover on iOS will not honour JavaScript focus changes on most elements that aren't natively focusable regardless of setting tabindex="-1" or tabindex="0". If you need to have shifting focus for iOS then what I have done is add an empty tag and set the focus to that, it's not the best solution but it's the only one available on iOS for now.

alex
  • 71
  • 4
1

Use tabindex="-1" on the div instead of tabindex="0". It will make the div programmatically focusable, whereas tabindex="0" makes it user focusable (as someone uses the tab key to move through the content). More on Using the tabindex attribute

  • I read the article you posted and also did more research, but whether it's tabindex="0" or tabindex="-1" - if I click the link, nothing happens. If the target is a button, or link, or the like focus gets moved appropriately... but not if it's a div. – TimB Dec 31 '18 at 00:01
0

This would always be best:

<a href="#content">Skip to content</a>
...
<div id="content" tabindex="-1">Target content...</div>

But sometimes you need some extra functionality so I add a keypress to make sure it triggers a click. Keycode 32 is for the space bar and the 13 is for the enter key.

$(".navbtn").click(function(e) {

    e.preventDefault();

    $("#content").focus();
});

$(".navbtn").keypress(function(e){
            if(e.which == 32 || e.which == 13 ){
                $(".navbtn").click();
            }
        }); 

Or you can just have the keypress trigger the focus

Gcamara14
  • 510
  • 4
  • 14