1653

I would like to find out, in JavaScript, which element currently has focus. I've been looking through the DOM and haven't found what I need, yet. Is there a way to do this, and how?

The reason I was looking for this:

I'm trying to make keys like the arrows and enter navigate through a table of input elements. Tab works now, but enter, and arrows do not by default it seems. I've got the key handling part set up but now I need to figure out how to move the focus over in the event handling functions.

5

22 Answers 22

1938

Use document.activeElement, it is supported in all major browsers.

Previously, if you were trying to find out what form field has focus, you could not. To emulate detection within older browsers, add a "focus" event handler to all fields and record the last-focused field in a variable. Add a "blur" handler to clear the variable upon a blur event for the last-focused field.

If you need to remove the activeElement you can use blur; document.activeElement.blur(). It will change the activeElement to body.

Related links:

15
  • 70
    Not sure about IE, but FF and Safari both return the BODY element.
    – JW.
    Commented Jul 2, 2010 at 15:19
  • 16
    activeElement actually doesn't return the focused element. Any element can have focus. If a document has 4 'scrolldivs', 0 or 1 of those divs is scrollable by arrow keys. If you click one, that div is focused. If you click outside all, the body is focused. How do you find out which scrolldiv is focused? jsfiddle.net/rudiedirkx/bC5ke/show (check console)
    – Rudie
    Commented Oct 22, 2012 at 22:40
  • 25
    @Rudie, @Stewart: I've built on your fiddle to create a more elaborate playground: jsfiddle.net/mklement/72rTF. You'll find that the only major browser (as of late 2012) that can actually focus such a div is Firefox 17, and only by tabbing to it. The types of elements that ALL major browsers return via document.activeElement are restricted to input-related elements. If no such element has the focus, all major browsers return the body element - except IE 9, which returns the html element.
    – mklement0
    Commented Dec 22, 2012 at 5:20
  • 16
    Not sure if it helps, but you can make an element such as a div receive keyboard focus by including the attribute tabindex="0" Commented Apr 12, 2013 at 16:49
  • 6
    Any access to document.activeElement should be wrapped in a try catch as under some circumstances it can throw an exception (not just IE9 AFAIK). See bugs.jquery.com/ticket/13393 and bugs.jqueryui.com/ticket/8443
    – robocat
    Commented Jul 2, 2013 at 2:11
160

As said by JW, you can't find the current focused element, at least in a browser-independent way. But if your app is IE only (some are...), you can find it the following way:

document.activeElement

It looks like IE did not have everything wrong after all, this is part of HTML5 draft and seems to be supported by the latest version of Chrome, Safari and Firefox at least.

7
  • 5
    FF3 too. This is actually part of the HTML5 spec around "focus management". Commented Jan 31, 2009 at 0:37
  • 2
    It works in the current version of Chrome and Opera (9.62). Does not work in Safari 3.2.3 on OS X, but it works in Safari 4 that was released yesterday :)
    – gregers
    Commented Jun 9, 2009 at 15:02
  • still the same for chrome 19 :S
    – Sebas
    Commented Jun 20, 2012 at 23:12
  • 1
    It only works in chrome (20) / safari (5.1.3) when you use the keyboard to tab onto the element. If you click on it then neither the jquery :focus selector nor the document.activeElement succeeds in returning what you clicked on (returning undefined and document body element respectively). PS I can't believe this thread is 2 years old and there are still regression problems on webkit, along with the one where skip links don't work, but so much work is being done with adding experimental css3. Think I may go back to recommending firefox to my family and friends.
    – Dawn
    Commented Jul 5, 2012 at 11:03
  • 1
    It returns 'body' for most of the elements. Pretty much useless.
    – Cornelius
    Commented Mar 21, 2020 at 12:46
97

If you can use jQuery, it now supports :focus, just make sure you are using version 1.6+.

This statement will get you the currently focused element.

$(":focus")

From: How to select an element that has focus on it with jQuery

