When slider items contain links and when you tab through them the positioning of items gets all screwed up. Depending on browsers the position gets recovered or not screwed at all.
JSFiddle: http://jsfiddle.net/tu2xqtej/4/
Safari 8: Nothing gets screwed because the tabindex never reaches links within slider items. Not very accessible
Chrome 38: position gets screwed and does not recover when sliding again (with arrow or arrow keys)
Firefox 33: position get screwed but recovers when sliding again (with arrow or arrow keys)
IE11, IE10 and IE9: Behave the exact same as Chrome does
I'm sure the tabindex behaviour is not something you can really do anything about since it's browser behaviour.
I think some other slider libraries don't have this problem because they are positioning items with CSS "position" either relative or absolute where as Slick is using floats to position items next to each other.
How to solve this?
Using CSS "position" might come to the rescue. However, if you tab through the items the link will be selected but you will see nothing and it would appear if the 'tab' button isn't doing anything. At that point it's cycling through all the "invisible" positioned items. Not very accessible.
I think a better approach would be to see if you can listen (with JS) to the tabindex and have the slider animate when the focus is on a tab in a slide. However this would also mean that if you have three sliding items and there's only a link in the first and last item it would skip the rest and go to the last item immediately. This is also what happens in the second slider in my JSFiddle example. To fix that you would have to add a "tabindex" to every slide so you could easily always slide through each item. That's what I did in the third slider. However you would always have to go through each slide before you could continue when just using the keyboard. and this method is also not working in Safari.
Not sure if solvable and what the best solution would be. But thought I'd at least let you know that I ran into this problem and some ways I thought of solving this.
There is literally nothing I can do about this. It's devastating. See here: http://codepen.io/kenwheeler/pen/AlmcI
I'll take a look and see if I can force the slide to take the tab first, and then slide it in on focus
Man that's a bummer. How about looking for the current focused element and check if the next focusable element is within a slick slider? Then on keyup you could slide to that particular slide. Although you will probably have a problem finding out wether the keyup will go to the next or previous tabindex.
The tabindex for each slide might be the better solution. You could either make it a setting to enable/disable that functionality or only add the tabindex to slides when a link within slides is found. That way if you have a simple carousel/slider with just images you don't have to tab through the whole slider.
As an extra check I think it would also be wise to include some logic in the plugin to check if the slider has been re-positioned without using 'slick' functionality and the set the current slide index to the actually shown slide. This is not happening in my third slider example on the JSFiddle resulting in weird slider behaviour when sliding after tabbing to a next item. (for example tab to the third slide and then slide with the arrows, you will get empty slides at the end) This check could also only be done when a "tabindex" element has been found within the slider for performance reasons.
I don't have any suggestions at the moment, but this topic seems very related/relevant to https://github.com/kenwheeler/slick/issues/716.
This is indeed very related/relevant to #716
I've been thinking and tabbing through the carousel (tabindex on every slide) also explained in #716 feels like the best and robust solution. You have to make sure is that the slider is being activated (update the current slide-index without fade or slide effects (since slide is already in view) to make sure the tabindex and slider are in sync). Also going through the tabindex reversed is slightly problematic since the link within the slide will come before the slide's tabindex.and it will screw up the slider position (slider position will be fixed when reverse tabbing one more item to the actual slide)
The downside about this technique is that a keyboard user always has to tab through every item which could get a bit annoying when there are many slides.
I thought of a solution and created a JSFiddle for that:
http://jsfiddle.net/f9wd8thj/1/
Basically a "skip link" appears (only on :focus, built with CSS) to skip the whole slider and go to:
a: a "skip to the start of slider" link that also appears on :focus. Press enter to see effect.
b: skip to the next focusable element after the slider (not built in JSFiddle just an idea)
When going through tabindex in reverse you could:
a: show a "skip to the start of slider" link on focus which brings you to start of slider. Press enter to see effect.
b: automatically bring it to the start of the slider (however this is not something one might expect), Aslo not built in JSFiddle, just an idea.
That still leaves us with the reversed tabindexing within the slider itself when links are present. Might be a tough nut to crack. Also you're going to need two more options for the labels on the buttons to make sure you can use the plugin in your own language..
Now I'd like to help out but my JS skills aren't good enough to build the actual functionality. Hope my ideas are of some help. If you don't want to hear them anymore please say so and I will stop trying to pursue perfection ;)
@robinpoort That's clever--I like the skip links that appear for tab users. That seems like a good accessibility function.
But yeah, this stuff does get really tricky, especially given that you can mix the use of arrow keys as well as the tab key. I'll have to chew on this further.
Happy Thanks Giving... Added the ScreenReader & Keyboard Accessibility
http://jsfiddle.net/equinoxs/u5j2wcjs/1/
Please let me know your thoughts. I will create a pull request.
Thanks
Awesome! Great work :) Smart to use and set tabindex to -1. That way you never have to scroll through the whole slider either.
I've tested this on Firefox and Chrome now and stumbled upon the following bug:
When you are focused on a single slide (
Remember: box-shadow would be considered un-accessible for visually-impaired users since older browsers wouldn't be able to render it. I just tried to replace it with outline in that jsfiddle @robinpoort shared, but the outline doesn't get rendered on the main slide item (outline sits outside the box-model). but I think you can fix that by adding 2px padding to the slider track.
I would consider adding:
:focus {
outline: 2px solid #ff9900!important;
}
.slick-track {
padding: 2px!important;
}
instead of your box-shadow declaration, to make it properly accessible :)
The focus style is added to make sure the user the sees the current focussed element.
We can use the 1px dotted outline. This will make sure we have the web standard of focussed element.
@robinpoort:
Yes, we need to update the focus only for the slider list. (May be the first a || input || button || Current List )
The current HTML structure in the slick is little bit un-common for the tab-index to follow. The following would be perfect for ADA compliance.
Also, we may need to update the keyHandler so that it works anywhere inside the slick-container instead of just the list. This will make the slick more keyboard accessible.
Just my thoughts...
Thanks
I have made some minor tweaks to make it more accessible as per earlier note.
http://jsfiddle.net/equinoxs/1x8w9c3n/1/
_.$list.on('keydown.slick', _.keyHandler); //OLD
_.$slider.on('keydown.slick', _.keyHandler); //NEW
To avoid the above inside the form fields.
if(!event.target.tagName.match('TEXTAREA|INPUT|SELECT')) { // NEW
if (event.keyCode === 37 && _.options.accessibility === true) {
_.changeSlide({
data: {
message: 'previous'
}
});
} else if (event.keyCode === 39 && _.options.accessibility === true) {
_.changeSlide({
data: {
message: 'next'
}
});
}
}
Removed the focus from the slider wrapper
// if (_.options.accessibility === true) {
// _.$list.prop('tabIndex', 0);
// }
Please review and let me know your thoughts.
Thanks
Sorry for replying this late. Been very busy and away!
Anyways awesome work again :)
I will do some more extended browser testing once we are all happy and ready with this :-)
Regarding (3):
I agree with @robinpoort that it seems problematic to have the focus jump to the first focusable element when you're using the arrow buttons. That seems like a no-no from an accessibility standpoint (ie, it is potentially disorienting to have the focus jump like that), and it makes it impossible to easily cycle through slides using the arrow buttons via the enter/space key (which those with vision difficulties and/or using screen readers might do) because the focus immediately leaves the arrow key.
That aside, I could go either way, but I do lean a little more towards _not_ having the first focusable element automatically receive focus, and instead let the user tab once to put focus on that element. And that has the additional benefit of resolving the above problem as well.
One other thought: It seems like currently the focus moves from within a current slide to the prev button and then to the next button. I'm a little ambivalent about that and am wondering if it would be better for the order to be prev - slide contents - next? In some ways that seems more intuitive to me (and makes visual sense).
But one thing that just occurred to me regarding the arrow keys and the automatic element focus discussion is that if a user is navigating via the next button they then have to shift-tab to cycle backwards through the links in the slide. I'm not sure if that is the way to do it or not. This accessibility stuff is hard to get right (it seems).
If you all haven't already it'd be worth it to review the ARIA recommendations for tabpanel, as that seems to be the closest analog for sliders (per https://github.com/kenwheeler/slick/issues/716#issuecomment-62072030).
Overall, this is looking great though! Good work! :)
@robinpoort @msrafi Do you guys have this in a branch?
@kenwheeler That would be great.
@robinpoort @EnigmaSolved I agree regarding #3. From the UI aspects it may look great. But for any major content driven or enterprise level applications, only the anchor and form-elements are considered as focus-able elements. Any good solution?
@EnigmaSolved, You got the right point. As I mentioned earlier in my note, we should follow the below markup for smoother tab flow.
Previous Button
Slide
Next Button
Then the controller.
Thanks
@msrafi @EnigmaSolved I like the proposed markup so tabbing through will get you to the Prev button first. If we need some additional styling for that then that is something I actually can work on ;)
As for tabindex on slides. I think with these changes (using the negative tabindex for other slides) we can just remove the tabindex on the active slide. Having focus on elements you can't do anything with is quite useless and only creates the need to press the tab key an extra time ;-)
This would give us the following:
<prev button tabindex>
<slider tabindex> to make sure we can also use the left and right arrow keys on the slider
<slide><a tabindex> (or any other focusable element) If available, remember we can also have sliders / carousels with images only
<next button tabindex>
<controller><control tabindex>
Then the automatic focus on slides/focusable elements. I think it would be best to get rid of this? Then there's only the problem of getting to focusable elements within that 'new activated' slide. The solution would either to do nothing at all and just let the user tab (coming from prev button) or shift+tab (coming from next button or controller) back to the slide or we could use a key combination like up arrow only or ctrl+up arrow to set focus to the first focusable element within the current active slide (if focusable elements are available).
Thoughts?
Doing some testing with screen readers...
@msrafi def let me know the results
Did some research with screen-readers. I removed the focus from the first element and added the focus to the current active slide. The screen reader announces the details after making some minor changes.
http://jsfiddle.net/1x8w9c3n/12/
Made following changes in this version:
Let me know your comments.
Cool stuff!
Makes sense?
@robinpoort I understand the focus jumping will confuse the users. Thank you for pointing it out.
Here is another solution.
http://jsfiddle.net/1x8w9c3n/19/
The focus will not change for slider event handlers (Arrows & controllers). But if the focus is inside the slide child elements, then the focus will moved to current slider after the animation is done. Hope it make sense.
Thanks
Hey @msrafi
Totally makes sense and this is both looking and working awesome now!
I think I am done here for now.
Awesome I'll get this stuff in core after the holidays. Thanks @msrafi
Always welcome... Have a good holidays
Awesome work @msrafi!
Looking forward seeing this in the core :)
Happy holidays people!
@msrafi @kenwheeler One more note on the prev button, next button, slider and controller. Although this is working perfectly now it only allows us to style the elements a certain way.
Take the following examples:

