How to make tab index work for dropdowns?

ShellZero picture ShellZero · Sep 14, 2016 · Viewed 12k times · Source

I have a header with a bootstrap dropdown component and I am trying to enable keyboard navigation to that element by using tabindex. The following is the html and simple css:

HTML:
<span class="pull-right">
   <span class="help-menu dropdown">
       <span class="dropdown-toggle" data-toggle="dropdown" role="button">
          <span class="help-header" tab-index="0">Help</span>
        </span>
           <ul class="dropdown-menu pull-right" tabindex="-1" role="menu">
             <li tabindex="-1"><a [href]="/help.html" target="_blank">Docs</a></li>
           </ul>
    </span>
 </span>

CSS:

.help-header{
   &:after{
      content: "\25BE"; //caret should be displayed!
   }
}
.help-menu{
     display: inline-block;
     cursor: pointer;
     background: aqua;
     margin-top: 10px;
    margin-right: 20px;
}

Here is the Fiddle link

Now, the Help doesn't get focus when I do a tab. But when I remove the tabindex from help-header class and apply it to either the span with class pull-right or the span with class help-menu and dropdown, the Help text gets the focus on tab. Even though, that gets the focus, I can't see the dropdown on hitting enter or space or the down arrow.

I'm really not sure how to make this work. I have been trying to figure it out since a while but I failed.

Am I missing any core concept of the tabindex here. Could anyone please help me or point me to a right direction.

Thanks a lot.

Cheers.

Answer

Yuri Ramos picture Yuri Ramos · Sep 15, 2016

The tabindex attribute explicitly defines the navigation order for focusable elements (typically links and form controls) within a page. It can also be used to define whether elements should be focusable or not.

[Both] tabindex="0" and tabindex="-1" have special meaning and provide distinct functionality in HTML. A value of 0 indicates that the element should be placed in the default navigation order. This allows elements that are not natively focusable (such as <div>, <span>, and <p>) to receive keyboard focus. Of course one should generally use links and form controls for all interactive elements, but this does allow other elements to be focusable and trigger interaction.

A tabindex="-1" value removes the element from the default navigation flow (i.e., a user cannot tab to it), but it allows it to receive programmatic focus, meaning focus can be set to it from a link or with scripting.** This can be very useful for elements that should not be tabbed to, but that may need to have focus set to them.

A good example is a modal dialog window - when opened, focus should be set to the dialog so a screen reader will begin reading and the keyboard will begin navigating within the dialog. Because the dialog (probably just a <div> element) is not focusable by default, assigning it tabindex="-1" allows focus to be set to it with scripting when it is presented.

A value of -1 can also be useful in complex widgets and menus that utilize arrow keys or other shortcut keys to ensure that only one element within the widget is navigable with the tab key, but still allow focus to be set on other components within the widget.

So in summary, if you want to set certain element be enabled by the keyboard tab you should change the value to 0.