2
  • 6
    This is good, but how does jQuery do it? document.activeElement? I found this: return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); Commented Oct 13, 2017 at 3:16
  • 1
    @HarryPehkonen Looks like common document.querySelector( ':focus' ) works just fine and is used by jQuery
    – V.Volkov
    Commented Aug 20, 2022 at 20:14
52

document.activeElement is now part of the HTML5 working draft specification, but it might not yet be supported in some non-major/mobile/older browsers. You can fall back to querySelector (if that is supported). It's also worth mentioning that document.activeElement will return document.body if no element is focused — even if the browser window doesn't have focus.

The following code will work around this issue and fall back to querySelector giving a little better support.

var focused = document.activeElement;
if (!focused || focused == document.body)
    focused = null;
else if (document.querySelector)
    focused = document.querySelector(":focus");

An addition thing to note is the performance difference between these two methods. Querying the document with selectors will always be much slower than accessing the activeElement property. See this jsperf.com test.

0
46

By itself, document.activeElement can still return an element if the document isn't focused (and thus nothing in the document is focused!)

You may want that behavior, or it may not matter (e.g. within a keydown event), but if you need to know something is actually focused, you can additionally check document.hasFocus().

The following will give you the focused element if there is one, or else null.

var focused_element = null;
if (
    document.hasFocus() &&
    document.activeElement !== document.body &&
    document.activeElement !== document.documentElement
) {
    focused_element = document.activeElement;
}

To check whether a specific element has focus, it's simpler:

var input_focused = document.activeElement === input && document.hasFocus();

To check whether anything is focused, it's more complex again:

var anything_is_focused = (
    document.hasFocus() &&
    document.activeElement !== null &&
    document.activeElement !== document.body &&
    document.activeElement !== document.documentElement
);

Robustness Note: In the code where it the checks against document.body and document.documentElement, this is because some browsers return one of these or null when nothing is focused.

It doesn't account for if the <body> (or maybe <html>) had a tabIndex attribute and thus could actually be focused. If you're writing a library or something and want it to be robust, you should probably handle that somehow.


Here's a (heavy airquotes) "one-liner" version of getting the focused element, which is conceptually more complicated because you have to know about short-circuiting, and y'know, it obviously doesn't fit on one line, assuming you want it to be readable.
I'm not gonna recommend this one. But if you're a 1337 hax0r, idk... it's there.
You could also remove the || null part if you don't mind getting false in some cases. (You could still get null if document.activeElement is null):

var focused_element = (
    document.hasFocus() &&
    document.activeElement !== document.body &&
    document.activeElement !== document.documentElement &&
    document.activeElement
) || null;

For checking if a specific element is focused, alternatively you could use events, but this way requires setup (and potentially teardown), and importantly, assumes an initial state:

var input_focused = false;
input.addEventListener("focus", function() {
    input_focused = true;
});
input.addEventListener("blur", function() {
    input_focused = false;
});

You could fix the initial state assumption by using the non-evented way, but then you might as well just use that instead.

22

document.activeElement may default to the <body> element if no focusable elements are in focus. Additionally, if an element is focused and the browser window is blurred, activeElement will continue to hold the focused element.

If either of these two behaviors are not desirable, consider a CSS-based approach: document.querySelector( ':focus' ).

2
  • Cool, yes in my case your approach made absolutly sense. I can set my focusable elements with 'tabindex="-1" ', if none of them has focus (let's say, some text or picture, that I don't care about) the document.querySelector( ':focus') returns null.
    – Manfred
    Commented May 10, 2015 at 13:49
  • See my answer to avoid using querySelector: stackoverflow.com/a/40873560/2624876
    – 1j01
    Commented Nov 29, 2016 at 19:12
15

I have found the following snippet to be useful when trying to determine which element currently has focus. Copy the following into the console of your browser, and every second it will print out the details of the current element that has focus.

setInterval(function() { console.log(document.querySelector(":focus")); }, 1000);

