Chrome Extension - first link is auto-focused in popup

两盒软妹~` 提交于 2019-12-03 10:28:13

The easiest (and javascript free!) way is to simply add tabindex="-1" to any element which you don't want to receive automatic focus.

link0ff

Perhaps auto-focus was intended for a convenience, but often it does a disservice. Since I see no way to stop the root cause, I found some roundabouts. One is using JavaScript. Chrome puts auto-focus after a short delay after displaying the popup. It's possible to unfocus it with blur() but unfocusing it too late will flash it momentarily, and trying to unfocus too early will do nothing. So to find the right time to unfocus is not easy, and this solution tries to do this several times during the first second after the popup is displayed:

document.addEventListener("DOMContentLoaded", function () {
  var blurTimerId = window.setInterval(function() {
    if (document.activeElement != document.body) {
      document.activeElement.blur();
    }
  }, 200);
  window.setTimeout(function() {
    window.clearInterval(blurTimerId);
  }, 1000);
});

Another pure HTML solution is to add tabindex="1" to the body tag.

Wrangling the initially focused element with a tabindex attribute is probably the best way to go, using:

  • tabindex="-1", as suggested by Paul Ferret to prevent an element from getting focus
  • tabindex="1", as suggested by link0ff, to specify which element should start with focus

If your situation is more complicated and you do want to bring in some javascript, I'd recommend using link0ff's solution, except, instead of trying to guess when to blur with timeouts, listen for the initial focus in event:

function onInitialFocus(event) {
  // Any custom behavior your want to perform when the initial element is focused.

  // For example: If this is an anchor tag, remove focus
  if (event.target.tagName == "A") {
    event.target.blur();
  }

  // ALSO, remove this event listener after it is triggered,
  // so it's not applied to subsequent focus events
  document.removeEventListener("focusin", onInitialFocus);
}

// NOTE: the "focusin" event bubbles up to the document,
// but the "focus" event does not.
document.addEventListener("focusin", onInitialFocus);

I don't believe the focus event is cancelable, so you can't just suppress the event.

Another easy alternative (which preserves "tabbability") is to just add an empty link (<a href="#"></a>) before your first actual link. It will invisibly "catch" the auto-focus from Chrome, but any users who want to tab through the links will still be able to do so normally.

The only minor downside of this approach is that it introduces a second "dead tab" when looping; that is, users will have to press tab three times to get from the last link back to the first, instead of just twice.

Clinton Skakun

tabindex="-1" worked for me. I was adding autofocus to an input and it didn't work until I used this tabindex="-1" attribute for each link before the input.

Strange to say the least.

This is the best solution to the problem. The tabindex="-1" solution harms user experience, and as opposed to @link0ff's solution, this one removes the focus instantly.

This element should be the first focusable element in the DOM:

<button class="invisible-button"></button>

This simply removes the button once it's been focused:

function removeAutoFocus(e) {
    if (e.target.classList.contains("invisible-button")) {
        e.target.style.display = "none";
        document.removeEventListener("focus", removeAutoFocus);
    }
}
document.addEventListener("focus", removeAutoFocus, true);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!