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
    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...

  • By
    Write Simple, Elegant and Maintainable Media Queries with Sass

    I spent a few months experimenting with different approaches for writing simple, elegant and maintainable media queries with Sass. Each solution had something that I really liked, but I couldn't find one that covered everything I needed to do, so I ventured into creating my...

Incredible Demos

  • By
    QuickBoxes for Dojo

    Adding to my mental portfolio is important to me. First came MooTools, then jQuery, and now Dojo. I speak often with Peter Higgins of Dojo fame and decided it was time to step into his world. I chose a simple but useful plugin...

  • By
    MooTools 1.3 Browser Object

    MooTools 1.3 was just released and one of the big additions is the Browser object.  The Browser object is very helpful in that not only do you get information about browser type and browser versions, you can gain information about the user's OS, browser plugins, and...

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!