Feel free to modify the console.log to log out something different to help you pinpoint the exact element if printing out the whole element does not help you pinpoint the element.

0
12

I liked the approach used by Joel S, but I also love the simplicity of document.activeElement. I used jQuery and combined the two. Older browsers that don't support document.activeElement will use jQuery.data() to store the value of 'hasFocus'. Newer browsers will use document.activeElement. I assume that document.activeElement will have better performance.

(function($) {
var settings;
$.fn.focusTracker = function(options) {
    settings = $.extend({}, $.focusTracker.defaults, options);

    if (!document.activeElement) {
        this.each(function() {
            var $this = $(this).data('hasFocus', false);

            $this.focus(function(event) {
                $this.data('hasFocus', true);
            });
            $this.blur(function(event) {
                $this.data('hasFocus', false);
            });
        });
    }
    return this;
};

$.fn.hasFocus = function() {
    if (this.length === 0) { return false; }
    if (document.activeElement) {
        return this.get(0) === document.activeElement;
    }
    return this.data('hasFocus');
};

$.focusTracker = {
    defaults: {
        context: 'body'
    },
    focusedElement: function(context) {
        var focused;
        if (!context) { context = settings.context; }
        if (document.activeElement) {
            if ($(document.activeElement).closest(context).length > 0) {
                focused = document.activeElement;
            }
        } else {
            $(':visible:enabled', context).each(function() {
                if ($(this).data('hasFocus')) {
                    focused = this;
                    return false;
                }
            });
        }
        return $(focused);
    }
};
})(jQuery);
2
  • 3
    Could this be replaced by @William Denniss's $("*:focus") ?
    – Pylinux
    Commented Jul 30, 2015 at 10:30
  • I suppose it could. I wrote this a long time ago and never had a reason to revisit a better solution now that it is 5 years later. Try it out! I might just do the same. I less plugin on our site! :)
    – Jason
    Commented Aug 21, 2015 at 19:33
12

A little helper that I've used for these purposes in Mootools:

FocusTracker = {
    startFocusTracking: function() {
       this.store('hasFocus', false);
       this.addEvent('focus', function() { this.store('hasFocus', true); });
       this.addEvent('blur', function() { this.store('hasFocus', false); });
    },

    hasFocus: function() {
       return this.retrieve('hasFocus');
    }
}

Element.implement(FocusTracker);

This way you can check if element has focus with el.hasFocus() provided that startFocusTracking() has been called on the given element.

9

JQuery does support the :focus pseudo-class as of current. If you are looking for it in the JQuery documentation, check under "Selectors" where it points you to the W3C CSS docs. I've tested with Chrome, FF, and IE 7+. Note that for it to work in IE, <!DOCTYPE... must exist on the html page. Here is an example assuming you've assigned an id to the element that has focus:

$(":focus").each(function() {
  alert($(this).attr("id") + " has focus!");
});
1
  • 1
    You should (always?) use this.id instead of $(this).attr('id'), or at least (when you allready have your jQuery object) $(this)[0].id. Native Javascript at this level is WAY faster and more efficient. Might not be noticable in this case, but systemwide you will notice a difference.
    – Martijn
    Commented Dec 15, 2015 at 13:51
9

If you want to get a object that is instance of Element, you must use document.activeElement, but if you want to get a object that is instance of Text, you must to use document.getSelection().focusNode.

I hope helps.

11
  • Better in what way?
    – 1j01
    Commented Nov 29, 2016 at 19:10
  • Open your browser’s inspector, click on any place of the page, past this document.getSelection().focusNode.parentElement and tap Enter. After that, past document.activeElement and do it samething. ;)
    – rplaurindo
    Commented Nov 29, 2016 at 19:22
  • With this comment box focused, document.activeElement gives the <textarea> whereas document.getSelection().focusNode gives the <td> that contains the <textarea> (and document.getSelection().focusNode.parentElement gives the <tr> containing the <td>)
    – 1j01
    Commented Dec 1, 2016 at 2:37
  • Sorry, my apologies. I didn’t explain it well. If you want to get a object that is instance of Element, you must to use document.activeElement, but if you want to get a object that is instance of Text, you must to use document.getSelection().focusNode. Please, test it again. I hope I helped.
    – rplaurindo
    Commented Dec 1, 2016 at 3:53
  • 2
    The question is asking for which element currently has focus. And the focusNode isn't guaranteed to be a text node either.
    – 1j01
    Commented Dec 2, 2016 at 6:45
