How can I remove the outline when focusing with the mouse, but still retain it when focusing with the

Is there a way in JavaScript to detect if an element received focus from the keyboard or mouse? I only want the outline to show when it's via the keyboard, not the mouse.

If this is possible, how can I override the browser's default outlining behavior?

Answer №1

Web browsers utilize the CSS outline property to indicate which element is currently in focus, a common knowledge amongst web developers. In jQuery, a typical implementation might look like this:

$(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 script listens for the mousedown event on any given element. By using event delegation, it covers both existing and dynamically created elements. When an element is clicked with the mouse, its CSS outline property is set to none, effectively removing the outline.

The targeted element then receives a new handler for the blur event. As soon as the focus leaves the element, the outline property is reset to an empty string, allowing the browser to handle the outline display. Subsequently, the element removes its own blur handler to optimize memory usage, ensuring that outlines are only visible when focused via keyboard navigation.

Edit

In response to feedback from Rakesh, a slight modification has been made to the function. It now checks if an outline is already defined and avoids overriding it. Check out the demo here.

Answer №2

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;
}

Answer №3

Eliminating the outline may not be the best option for ensuring accessibility! It is preferable for the focus ring to appear only when the user specifically intends to utilize the keyboard.

In response to 2018: Consider utilizing :focus-visible. This feature, currently a W3C proposal, allows for styling keyboard-focused elements in CSS. In case major browsers do not support it yet, you can implement a solid polyfill. This method does not necessitate the addition of extra components or modifications to the tabindex.

/* Eliminate outline for non-keyboard :focus */
*:focus:not(.focus-visible) {
  outline: none;
}

/* Optionally customize .focus-visible */
.focus-visible {
  outline-color: lightgreen;
}

If you require more information, I have also penned an informative article with demos available at this link.

Answer №4

To avoid the focus event from firing, one simple solution is to utilize mouse events.

$('#element').click(function(){
   $(this).blur();
});

An issue that may arise with this approach is the inability to select the element using the mouse. To address this, you can add a class and modify the focus style accordingly.

$('#element').click(function(){
   $(this).addClass('fromMouse');
});
$('#element').blur(function(){
  if($(this).hasClass('fromMouse')){
     $(this).removeClass('fromMouse');
  }
});

CSS

.fromMouse{
  outline: none;
}

http://api.jquery.com/blur/

Answer №5

Cascading Style Sheets

:focus{
  outline: none;
}

.outline{
  outline: 2px solid rgba(200,120,120, 0.8);
}

jQuery script

$(function(){
  $('*').on('keydown.tab', function(e){
    /*
    TAB or Shift Tab, Aw.
    Add some more key code if you really want
    */
    if ( 9== e.which && this == e.target ){
      window.setTimeout( function(){
        $('.outline').removeClass('outline');
         $(document.activeElement).addClass('outline');
      }, 100 );
    }

  });

});

This method works effectively. The outline will only be displayed when the element is focused using the keyboard (specifically Tab and Shift Tab keys).

Check it out in action: http://jsbin.com/okarez/1

Answer №6

After reviewing @theftprevention's response, a more personalized approach could be:

$(function(){
    $('body')
    .on('focus', '*', function() {
        var e = $(this);
        if (!e.is('.focus-mouse')) {
            e.addClass('focus-keyboard');
        }
    })
    .on('mousedown', '*', function() {
        $(this).removeClass('focus-keyboard').addClass('focus-mouse');
    })
    .on('blur', '*', function() {
        $(this).removeClass('focus-keyboard').removeClass('focus-mouse');
    });
});

Now it is easy to customize using the .focus-keyboard and .focus-mouse classes in CSS.

.focus-keyboard{
    background:#eeeeee;
}
.focus-mouse{
    outline: 0;
}

Answer №7

By adding a class to the body element, you can detect whether the user is currently using a mouse or keyboard through CSS.

document.body.addEventListener('mousedown', function() {
  document.body.classList.add('using-mouse');
});
document.body.addEventListener('keydown', function() {
  document.body.classList.remove('using-mouse');
});

You can then style it in your CSS like this:

:focus {
  outline: #08f auto 2px;
}

