Sean Clark Hess
Sean Clark Hess

Reputation: 16059

How to remove focus around buttons on click

My buttons all have a highlight around them after I click them. This is in Chrome.

Unselected Selected

<button class="btn btn-primary btn-block">
    <span class="icon-plus"></span> Add Page
</button>

I am using Bootstrap with a theme, but I'm pretty sure that's not it: I was noticing this before on another project.

It goes away if I use an <a> tag instead of <button>. Why? If I wanted to use <button> how would I make it go away?

Upvotes: 360

Views: 672923

Answers (30)

JamesWilson
JamesWilson

Reputation: 4830

Use focus-visible

Note 1: In each of the 3 options outlined below, buttons behave the same way (no focus ring on click), but selects and inputs vary slightly in their default behavior. Only Option 3 removes focus rings consistently around buttons, inputs, and selects. Please compare all approaches and make sure you understand the implications.

Note 2: Due to the cascading nature of CSS, the order of the CSS rules is important.

Note 3: There are still some accessibility concerns with any focus-visible approach. Namely, that until browsers expose a configuration to let users choose when to show visible focus rings, focus-visible should be considered worse for accessibility than using focus rings everywhere all the time, but better than the harmful :focus {outline:none} approach mentioned in other answers to this question. See "A note about accessibility" section at the bottom of this answer for more details.

OPTION 1: Use the :focus-visible pseudo-class

The :focus-visible pseudo-class can be used to remove outlines and focus rings on buttons and various elements for users that are NOT navigating via keyboard (i.e., via touch or mouse click).

Warning 2: As of 2021, the :focus-visible pseudo-class is ** widely supported across modern browsers but fails on fringe browsers**. If old-browser support is important, the Javascript polyfill in option 2 below is the closest approximation however, please be aware that as of June 2024, Polyfill.io is no longer a trustworthy source.

/**
 * Remove focus styles for non-keyboard focus.
 */
:focus:not(:focus-visible) {
  outline: 0;
  box-shadow: none;
}

/**
 * Cross-browser styles for explicit focus via 
 * keyboard-based (eg Tab) navigation or the
 * .focus-visible utility class.
 */
:focus,
.focus-visible:focus:not(:focus-visible) {
  outline: 0;
  box-shadow:
    0 0 0 .2rem #fff,
    0 0 0 .35rem #069;
}
<h3>Defaults:</h3>
<button>Foo</button>
<input type="button" value="Bar"/> 
<select><option>Baz</option></select>
<input type="text" placeholder="Qux"/>
<textarea placeholder="Quux" rows="1"></textarea>

<h3>Force focus on click:</h3>
<button class="focus-visible">Foo</button>
<input class="focus-visible" type="button" value="Bar"/> 
<select class="focus-visible"><option>Baz</option></select>
<input class="focus-visible" type="text" placeholder="Qux"/>
<textarea class="focus-visible" placeholder="Quux" rows="1">
</textarea>


OPTION 2: Use a .focus-visible polyfill

This solution uses a normal CSS class instead of the pseudo-class mentioned above and has wider browser support (in 2021). It requires either 1 or 2 Javascripts be added to your HTML; one for the official focus-visible polyfill and the other for older browsers that don't support classList.

Note: In Chrome, the polyfill seems to treat selects differently than the native :focus-visible pseudo-class.

/**
 * Cross-browser focus ring for explicit focus 
 * via keyboard-based (eg Tab) navigation or the
 * .focus-visible utility class.
 */
:focus {
  outline: 0;
  box-shadow:
    0 0 0 .2rem #fff,
    0 0 0 .35rem #069;
}

/**
 * Remove focus ring for non-explicit scenarios.
 */
:focus:not(.focus-visible) {
  outline: 0;
  box-shadow: none;
}
<h3>Defaults:</h3>
<button>Foo</button>
<input type="button" value="Bar"/> 
<select><option>Baz</option></select>
<input type="text" placeholder="Qux"/>
<textarea placeholder="Quux" rows="1"></textarea>

<h3>Force focus on click:</h3>
<button class="focus-visible">Foo</button>
<input class="focus-visible" type="button" value="Bar"/> 
<select class="focus-visible"><option>Baz</option></select>
<input class="focus-visible" type="text" placeholder="Qux"/>
<textarea class="focus-visible" placeholder="Quux" rows="1">
</textarea>

