How can I unfocus the modal trigger button after closing the modal in bootstrap
Asked Answered
T

4

13

I can't seem to blur the button after closing the modal.

$('#exampleModal').on('hidden.bs.modal', function(e){
        $('button').blur();
    });

I've tried the above and it still doesn't seem to blur it. I've tried almost everything. The only solution is to set a timeout and blur it after the model finishes the hidden transition. Any better solution?

Thad answered 20/2, 2015 at 14:23 Comment(5)
I'm not clear on what button you're trying to remove focus from, see this example bootply. When the modal closes, the focus is not on any button used to close it. Can you clarify?Filibeg
Might be helpful if you could mock up your code on JS Fiddle or Bootply so we can see if there's anything with your code that may be preventing it.Kinnikinnick
@Filibeg What browser are you running in? When I run it on my work machine using Chrome, the button to launch the modal is certainly focused.Kinnikinnick
Ahhhh----I was focused on the close buttons. No pun intended.Filibeg
No worries, that's what comments are for. :D I plugged in the asker's JQ into your Bootply and it definitely doesn't cause the button to lose focus. bootply.com/eC1cXzeogYKinnikinnick
F
15

The focus back to the trigger element is set within the modal plugin using a .one() binding, which unfortunately cannot be unbound. The good news is we can do this:

$('#myModal').on('shown.bs.modal', function(e){
    $('#myModaltrigger').one('focus', function(e){$(this).blur();});
});

Where #myModaltrigger is the ID of the modal trigger button. The reason to use the .one() binding is so that the function to blur will be called only after the modal is shown. Once it hides, and the focus/blur happens, the button can be focused normally, like by tabbing to it, without it automatically blurring.

See this working example

Filibeg answered 20/2, 2015 at 16:10 Comment(5)
Gee this worked wonderfully. thanks! was wondering why i couldn't find an answer like this in stackoverflow.Thad
Note: You're harming your webpage's accessibility by doing this.Seng
@Seng Not really.It only removes focus from the trigger button after a modal is closed. After that, the button can be tabbed to without any problem, and wont un-focus itself. That's the point of of the .one() binding.Filibeg
AIUI, the problem is that it disorients users who use assistive technology. Blurring the button can make them lose their position on the page so they can't just pick up where they left off from before they opened the modal.Seng
@Seng I see what you're saying.Filibeg
L
3

Indeed, @cvrebert is right here that doing this negatively impacts accessibility.

blur() resets the focus, so keyboard users (both sighted keyboard users, and more critically users of screenreaders) are effectively bounced back to the very start of the page.

try http://jsbin.com/sukevefepo/1/ just using the keyboard: TAB to the button, trigger it with ENTER/SPACE, then TAB to the close button, ENTER/SPACE. now, after the modal is closed, TAB...and you see that your focus is back on the very first link. for anything but the most simple pages, this is a major annoyance at best, and can be dramatically disorienting for screenreader users).

in short: current Bootstrap behaviour is correct. I understand the desire to neuter the focused appearance of the modal trigger once the modal itself is closed...but using blur() is not the answer (unless you care little about keyboard/AT users, that is).

a more robust approach, that I'm planning to investigate for future version of Bootstrap, is to dynamically set a class on the body once a user first navigates using TAB/SHIFT+TAB (indicating a keyboard user), and to suppress :focus styles for these situations otherwise.

Lithometeor answered 1/3, 2015 at 11:11 Comment(1)
this would be more appropriate as a comment, not an answer, as it does not provide an answer to the question. And welcome to StackOverflowFilibeg
C
1

My solution which works with multiple modals on page (based on Bootstrap modal examples):

$('.modal').on('show.bs.modal', function (event) {
    var button = $(event.relatedTarget); // Button that triggered the modal
    button.one('focus', function (event) {
        $(this).blur();
    });
});
Charis answered 1/8, 2017 at 7:43 Comment(0)
S
0

Anno 2022 this might be sufficient for you:

TL;DR

// Remove focus from whatever element is active...
document.activeElement.blur?.();

Explanation

Here document.activeElement.blur?.():

  • gets the element that has focus on the webpage,
  • checks if the instance method blur exists
  • and invokes it if it does. (Focus is then removed from the element and applied to the body element).

The instance method check is necessary to prevent an error in case the selected element is an SVGElement (for example) which does not have a blur method, unlike an HTMLElement which does.

(I took this route to remove the focus (ring) from the trigger button in an Angular website where a ng-Bootstrap modal dialog was opened via an NgRx action and had no reference to which element triggered it.)

Statutable answered 15/11, 2022 at 14:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.