Using tabindex with :focus

For those who have studied web site accessibility, this is probably old hat. Admittedly, I haven’t spent enough time thinking about accessibility, so this is one of those things I didn’t even realize until recently. So shame on me. :)

Let’s say you have the following page, with various elements, starting with maybe a form field:

Check out this Pen!

If you start with keyboard focus on the search input, then use the tab key to cycle through the elements, you’ll notice that the “focus” of the cursor goes from search field, to “Dummy link 1” (skipping the heading and paragraphs), to “Dummy link 2”, etc. To make it clear what’s focused, I’ve added a background color using the :focus pseudo-class.

Okay, simple enough. But what if you want to cycle through all the elements on the page? Easy, you just add tabindex attributes in the HTML to any element you want to receive focus:

Check out this Pen!

Now when you cycle through the elements with the tab key, all the elements receive focus, including all the paragraphs, with the background color added for each.

But notice another thing that happens: Any of those elements will receive focus styles even if you click on them with the mouse.

This means you can do something like the following demo. This is as a pure CSS game called “Find the Kitten”:

Check out this Pen!

This uses the same technique as the previous demo, changing styles on focus, but with the tabindex values added to all the elements, the boxes are clickable.

With a little more creativity, and combining this with other new CSS features, this could make for some interesting effects.

Accessibility Concerns?

I should stress that the techniques I’m using here are experimental and you should do some research on tabindex and :focus before you go crazy adding all sorts of elements on your pages that change styles when clicked/focused.

Again, this concept is probably not new to most experienced developers who have studied accessibility, but I thought it was interesting enough to write about.

Advertise Here

15 Responses

  1. I really enjoyed the “Find the kitten” game.

    Also, it’s good to keep in mind that the tabindex attribute can be used on any HTML element only on HTML5 browsers.

    • Good point. Of course, that’s just a validation thing, and doesn’t mean anything as long as the browser supports :focus properly. So even if you use an XHTML/HTML4 doctype, it would still work in a supporting browser, even if the page doesn’t validate.

      But anyhow, here is the reference:

      http://www.w3.org/TR/html5-diff/#new-attributes

      That document discusses differences, and in that section it says tabindex is a new global attribute.

      Thanks!

  2. kajo:

    great discovery, I didn’t know about it!

  3. Awesome!

    I wish this blog to have separate accessibility category, where I can learn even more!!!

  4. Ben:

    Cool and simple, I like it

  5. Adam:

    Interesting technique indeed. I always love coming across new simple approaches to everyday things like this. I’ll just note that I gave it a try in IE8 and had no luck. Would be curious how far back browser support goes across the board.

  6. I have been using this technique for few projects now.
    It’s really useful on navigation menus and how it can be frustrating on mobile devices as there is no hover state.
    I’m using Drupal and with the help of a module called Nice Menu, I’m able to place any placeholder and specify any attribute.

    So my setup is like this:

    
        Drop-down Menu
             <a href="#link1" rel="nofollow">Item 1</a>
             <a href="#link2" rel="nofollow">Item 2</a>
             <a href="#link3" rel="nofollow">Item 3</a>
    

    And then I would do my CSS as follows:

    
    ul span:focus ~ ul {
     /* do something here, like change display from :none to :block etc. */
    }
    

    Here is alive example of a project we just launched today:

    http://greatcalgaryfestivals.ca

    Notice how the filters drop-down is using the same principal, and also the Made In YYC at the footer.
    There is a ton more CSS tricks that I applied on that site *hint : look at how the filters are working* .
    ~Sinan

  7. When you are considering using tabindex to make an element that isn’t normally focus-able like <div>, you should consider whether there is another element that is already focus-able that makes more sense like <a> or <button>. Using a <div> or <span> may accomplish the same thing with more markup and less semantic meaning.

    This is a handy trick to have in your belt though, particularly if you want to make old websites keyboard accessible without making major changes to the markup.

  8. Interesting, Looking forward to it.

  9. good idea to make use of tabindex

  10. So, this is a bit of an older article, but I’ll leave my $0.02.

    I’m currently the sole developer on a public library website redesign. Since it’s a public-sector project, it has to adhere to section 508 and be highly accessible. I managed to get the “Skip to Content” and “Skip to Navigation” links working just fine: absolutely positioned off the screen and statically positioned on-screen when they are tabbed into focus. I also used this CSS rule to make any focused link highly visible:

    
    a:focus{
        background: yellow;
        color: black;
        font-size: 26px;
    }

    This worked great because, in most browsers, focus was not given to links when clicking on them. The one exception was IE. A non-disabled IE user would click with their mouse on a link and watch it turn big, black, and yellow. This behavior was only intended for visually impaired users hitting Tab to shift focus through links, not mouse users. My solution was to use a `click` and `keyup` event listener to add or remove a .nofocushighlight class from the body tag based on whether the user was using their mouse or their enter key. A corresponding CSS rule for .nofocushighlight a:focus then removed the focus styling when it wasn’t appropriate (a mouse user):

    The JavaScript (jQuery):

    
    $('a').bind('mouseup keyup', function(e){
        if (e.which == 13) {  // enter key was pressed
            $('body').removeClass('nofocushighlight');
         } else if (e.which == 1) {  // left mouse button was pressed
            $('body').addClass('nofocushighlight');
        }
        return false;
    })
    

    And then adding the corresponding CSS rule:

    
    .nofocushighlight a:focus{
        background: inherit;
        color: inherit;
        font-size: inherit;
    }
    

    If these were external links, I wouldn’t really have cared that much, but if these were external links, I wouldn’t have cared as much because the user would be taken to a different page and wouldn’t see the highlighted link for very long. But because I am using links for intra-page navigation, it just didn’t look good to have huge highlighted links when it wasn’t necessary.

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field. If you use keywords, your comment will be deleted, or your name will be replaced with the alias from your email address. No foul language, please. Thank you for cooperating.

Instructions for code snippets: Wrap inline code in <code> tags; wrap blocks of code in <pre> and <code> tags. When you want your HTML to display on the page in a code snippet inside of <code> tags, make sure you use &lt; and &gt; instead of < and >, otherwise your code will be eaten by pink unicorns.