<!-- place this code just before the closing </html> tag -->
<script src="https://cdnjs.cloudflare.com/polyfill/v2/polyfill.js?features=Element.prototype.classList"></script>
<script src="https://unpkg.com/focus-visible"></script>


OPTION 3: Use a global key-navigation vs mouse-navigation state

An inverse solution to focus-visible, is to disable outlines on mousemove, and enable them on keydown -> "Tab". In this case, rather than specifying which elements shouldn't show an outline, you must specify which elements should.

document.addEventListener("mousemove", () => 
  document.body.classList.remove("focus-visible")
);

document.addEventListener("keydown", ({key}) => 
  (key === "Tab") && document.body.classList.add("focus-visible")
);
/**
 * Cross-browser focus ring for explicit focus 
 * via keyboard-based (eg Tab) navigation or the
 * .focus-visible utility class.
 */
:focus {
  outline: 0;
  box-shadow:
    0 0 0 .2rem #fff,
    0 0 0 .35rem #069;
}

/**
 * Remove focus ring for non-explicit scenarios.
 */
body:not(.focus-visible) :focus:not(.focus-visible) {
  outline: 0 !important;
  box-shadow: none !important;
}
<h3>Defaults:</h3>
<button>Foo</button>
<input type="button" value="Bar"/> 
<select><option>Baz</option></select>
<input type="text" placeholder="Qux"/>
<textarea placeholder="Quux" rows="1"></textarea>

<h3>Force focus on click:</h3>
<button class="focus-visible">Foo</button>
<input class="focus-visible" type="button" value="Bar"/> 
<select class="focus-visible"><option>Baz</option></select>
<input class="focus-visible" type="text" placeholder="Qux"/>
<textarea class="focus-visible" placeholder="Quux" rows="1">
</textarea>

A note about accessibility

Removing all focus rings a la :focus { outline: none; } or :focus { outline: 0; } is a known accessibility issue and is never recommended. Additionally, there are folks in the accessibility community who would rather you never remove a focus ring outline and instead make everything have a :focus style — either outline or box-shadow could be valid if styled appropriately.

Finally, some folks in the accessibility community believe developers should not implement :focus-visible on their websites until all browsers implement and expose a user preference which lets people pick whether all items should be focusable or not. I personally don't subscribe to this thinking, which is why I provided this solution that I feel is far better than the harmful :focus { outline:none }. I think :focus-visible is a happy medium between design concerns and accessibility concerns. As of 2022, Chrome browser has exposed a user preference to set focus visibility styles, but FireFox has not.

Resource:

Demo:

Upvotes: 100

PeterG
PeterG

Reputation: 51

I found the same situation using a submit button in a form using a bootstrap (v4.4.1) class. The problem arose as I was building a single-page user interface using JavaScript to manipulate all the required changes to the DOM. The form data was submitted to the server via 'fetch' using a JSON string rather than a HTTP POST request. Note that usually the form's default behaviour is to reload the document, and normally this would refresh the button, however the form's default behaviour was prevented by using e.preventDefault() in the listener function for the form's submit event (it is a single-page UI so the document is never reloaded and traffic to the server is minimised to data only). Given the document was not reloaded the button appeared to stay depressed until the user clicked elsewhere in the window. This is what I had (with the problem):

<input type="submit" class="btn btn-primary">

This is what I used to solve the problem of the button remaining pressed:

<input type="submit" class="btn btn-primary" onmouseup="this.blur()">

Upvotes: 5

dacey
dacey

Reputation: 175

I am curious as to why someone would want to remove the outline. Like many have mentioned, there are accessibility concerns if you remove the outline. Users using Assistive Technologies such as screen readers need to know where the focus is when visiting websites/applications. I know the blue color around the button can "mess up" designs, however, you can change the color with CSS using:

outline-color: your color hex here;

Another way you can edit this is by adding a boarder on focus.

Upvotes: -2

Mostafa
Mostafa

Reputation: 989

Just try one of these:

outline:0; or outline:0px; or outline: none;

and $(this).trigger("blur");

Upvotes: -3

timthedev07
timthedev07

Reputation: 454

