Prevent browser from re-positioning focused elements navigated to via tabbing
Asked Answered
C

4

10

When you navigate through form elements or anchors using the tab key (and shift + tab) the browser automatically scrolls to that focused element. If the element is not viewable because it is a part of an overflown content where overflow is set to be hidden, it moves (or scrolls) the content's container to reveal the focused element. I want to either stop or find a way to negate this behavior

Here's something I put together to showcase the issue. I reproduced it in Chrome.

https://jsfiddle.net/charlieko/wLy7vurj/2/

var container = $("#container")
var cur = 0;

function go(increment) {
  var next = cur + increment;
  if (next < 0) next = 4;
  else if (next > 4) next = 0;
  cur = next
  var newX = cur * 500;
  container.css({
    transform: 'translate(-' + newX + 'px, 0)'
  })
}

$("#left").click(function(e) {
  go(-1);
});
$("#right").click(function(e) {
  go(1);
});
body {
  overflow: hidden;
}
#container {
  width: 2600px;
  overflow: none;
  transition: transform 0.4s;
  transform: translate(0, 0);
  overflow: hidden;
  margin: 0;
}
li {
  width: 500px;
  text-align: center;
  list-style-type: none;
  float: left;
  margin: 0;
  padding: 0;
}
a {
  color: black;
  font-size: 2.0rem;
}
#ui {
  position: fixed;
  top: 200px;
}
#ui span {
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
  <ul>
    <li><a href="#">Link 1</a> | ABCD EFG</li>
    <li><a href="#">Link 2</a> | HIJK LMNO</li>
    <li><a href="#">Link 3</a> | PQRSTU VW</li>
    <li><a href="#">Link 4</a> | XYZA BC</li>
    <li><a href="#">Link 5</a> | DEFG HI</li>
  </ul>
</div>
<div id="ui">
  <div>
    <span id="left">Left</span>
    |
    <span id="right">Right</span>
  </div>
  <p>
    Use left and right to move. Issue: Use tab key (and shift+tab) to navigate to any of the links. The container of the links shift to show the focused link. Notice the content is decentered when it happens.
  </p>
</div>

The issue is that now there are two ways to slide the contents: via interacting with the left|right buttons and via tabbing through the links. When the user chooses to navigate using the tabs it messes up the sliding logic. The content is de-centered, and the index I saved in a variable no longer represents what's visible on the screen. I can handle the accessibility issue programmatically using an onFocus event, so this automatic behavior isn't helping anything.

Is there a way to stop this behavior? I already tried preventDefault() method on onFocus events on the anchor elements.

Cygnus answered 5/4, 2016 at 18:28 Comment(2)
why are you physically shifting the elements, why don't you just animate it sliding over and then just hide it?Jackie
I do want users to use the tab key to navigate. Hiding it would prevent that right? I just want the tabbing navigation to not move the container the focused element is in, which messes up the logic I set up.Cygnus
C
11

I was able to figure out a solution. What the browser does is that it scrolls the direct parent of the overflowing content to the position so that the focused element is right in the center. Simply modifying scrollLeft property of the parent element did the trick. So in the onFocus event of the link:

function onFocus (e) {
    document.getElementById('content-parent').scrollLeft = 0;
    // Code for repositioning the content itself using transform with transition animation
}
Cygnus answered 13/4, 2016 at 15:52 Comment(1)
This will still allow the item to be tabbed to, it just prevent the browser from showing that it did this. This will probably cause people who are using the tab key to navigate on the page to become frustrated with the amount of tabbing required to get to the next element after this widget.Yul
A
0

Overflow:hidden is usually good for content which is intended to scroll and move, so preventing that will be difficult. If you want the Tab control to stay only on things which are visible (including any buttons or links that update your slider), then you'll need a different method of hiding your content in addition to (or instead of) overflow.

Try display:none on your list items until they are within the open/visible part of div#container. That removes them from the DOM (and therefore from keyboard focus) until you're ready. If you create a class called 'hidden' with just display:none in it, then the only script you'll need is to add/remove the class from the list item when the Left/Right controls are used. I'd edit your code sample to demonstrate but I'm on a tiny screen right now.

The problem then is that your keyboard users can't reach the Left/Right controls. If you change those to button or link elements, then they'll have keyboard support by default in every browser. And then all your users are relying on your Left/Right controls no matter whether they're using a mouse or the keyboard, which gives you more control over how it looks at each stage.

Aliment answered 7/4, 2016 at 11:37 Comment(1)
I think this is a good answer given my jsfiddle code and my question. I wasn't able to implement this solution because the actual app I'm working on has a specific design that does not really have the persistent left/right buttons.Cygnus
S
0

You could just set tabindex to -1 for the links to avoid focusing.

Strickle answered 7/4, 2016 at 12:3 Comment(1)
I still want users to be able to navigate using the tab key.Cygnus
T
0

You could set tabindex="-1" for elements that are off the screen. This is suggested by MDN.

https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex

Threewheeler answered 18/4, 2018 at 8:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.