body.using-mouse :focus {
  outline: none;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Changing marker colors dynamically in Google Maps with NextJS

I'm using the @googlemaps/js-api-loader package to load a map in my nextJS app. I have a list of locations that I want to plot on the map, and I also want these locations disabled on the left side of the page. When hovering over one of the locations ...

Dividing the code into a function and invoking it does not produce the desired outcome

Everything seemed to be working perfectly until I attempted to encapsulate the code into a function and call it within my expression. Unfortunately, this approach did not yield the desired results. Functional code: render: function() { return ( ...

Using data binding in VueJS to construct a dynamic URL

Exploring VueJS for the first time and it's been a great experience so far. However, I'm facing a couple of challenges with data binding. The requirement is for the customer to input an image URL, and no image should be displayed until a valid ...

Angular HTML is throwing an error related to object arrays

Is there a way to display only specific fields of an array? <div class="form-check" *ngFor="let periodo of filterPeriodos()"> <div>{{periodo.periodos | json}}</div> <input class="form-check-input mr- ...

Is there a way to automatically redirect my login page back to the original page in case of login failure?

I'm currently working on a basic login page using express.js + E.js. If the login credentials are incorrect, I have a variable badLogin that is triggered (see below). However, my goal is to redirect the website back to the login page instead of remai ...

Host your own website online using your personal computer

So I have created a simple HTML page that I want to publish on the Internet using my PC. This is just for testing purposes, so I don't require a static IP address or high uptimes. First, I installed Tomcat Apache and placed my WAR file in the webapps ...

Error occurs in ASP.NET AJAX Control Toolkit while uploading files within Scriptresource.axd

I recently encountered an issue with my AJAX Control Toolkit File Upload (Version 15.1.4) in my ASP.Net Web Application. Up until this week, it was functioning perfectly fine. However, starting yesterday, I started receiving a JavaScript error right after ...

Is there a way to eliminate the gap beneath each row of my Tic-Tac-Toe grid in Next.js with CSS styling?

What could be causing the space under every row in my CSS? I am currently developing a tic-tac-toe application using Next.js to enhance my skills. However, I have encountered an issue with the CSS where there appears to be a small space underneath each bo ...

How to line up two blocks side by side in a single block with Bootstrap without the use of CSS

The bootstrap margin is causing issues with this code <div class="row"> <div class="row1 col-lg-3"> <div class="row2 col-lg-1"></div> <div class="row2 col-lg-1"></di ...

Ways to rotate SVG images exclusively upon clicking

After experimenting with rotating SVG images on my navbar buttons, I encountered an issue. Whenever I click one button, all the images rotate simultaneously. Additionally, clicking elsewhere does not reset the images to their original positions. This is t ...

Unable to receive AJAX response for the GET request

I am attempting to achieve the following: Upon clicking on H1, jQuery is supposed to retrieve information for a specific key from the server and display it in a prompt. The PHP code resides in server.php. $link = mysql_connect("mysql.hostinger.com.ua", "_ ...

What are the steps to convert a canvas element, using an image provided by ImageService as a background, into a downloadable image?

I've been working on an app that allows users to upload an image, draw on it, and save the result. To achieve this functionality, I'm using a canvas element with the uploaded image as its background. The image is retrieved through ImageService. B ...

Unable to activate focus() on a specific text field

It's quite peculiar. I'm working with a Sammy.js application, and my goal is to set the focus on a text field as soon as the HTML loads. Here's the CoffeeScript code snippet I've written: this.partial('templates/my-template.jqt&ap ...

Can an Angular application be developed without the use of the app-root tag in the index.html file?

I'm a newcomer to Angular and I'm trying to wrap my head around how it functions. For example, if I have a component named "login", how can I make Angular render it directly? When I try to replace the app-root tag with app-login in index.html, n ...

What is the best way to retrieve the URL from a specific HTML tag?

I am attempting to extract all URLs that have id='revSAR' from the provided HTML tag using a Python regex: <a id='revSAR' href='http://www.amazon.com/Altec-Lansing-inMotion-Mobile-Speaker/product-reviews/B000EDKP8U/ref=cm_cr_dp ...

Angular: controller's property has not been initialized

My small controller is responsible for binding a model to a UI and managing the UI popup using semantic principles (instructs semantic on when to display/hide the popup). export class MyController implements IController { popup: any | undefined onShow(con ...

Incorporating a Custom CKEditor5 Build into an Angular Application

I am currently in the process of developing an article editor, utilizing the Angular Integration for CKEditor5. By following the provided documentation, I have successfully implemented the ClassicEditor build with the ckeditor component. Below are the ess ...

Maximizing the potential of Next JS 13 Server Components

Exploring the updates in Next JS 13, I have found it intriguing that every component is now a server component by default. This concept has been puzzling for me as I try to grasp how to effectively leverage this feature. For instance, my current challenge ...

Why won't JSZip accept a base64 string for loading a zip file?

As I work on implementing a feature where a small JSON object is written to the URL as a user interacts with items on a page, I also want to make sure the URL can be read later so users can resume where they left off. I successfully managed to create the ...

Using jQuery to retrieve the domain extension from a URL

Seeking assistance with extracting domain extensions from various URLs using jQuery. Uncertain how to account for all possible scenarios. Here are the parts of the URL that need to be extracted: https://www.amazon.**com**/dp/067144901X https://www.amazon. ...