The slick in this branch has a good accessible keyboard focus flow for 'Slider 1'. However the current stable slick way of doing things would be something like 'Slider 3' but then with the controller last and buttons first.
Maybe this is a discussion for another time and place but it might be wise to consider the following:
order: ['prev', 'slider', 'next', 'controller'] or order: ['prev', 'next', 'slider', 'controller'] etc.Not sure which of them would be better. Adding markup with JS make markup files harder to read though so adding it manually would be a good practice. But then it makes it harder fo more people to actually use slick.
Food for thought :)
@robinpoort Thats a nice concept you have here. I think we can do that. I will try something later this weekend.
@msrafi That would be cool :-)
Guys, I spent some time since last weekend and found the changes that I am making is affecting the performance when using it with breakpoints/resize. I would consider this would be a good to have feature with design dependency. But, we can close the accessibility issue and open it as a new feature. Will try later when I get more time.
Agreed let's handle this in a different issue:
https://github.com/kenwheeler/slick/issues/912
@kenwheeler Any chance the tabindex change is merged soon, so using tab-index doesn't destroy the slider anymore? Willing to help if needed.
This seems to be the relevant PR: #1146
Has this been addressed yet? I'm having the same issue as the original poster and it's almost 2017 here.. =\
I have a work-around that seems to work pretty well, but it feels hackish
camdagr8 - I don't think this has actually been fixed totally, at least for the version of Chrome that runs FireTV web apps - gonna look at your code tomorrow.