Focusable Elements with tabindex

By  on  

I was recently debugging a Dojo-fueled web application that features a "Tree" dijit (much like Christoph Pojer's MooTools Tree Component). The tree's container had a fixed width and an CSS "overflow" property of "hidden" to avoid scrolling. The problem I was encountering was that when I clicked a tree item, the item would receive focus and, if it were too long, the left side of the container would get "cut off." Of course I could add overflow:auto to the container but the goal was to avoid scrolling with the element.

I spent hours trying to figure out how to avoid this "left-side cutoff." I tried using different CSS positioning, display types, and floating. I tried using Dojo to listen to tree item focus events and quick scroll back to the left -- that didn't work either. After hours of researching and testing, I found a method within the Dijit TreeNode class called setFocusable:

setFocusable: function(/*Boolean*/ selected){
	// summary:
	//		A Tree has a (single) node that's focusable.
	//		Mark that this node is/isn't that currently focsuable node.
	// description:
	//		In particular, setting a node as selected involves setting tabIndex
	//		so that when user tabs to the tree, focus will go to that node (only).

	this.labelNode.setAttribute("tabIndex", selected ? "0" : "-1");
},

The method modifies the tabindex attribute of the element. Initially I didn't think it could be possible that this was the problem. After a few quick tests, however, it was apparent that tabindex was causing the problem. I did a quick search and hit Jonathan Snook's Making Elements Focusable with tabindex post. Snook explains:

The tabindex value can allow for some interesting behaviour.

  • If given a value of "-1", the element can't be tabbed to but focus can be given to the element programmatically (using element.focus()).
  • If given a value of 0, the element can be focused via the keyboard and falls into the tabbing flow of the document.
  • Values greater than 0 create a priority level with 1 being the most important.

After a bunch more testing (...and cursing) I realized just how powerful tabindex can be. For those of you who prefer to read code, here's an example usage:

<a href="https://davidwalsh.name">Some Link</a>
<!-- ...tabs to.... -->
<span id="my-span" tabindex="0">Some Span</span>

And I can use JavaScript to focus on it!

document.getElementById('my-span').focus();

The A element wouldn't usually tab to the SPAN element but thanks to tabindex, it does. Imagine how much more powerful tabindex can be when used with JavaScript, as evidenced by the original Dojo snippet. I can programitically give or remove the ability for any element to receive focus by modifying its tabindex attribute. Sweet!

Part of me feels like I should have known about tabindex with focus() sooner -- the other part of me feels like it's a quirk that's not very commonly used. What do you think?

Recent Features

  • By
    Camera and Video Control with HTML5

    Client-side APIs on mobile and desktop devices are quickly providing the same APIs.  Of course our mobile devices got access to some of these APIs first, but those APIs are slowly making their way to the desktop.  One of those APIs is the getUserMedia API...

  • By
    Welcome to My New Office

    My first professional web development was at a small print shop where I sat in a windowless cubical all day. I suffered that boxed in environment for almost five years before I was able to find a remote job where I worked from home. The first...

Incredible Demos

  • By
    CSS Selection Styling

    The goal of CSS is to allow styling of content and structure within a web page.  We all know that, right?  As CSS revisions arrive, we're provided more opportunity to control.  One of the little known styling option available within the browser is text selection styling.

  • By
    PHP IMDB Scraper

    It's been quite a while since I've written a PHP grabber and the itch finally got to me. This time the victim is the International Movie Database, otherwise known as IMDB. IMDB has info on every movie ever made (or so it seems). Their...

Discussion

  1. CTuLT

    \(^O^)/ You finally learned Dojo! Still much more to learn, but you learned the basics! I have been using Dojo for 4 years and I still don’t know it all.

  2. MLaZz

    I used tabindex on my MultiSelect plugin (http://mootools.net/forge/p/mutiselect) to allow for keyboard navigation. Other than that i0ve never used it before, never needed..

  3. Luke

    I never realised that setting tabindex to -1 or 0 performed that behaviour… What I read when I first started learning HTML…going back a while XD, is that 0 is the start… now that just tells me I learnt from an in-accurate source, what they also said is that tabindex should take a value from 0-x, which also left me in the dark about using -1 to ignore an element. What you said is exactly right that tabindex is alot more powerful than it first appears and I think it opens quite a few door ways to custom and/or complex kayboard navigation.

  4. Great tutorial !
    I test with jQuery , it’s work:
    `document.getElementById(‘focusi’).focus();`
    I suggest you add in the github

  5. Pat Nellesen

    Thanks for the info about tabindex – I wasn’t aware of that behavior either (and I’ve been doing this stuff for a very long time ;) )

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!