skip to Main Content

My website has carousel/slider panels with tabbed navigation. Each panel shows a "river" of book covers. 5 covers are shown at a time and clicking next/prev slides 3 books out and 3 new books in. The order of the books in the DOM doesn’t change, just their left position and their visibility.

<div class="books">
<a class="book"><img>#1</a>
<a class="book"><img>#2</a>
<a class="book"><img>#3</a>
<a class="book"><img>#4</a>
...
<a class="book"><img>#25</a>
</div>

For accessibility, i need to keep the tab order for keyboard navigation as [prev button][book 1][book 2][book 3][book 4][book 5][next button] even when prev/next is clicked.

The image shows my problem: if prev is clicked, three books slide in, but in the DOM they are books #23, #24, and #25. When tab is pressed, focus jumps to book #1 in the DOM, now positioned fourth from left.

slider panels displaying 5 book covers at a time

This is only a problem the first time prev is clicked, but it was still flagged as an accessibility problem. (I knew these kinds of sliders would be challenging for accessibility)

I tried setting the flexbox order dynamically when clicking prev and next, but found tab order is not affected by CSS properties. Setting the tabindex to 1, 2, 3, 4, 5 makes the book covers, halfway down the page, into the first focusable items of course– undesirable!

Is there something I’m missing about setting tabindex dynamically, so it’s restricted to its container somehow? My original slider design worked by actually moving items in the DOM, which presented its own issues. Is there any way to keep the focus order logical as the visibility setting of the books changes, without changing the DOM order? Am I missing an ARIA feature?

2

Answers


  1. Chosen as BEST ANSWER

    I thought I would share my solution in case someone ends up stumped like me.

    • Limit the books in the slider to something easily divisible. I chose 20, I was already limiting it to 25 and shuffling on reload.
    • Limit the views for different screen sizes to something that divides 20, in my case, 2, 4, and 5. I used to have a breakpoint where I showed 3 books, so I eliminated it
    • Move all of the visible books on every click. If 5 are visible, all 5 slide out on click. Formerly, I was sliding out either 3 or 1 based on screen size.

    With these changes, I didn't have to go back to moving the books in the DOM. The (visible) book with the lowest DOM order is always next to my Prev button, and the one with the highest DOM order is always next to Next. We stop running into the issue where books 22, 23, 24, 0, and 1 are visible and focus jumps to book 0.


  2. You haven’t missed anything. Tab order always follows DOM order, and there is only one way to break that, using tabindex>0.
    CSS only affect display, it can never have any effect on tab order.

    So basically, to keep a consistent tab order with what’s displayed in your carousel, you have the choice between moving elements in the DOM, or use tabindex>0.

    If you start using tabindex>0 at a single place, then you must add a positive tabindex value to every focusable item in the whole page in order to keep a consistent tab order everywhere (yes, including outside the sole carousel component).
    It’s certainly much more challenging to do, more fragile, and harder to maintain than moving elements in the DOM.

    The easiest solution would be to disable the prev button when you are at slide 1, and the next button when you are at the end. Or otherwise said, don’t make the carousel circular, infinitely scrollable or wrapping around on edges.
    By doing so, you are avoiding all problems! That’s probably not the answer you expected…

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search