Cross-browser div focus and blur

Internet Explorer has for some time supported giving ‘focus’ to non-focussable elements such as divs. Firefox, by contrast, does not. Whilst this makes sense semantically, it’s often still very useful to use these triggers. For example, you can use onfocus to show a popup when a div is clicked, and close the popup when anything else is clicked on the page (in the onblur event).

There are many, many workarounds which provide this functionality, using such tricks as hidden input elements, global onclick handlers, and so on, but the simplest is simply this: give your div a tabIndex attribute. For example,

[sourcecode language=”html”]

Click to show another div.

[/sourcecode]
works perfectly in Firefox, Internet Explorer, and Chrome as shown in the example below:

Click to show another div.

You can also achieve a similar effect purely with CSS:

[sourcecode language=”html”]

Focus me!
Hooray!

[/sourcecode]

Focus me!
Hooray!

Because the second example shows or hides a child element, the parent element will remain focussed if the user interacts with the child element, or its children. This allows you to embed links, forms, videos, and so on in the child element.

The value of tabIndex can have significance, too:

  • -1: The user can’t tab to the element, but it can be given focus programmatically (element.focus()) or by being clicked on.
  • 0: The user can tab to the element, and its order in the tabbing is automatically determined.
  • >0: Give the element a priority, with ‘1’ being the highest priority.

I originally discovered this technique on this CodingForums.com thread.

Comments

15 responses to “Cross-browser div focus and blur”

  1. Josh Habdas Avatar

    Thanks for the idea. Only problem is that tabindex is not a valid attribute of the DIV element as per the HTML 4 spec: http://www.w3.org/TR/REC-html40/index/attributes.html.

  2. Barry van Oudtshoorn Avatar

    You’re right, Josh. This is, unfortunately, a hack more than it is the ‘correct’ way of doing things. But it works nevertheless. 🙂

  3. bluerouse Avatar
    bluerouse

    Nice approach!
    But: Whats to do if you got a link in the ‘monkey’-Div? You can’t click it, because the Blur-Event is before the Click-Event…

    You got an idea?

    1. Barry van Oudtshoorn Avatar

      @bluerouse: In that case, you’re probably better off using Javascript that doesn’t rely on the ‘focus’ and ‘blur’ events.

      A MooTools snippet that adds the ‘outerClick’ event to elements is here: http://blog.kassens.net/outerclick-event .

      Using this, you could rewrite the example like this — note that, as I tend to nowadays, I’ll just create the elements in JavaScript:

      $(document.body).adopt(
      	new Element('div').addEvents(
      		'outerClick': function() {
      			$('monkey').setStyle('display', 'none');
      		},
      		'click': function() {
      			$('monkey').setStyle('display', 'block');
      		}
      	),
      	new Element('div', {
      		'id': 'monkey',
      		'styles': {
      			'display': 'none'
      		}
      	})
      )
      
  4. Andrei Nemeti Avatar

    Thanks. Helped with my simple task.
    Josh Habdas is right. It won’t validate, but as long as we have to hack IE, let’s just assume it’s valid 🙂

  5. caolvchong Avatar

    Thanks. Safari also support tabIndex on my PC.
    Safari version:4.0.3, Windows XP.

  6. Mohsen Avatar
    Mohsen

    Awsome!!
    It saved me. I do it by Prototype and it works great.
    Thanks.

  7. 2rist Avatar
    2rist

    This method is good until there is some “focusable” elemt inside your div(like input). In this situation when u click on this input – it takes focus and “div” blur is called despite the fact “clisk is inside div”

    You can solve this problem by doing something not very good like

    divElement.find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]').add(divElement).each(function() {
    $(this).blur(function () {
    closeDivTimeoutId = setTimeout(function () {
    //Your blur code here
    }, 100);
    }).focus(function () {
    if (closeDivTimeoutId ) {
    clearTimeout(closeDivTimeoutId );
    }
    });
    });

  8. ali hossinzadeh Avatar

    it nice work thanks

    but when i try use the css method
    if
    Hooray!
    chenge to
    Hooray!
    when click Hooray! it hide

  9. ali hossinzadeh Avatar

    it work in IE, Chrome
    but not in fierfox

    1. Barry van Oudtshoorn Avatar

      Not quite sure why it’s not working for you Ali… I’ve just tested in Firefox, and it appears to be functioning as expected. Maybe you could put a very small example of the problem up on jsFiddle?

      1. Harry Avatar
        Harry

        Yes not working in Firefox

        1. Barry van Oudtshoorn Avatar

          It’s working for me, Harry — in what context does it not work for you?

  10. asdf Avatar
    asdf

    the content
    on this
    site
    is way
    to narrow
    did
    not
    read it

  11. zostinger Avatar

    why iam not getting the perfact onclick blur while trying this trick?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.