Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No outline on mouse focus but still have outline on keyboard focus?

When elements of a page have focus (such as a link or button), they show an outline. I would like this outline to only display when that element was given focus by the keyboard, not by the mouse.

Is it possible to determine how that element got its focus with JavaScript? If so, how do I then control the browser's own outlining feature?

like image 702
simple Avatar asked Aug 01 '13 16:08

simple


People also ask

How do I remove the outline from my focus-visible?

Using the CSS rule :focus { outline: none; } to remove an outline on an object causes the link or control to be focusable, but removes any visible indication of focus for keyboard users. Methods to remove it such as onfocus="blur()" result in keyboard users being unable to interact with the link or control.

Which pseudo-class allows you to selectively show a focus ring on elements only if keyboard navigation is detected?

The :focus-visible pseudo-class (also known as the “Focus-Indicated” pseudo-class) is a native CSS way to style elements that: Are in focus. Need a visible indicator to show focus (more on this later)

What is the difference between focus and focus-visible?

Adding the :focus pseudo-class to an element will make it show a focus specific styles and disregard browsers heuristics. The :focus-visible , in contrast, applies custom styling only if it would be shown natively.

What is visible keyboard focus?

Examples. When text fields receive focus, a vertical bar is displayed in the field, indicating that the user can insert text, OR all of the text is highlighted, indicating that the user can type over the text. When a user interface control receives focus, a visible border is displayed around it.


2 Answers

Browsers use the CSS outline property to show which element has the focus, as you might already know. So, in jQuery, you might use:

$(document).ready(function() {
    $("body").on("mousedown", "*", function(e) {
        if (($(this).is(":focus") || $(this).is(e.target)) && $(this).css("outline-style") == "none") {
            $(this).css("outline", "none").on("blur", function() {
                $(this).off("blur").css("outline", "");
            });
        }
    });
});

Explanation: This function looks for the mousedown event on any element. This event is delegated, meaning it will apply to elements currently on the page as well as any created dynamically in the future. When the mouse is clicked over the element, its CSS outline property is set to none; the outline is removed.

The targeted element gets a new handler for blur. When focus is taken from the element, the outline property is set to a blank string (this removes it from the element's style attribute), allowing the browser to control the outline again. Then, the element removes its own blur handler to free up memory. This way, an element is only outlined when focused from the keyboard.

Edit

Based on Rakesh's comments below, I made a slight change. The function can now detect if there's already an outline set, and will avoid overriding it. Demo here.

like image 95
theftprevention Avatar answered Oct 27 '22 00:10

theftprevention


http://jsfiddle.net/np3FE/2/

$(function(){
    var lastKey = new Date(),
        lastClick = new Date();

    $(document).on( "focusin", function(e){
        $(".non-keyboard-outline").removeClass("non-keyboard-outline");
        var wasByKeyboard = lastClick < lastKey
        if( wasByKeyboard ) {
            $( e.target ).addClass( "non-keyboard-outline");
        }

    });

    $(document).on( "click", function(){
        lastClick = new Date();
    });
    $(document).on( "keydown", function() {
        lastKey = new Date();
    });


});

CSS

*:active, *:focus {
    outline: none;
}

*:active.non-keyboard-outline, *:focus.non-keyboard-outline {
    outline: red auto 5px;
}
like image 36
Esailija Avatar answered Oct 26 '22 23:10

Esailija