8

There are potential problems with using document.activeElement. Consider:

<div contentEditable="true">
  <div>Some text</div>
  <div>Some text</div>
  <div>Some text</div>
</div>

If the user focuses on an inner-div, then document.activeElement still references the outer div. You cannot use document.activeElement to determine which of the inner div's has focus.

The following function gets around this, and returns the focused node:

function active_node(){
  return window.getSelection().anchorNode;
}

If you would rather get the focused element, use:

function active_element(){
  var anchor = window.getSelection().anchorNode;
  if(anchor.nodeType == 3){
        return anchor.parentNode;
  }else if(anchor.nodeType == 1){
        return anchor;
  }
}
1
  • 3
    That's not really a problem with document.activeElement: the inner <div> elements actually can't receive focus, as you can see visually by setting the :focus pseudo-class to something visible (example: jsfiddle.net/4gasa1t2/1). What you're talking about is which of the inner <div>s contains the selection or caret, which is a separate issue.
    – Tim Down
    Commented Jul 19, 2015 at 9:59
7

If you're using jQuery, you can use this to find out if an element is active:

$("input#id").is(":active");
6

Reading other answers, and trying myself, it seems document.activeElement will give you the element you need in most browsers.

If you have a browser that doesn't support document.activeElement if you have jQuery around, you should be able populate it on all focus events with something very simple like this (untested as I don't have a browser meeting those criteria to hand):

if (typeof document.activeElement === 'undefined') { // Check browser doesn't do it anyway
  $('*').live('focus', function () { // Attach to all focus events using .live()
    document.activeElement = this; // Set activeElement to the element that has been focussed
  });
}
5

Just putting this here to give the solution I eventually came up with.

I created a property called document.activeInputArea, and used jQuery's HotKeys addon to trap keyboard events for arrow keys, tab and enter, and I created an event handler for clicking into input elements.

Then I adjusted the activeInputArea every time focus changed, so I could use that property to find out where I was.

It's easy to screw this up though, because if you have a bug in the system and focus isn't where you think it is, then its very hard to restore the correct focus.

5

With dojo, you can use dijit.getFocus()

5

use document.activeElement.id

appending .id filters out returning the entire DOM and allows you to work only with identified elements

4

simple use document.activeElement to find the current active element

3

I think that Christian's answer is closest to the correct answer; with the addition that the focusout event has a property named relatedTarget that allows one to figure out what received the focus.

document.addEventListener("focusout",ev => {
  const focusedElement = ev.relatedTarget;

  // ...
});

The other answers that use querySelector(':focus') and activeElement have annoying caveats.

https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/relatedTarget

3

You can use the document.activeElement property to determine which DOM element currently has the focus. This property will return the currently focused element in the document, or null if no element has focus. You can use this property in combination with an event listener to detect when the focus changes. eg:

document.addEventListener('focusin', function(event) {
  console.log('Focused element:', document.activeElement);
});
0

If you want to test the focused element on the dev tools, I suggest using.

$(":focus")

As document.activeElement will change to body when you click on anything in the dev tool.

Add focus attribute to the input

$(":focus" vs document.activeElement)

0

To get the previous active element add this.

Example: you click on a button and need the previous active element. Since the button gets the focus once click on it.

document.addEventListener("focusout",ev => {
  document.previousActiveElement = ev.target;
});
2
  • Tony wants the currently active element and your code will return last active element.
    – Ahmed Syed
    Commented Jul 17, 2022 at 15:12
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Jul 17, 2022 at 15:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.