For anyone who's using react-bootstrap and encountered this problem, here's what I did to make things work:

.btn:focus {
    /* the !important is really the key here, it overrides everything else */
    outline: none !important;
    box-shadow: none !important;
}

And things did not work before adding !important.

Upvotes: 4

Kia Kaha
Kia Kaha

Reputation: 1781

If the button:focus {box-shadow: none} didn't work out for you there might be some library adding the border as in my case with the pseudo-selector ::after.

So I removed the border showing up on focus with the following solution:

button:focus::after {
    outline: none;
    box-shadow: none;
}

Upvotes: 0

user11533590
user11533590

Reputation:

React with TS solution

  const btnRef = useRef<HTMLButtonElement | null>(null);
  const handleOnMouseUp = () => {
    btnRef.current?.blur();
  };
  
  <button
    ref={btnRef}
    onClick={handleOnClick}
    onMouseUp={handleOnMouseUp}
  >
    <span className="icon-plus"></span> Add Page
  </button>

Upvotes: 3

TetraDev
TetraDev

Reputation: 17064

If you want to accomplish the removal of the outline on mousedown but not on keyboard tab, and you're using VueJS, here's the solution:

<button @mousedown="$event.preventDefault()">No Online On Click</button>

This basically prevents it from receiving focus on click, but any other way of receiving focus stays active.

Upvotes: 2

webpassion101
webpassion101

Reputation: 68

Although the CSS solutions offered here work,

for anyone who prefers to use the Bootstrap 4 way, as suggested in the official Bootstrap Theming guide, this should help:

in your custom.scss file (see guide above ^) where you add your variable overrides, add the following variable to remove the box-shadow for buttons:

// import bootstrap's variables & functions to override them
@import "node_modules/bootstrap/scss/functions";
@import "node_modules/bootstrap/scss/variables";
@import "node_modules/bootstrap/scss/mixins";

// override the variables you want (you can look them up in node_modules/bootstrap/scss/variables file, they're the ones that have the !default keyword at the end)
$btn-focus-box-shadow: none;

// option A: include all of Bootstrap (see the above guide for other options)
@import "node_modules/bootstrap/scss/bootstrap";

this works for me.

please note that there are many variables in bootstrap's variables file for box-shadow, for other controls as well, so it might require some more research on your side if you want to use them and/or this specific variable doesn't work for you.

Upvotes: 1

NobodySomewhere
NobodySomewhere

Reputation: 3225

A bit nuclear, but this is simple way that worked for me on Angular 9. Use with causon since it affects every html element.

*:focus {
  outline: 0 !important;
}

Upvotes: 3

Suren
Suren

Reputation: 1

Here are two possible solutions.

1.) button type="button" className="btn-cart"onClick{(event)=>this.blur(event)}

2.) button type="button" className="btn-cart" onclick={this.blur}

Both of the solutions will remove the highlighted part around the button i.e -> blur() has its own specification in it of removing highlighted part around.

Upvotes: 0

jerimiah797
jerimiah797

Reputation: 4631

I found this Q and A on another page, and overriding the button focus style worked for me. This problem may be specific to MacOS with Chrome.

.btn:focus {
  outline: none;
  box-shadow: none;
}

Note though that this has implications for accessibility and isn't advised until you have a good consistent focus state for your buttons and inputs. As per the comments below, there are users out there who cannot use mice.

Upvotes: 421

Keith DC
Keith DC

Reputation: 673

I found no solid answers that didn't either break accessibility or subvert functionality.

Perhaps combining a few will work better overall.

<h1
  onmousedown="this.style.outline='none';"
  onclick="this.blur(); runFn(this);"
  onmouseup="this.style.outline=null;"
>Hello</h1>

function runFn(thisElem) { console.log('Hello: ', thisElem); }

Upvotes: 1

I found a solution simply add below line in your css code.

button:focus { outline: none }

Upvotes: 2

ritesh
ritesh

Reputation: 187

You can use focus event of button. This worked in case of angular

<button (focus)=false >Click</button

Upvotes: -3

TimothePearce
TimothePearce

Reputation: 1148

For sass users, Bootstrap 4 should be manipulated by overriding variables.

If you want to disable the box-shadow on focus around buttons:

$btn-focus-box-shadow: none;

