Get the Focused Element with JavaScript

By  on  

Ensuring that a website or web app is both accessible and usable, as well as functional, is paramount to a positive user experience for all users.  Users don't appreciate when we've done a good job, but they definitely know when we've done poorly.  One important part of app usability and accessibility is focus management, a task often overlooked by developers.

A prime example of poor focus management:  opening a modal upon clicking a triggering link, not focusing on the any element in the modal.  Even worse:  focusing on one of the modal's elements but not returning focus to its trigger element once it has been closed.  Ideally you would store a reference to the trigger, focus into the modal, and focus back on the trigger element when the modal is closed.

What about the times when you aren't aware of which element is focused though?  The document tells us which element is focused via the document.activeElement property!

The JavaScript

Retrieving the currently selected element is as easy as using document.activeElement:

var focusedElement = document.activeElement;

/* per my example:
	var triggerElement = document.activeElement;
	myModal = new MyModal({
		onOpen: function() {
			this.container.focus();
		},
		onClose: function() {
			triggerElement.focus();
		}
	});
*/

This property isn't simply reserved for traditionally focusable elements, like form fields and links, but also any element with a positive tabIndex set.

What I love about document.activeElement is that you don't need any type of event listener or delegated listener to keep track of what element is focused -- you can simply reference that one property at any time.  Of course you should do loads of testing before relying on a feature like this -- it seems ripe for cross-browser issues or race conditions.  All in all, however, I've been pleased with my use of it and its reliability!

Recent Features

  • By
    5 Awesome New Mozilla Technologies You’ve Never Heard Of

    My trip to Mozilla Summit 2013 was incredible.  I've spent so much time focusing on my project that I had lost sight of all of the great work Mozillians were putting out.  MozSummit provided the perfect reminder of how brilliant my colleagues are and how much...

  • By
    Designing for Simplicity

    Before we get started, it's worth me spending a brief moment introducing myself to you. My name is Mark (or @integralist if Twitter happens to be your communication tool of choice) and I currently work for BBC News in London England as a principal engineer/tech...

Incredible Demos

  • By
    Dynamic Waveform Visualizations with wavesurfer.js

    Waveform images are an awesome addition to boring audio widgets.  They can be functional as well as aesthetically pleasing, allowing users to navigate audio visually.  I recently found wavesurfer.js, an amazing waveform image utility that uses to Web Audio API to create super customizable...

  • By
    Flashy FAQs Using MooTools Sliders

    I often qualify a great website by one that pay attention to detail and makes all of the "little things" seem as though much time was spent on them. Let's face it -- FAQs are as boring as they come. That is, until you...

Discussion

  1. Darius Kruythoff

    If memory serves me, this breaks in IE9 within iframes.
    try/catch can help here.

  2. Gwyn

    Thanks, this seems to be a good technique. I hadn’t thought of using focus outside of links and form fields. Would you recommend this for a tabbed interface (switching focus between tabpanels?

  3. olivvv

    to detail our twitter exchange, wrapping document.activeElement in a setTimeout is necessary when you want to catch it onblur().

  4. MDN claims that on a Mac elements that are not a text input tends to *not* get focus assigned to them (https://developer.mozilla.org/en-US/docs/Web/API/document.activeElement). I haven’t experimented enough to provide any useful tips but it’s definitely something to look out for.

    • I did see that, though I experienced no issues on non-input elements, so I didn’t mention it.

  5. Karl Swedberg

    Hey David,

    Thanks for this post! I’m guessing the MDN note about elements other than text inputs not getting focus is referring to OS X Safari in particular. Also, the “Full Keyboard Access” setting in System Preferences > Keyboard > Shortcuts seems to have an effect on it. I put together a little demo: http://jsbin.com/dofiv/1/edit?html,js,console,output

    * With the default “Full Keyboard Access” setting — “Text boxes and lists only” — the radio inputs and button don’t get focus when clicked and can’t be tabbed into.
    * When “Full Keyboard Access” is set to “All controls,” only the radio with a tabindex attribute can be tabbed into, and that one doesn’t get focus when clicked.
    * I can’t tab into the a element regardless of the keyboard access setting, but it gets focus either way when clicked.
    * Interestingly, I can tab into the div element with tabindex and it gets focus click regardless of the keyboard access setting.

    For what it’s worth, here is what Sizzle does to determine the “active” element: https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L1299
    And this comment explains how it handles the IE8-9 iframe error: https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L603-L606

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