You can also disable the box-shadow on focus around inputs with:

$input-focus-box-shadow: none;

Or both with one variable:

$input-btn-focus-box-shadow: none;

Upvotes: 0

weichao
weichao

Reputation: 3381

I find a solution. when we focus, bootstrap use box-shadow, so we just disable it(not enough reputation, cannot upload image :( ).

I add

.btn:focus{
    box-shadow:none !important;
}

it works.

Upvotes: 10

None
None

Reputation: 602

directly in html tag (in a scenario where you might want to leave the bootstrap theme in place elsewhere in your design)..

examples to try..

<button style="border: transparent;">
<button style="border: 1px solid black;">

..ect,. depending on the desired effect.

Upvotes: 0

spcsLrg
spcsLrg

Reputation: 377

I was having the same problem using <a> acting as button and I discovered I was missing a workaround by adding attr type="button" makes it behave normally for me at least.

<a type="button" class="btn btn-primary">Release Me!</a>

Upvotes: 0

Renish Gotecha
Renish Gotecha

Reputation: 2522

Add this in script

$(document).ready(function() {
    $('#addBtn').focus(function() {
        this.blur();
    });
});

Upvotes: -1

ich_cb
ich_cb

Reputation: 109

For people wanting a pure css way to do that:

:focus:not(:focus-visible) { outline: none }

This could also work for link and so on, and bonus, it keeps the keyboard accessibilities. Lastly it is ignored by browsers that don’t support :focus-visible

Upvotes: 4

Gabriel Reis
Gabriel Reis

Reputation: 37

Add this in CSS:

*, ::after, ::before {
    box-sizing: border-box;
    outline: none !important;
    border: none !important;
    -webkit-box-shadow: none !important;
    box-shadow: none !important;
}

Upvotes: 2

user8790423
user8790423

Reputation:

This works best

.btn-primary.focus, .btn-primary:focus {
-webkit-box-shadow: none!important;
box-shadow: none!important;
}

Upvotes: 2

yennefer
yennefer

Reputation: 189

.btn:focus:active {
  outline: none;
}

this removes the outline on click, but keeps the focus when tabbing (for a11y)

Upvotes: 2

Tomasz Waszczyk
Tomasz Waszczyk

Reputation: 3129

For AngularJS developers I use from the solution:

var element = $window.document.getElementById("export-button");
    if (element){
        element.blur();
    }

Remember to inject $window.

Upvotes: -2

Nate Symer
Nate Symer

Reputation: 2293

If you're using a webkit browser (and potentially a browser compatible with webkit vendor prefixing), that outline belongs to the button's -webkit-focus-ring pseudoclass. Simply set it's outline to none:

*:-webkit-focus-ring {
  outline: none;
}

Chrome is such a webkit browser, and this effect happens on Linux too (not just a macOS thing, although some Chrome styles are macOS only)

Upvotes: 0

zmechanic
zmechanic

Reputation: 1990

You can set tabIndex="-1". It will make browser to skip this button when you TAB through focusable controls.

Other "fixes" suggested here, only remove focus outline, but still leaves buttons tabable. However, from usability point of view, you already removed glow, so your user won't know what is currently focused button, any way.

On other hand, making button non-tabable have accessibility implications.

I'm using it to remove focus outline from X button in bootstrap modal, which have duplicate "Close" button at the bottom any way, so my solution have no impact on accessibility.

Upvotes: 1

Milan Panigrahi
Milan Panigrahi

Reputation: 546

  .btn:focus,.btn:active, a{
        outline: none !important;
        box-shadow: none;
     }

this outline:none will work for both button and a tag

Upvotes: 1

menaka_
menaka_

Reputation: 1100

This worked for me. I created a custom class which overrides the necessary CSS.

.custom-button:focus {
    outline: none !important;
    border: none !important;
    -webkit-box-shadow: none !important;
    box-shadow: none !important;
}

enter image description here

The -webkit-box-shadow will work for Chrome and safari browsers.

Upvotes: 18

Rob
Rob

Reputation: 1216

This works for me, another solution not mentioned. Just throw it in the click event...

$(this).trigger("blur");

Or call it from another event/method...

$(".btn_name").trigger("blur");

Upvotes: 12

Related Questions