如何在没有轮廓的情况下以pragrammatically方式关注HTML元素?

时间:2022-08-27 12:11:42

Caution: :focus { outline: none } should not be the answer as it also prevents outline when navigating by tab key

注意:: focus {outline:none}不应该是答案,因为它还可以在按Tab键导航时阻止轮廓

Clicking a button does not show outline but the button becomes document.activeElement (JSFiddle). I want to mimic this behavior without mouse clicking.

单击按钮不显示轮廓,但按钮变为document.activeElement(JSFiddle)。我想在没有鼠标点击的情况下模仿这种行为。

如何在没有轮廓的情况下以pragrammatically方式关注HTML元素?

The method should:

该方法应该:

  1. make the element as document.activeElement.
  2. 将元素设为document.activeElement。

  3. not cause outline
  4. 不引起大纲

  5. still allow outline when pressing keyboard tab key
  6. 按键盘标签键时仍然允许轮廓

(If anyone asks, my current intention is to focus a modal dialog and return the focus to the previous focused element when the dialog is closed. This requires preventing outline for seamless experience.)

(如果有人问,我目前的目的是聚焦一个模态对话框,并在对话框关闭时将焦点返回到前一个聚焦元素。这需要防止轮廓无缝体验。)

pseudo code:

showDialog();

function whenDialogClosed() {
  previouslyFocused.focus(); // should not display outline
}

2 个解决方案

#1


1  

You could add a transition to the unfocus.

您可以向非焦点添加过渡。

var dial = document.getElementById('dial');
var focused;
function openDialog(){
  document.body.className="havingFocus";
  dial.className="";
  focused = document.activeElement;
  document.getElementById('new_focus').focus();
}
function closeDialog(){
  document.body.className="";
  dial.className="hidden";  
  focused.focus();
}
.havingFocus * {
  transition: all 0s;
  transition-delay: 20000s;
  outline: 1px solid transparent;
}
*:focus{
  transition-delay:0s;
  outline: 2px solid highlight;
}

div{
  margin:20px;
  border:1px solid black;
  padding: 20px;
  position:relative;
}
div:before{
  content:'x';
  position: absolute;
  right:10px;
  top:0px;
}

.hidden{
  display:none;
}
<input value="test123"/>
<div id="dial" class="hidden">
  <input value="in dialog" id="input"/>
  <button onclick="closeDialog()" id="new_focus">close</button>
</div>
<button onclick="openDialog()">open</button>

#2


0  

CSS finally got an answer by adding a pseudo-class :focus-visible that activates exactly when browser decides to do.

CSS最后通过添加一个伪类得到了答案:焦点可见,在浏览器决定时会激活。

For this reason, modern browsers apply simple heuristics to determine whether or not to apply their default focus styling. In general, if an element received focus as a result of a mouse/pointer click, browsers will suppress their default focus indication.

出于这个原因,现代浏览器应用简单的启发式方法来确定是否应用其默认焦点样式。通常,如果某个元素因鼠标/指针点击而获得焦点,则浏览器将禁止其默认焦点指示。

As of Sep 2018, no browser supports the property yet so you should use a polyfill and do this:

截至2018年9月,没有浏览器支持该属性,因此您应该使用polyfill并执行以下操作:

/*
 * .js-focus-visible is automatically added to document.body
 * to ensure the rules run only in JS-supported environment
 */

.js-focus-visible .your-selector:focus:not(.focus-visible) { outline: none }

Demo:

focusrandom.addEventListener("click", () => {
  const num = Math.ceil(Math.random() * 5);
  const button = document.getElementById(`button${num}`);
  button.focus();
});
wofocusrandom.addEventListener("click", () => {
  const num = Math.ceil(Math.random() * 5);
  const button = document.getElementById(`wobutton${num}`);
  button.focus();
});
.js-focus-visible .apply button:focus:not(.focus-visible) {
  outline: none;
}
<script src="https://unpkg.com/focus-visible"></script>
<p class="apply">
  With focus-visible:
  <button id="button1">1</button>
  <button id="button2">2</button>
  <button id="button3">3</button>
  <button id="button4">4</button>
  <button id="button5">5</button>
</p>
<p>
  Without focus-visible:
  <button id="wobutton1">1</button>
  <button id="wobutton2">2</button>
  <button id="wobutton3">3</button>
  <button id="wobutton4">4</button>
  <button id="wobutton5">5</button>
</p>

<button id="focusrandom">Focus random button</button>
<button id="wofocusrandom">Focus random button without focus-visible</button>

(From https://*.com/a/50571098/2460034. Thank you Aaron!)

(来自https://*.com/a/50571098/2460034。谢谢Aaron!)

#1


1  

You could add a transition to the unfocus.

您可以向非焦点添加过渡。

var dial = document.getElementById('dial');
var focused;
function openDialog(){
  document.body.className="havingFocus";
  dial.className="";
  focused = document.activeElement;
  document.getElementById('new_focus').focus();
}
function closeDialog(){
  document.body.className="";
  dial.className="hidden";  
  focused.focus();
}
.havingFocus * {
  transition: all 0s;
  transition-delay: 20000s;
  outline: 1px solid transparent;
}
*:focus{
  transition-delay:0s;
  outline: 2px solid highlight;
}

div{
  margin:20px;
  border:1px solid black;
  padding: 20px;
  position:relative;
}
div:before{
  content:'x';
  position: absolute;
  right:10px;
  top:0px;
}

.hidden{
  display:none;
}
<input value="test123"/>
<div id="dial" class="hidden">
  <input value="in dialog" id="input"/>
  <button onclick="closeDialog()" id="new_focus">close</button>
</div>
<button onclick="openDialog()">open</button>

#2


0  

CSS finally got an answer by adding a pseudo-class :focus-visible that activates exactly when browser decides to do.

CSS最后通过添加一个伪类得到了答案:焦点可见,在浏览器决定时会激活。

For this reason, modern browsers apply simple heuristics to determine whether or not to apply their default focus styling. In general, if an element received focus as a result of a mouse/pointer click, browsers will suppress their default focus indication.

出于这个原因,现代浏览器应用简单的启发式方法来确定是否应用其默认焦点样式。通常,如果某个元素因鼠标/指针点击而获得焦点,则浏览器将禁止其默认焦点指示。

As of Sep 2018, no browser supports the property yet so you should use a polyfill and do this:

截至2018年9月,没有浏览器支持该属性,因此您应该使用polyfill并执行以下操作:

/*
 * .js-focus-visible is automatically added to document.body
 * to ensure the rules run only in JS-supported environment
 */

.js-focus-visible .your-selector:focus:not(.focus-visible) { outline: none }

Demo:

focusrandom.addEventListener("click", () => {
  const num = Math.ceil(Math.random() * 5);
  const button = document.getElementById(`button${num}`);
  button.focus();
});
wofocusrandom.addEventListener("click", () => {
  const num = Math.ceil(Math.random() * 5);
  const button = document.getElementById(`wobutton${num}`);
  button.focus();
});
.js-focus-visible .apply button:focus:not(.focus-visible) {
  outline: none;
}
<script src="https://unpkg.com/focus-visible"></script>
<p class="apply">
  With focus-visible:
  <button id="button1">1</button>
  <button id="button2">2</button>
  <button id="button3">3</button>
  <button id="button4">4</button>
  <button id="button5">5</button>
</p>
<p>
  Without focus-visible:
  <button id="wobutton1">1</button>
  <button id="wobutton2">2</button>
  <button id="wobutton3">3</button>
  <button id="wobutton4">4</button>
  <button id="wobutton5">5</button>
</p>

<button id="focusrandom">Focus random button</button>
<button id="wofocusrandom">Focus random button without focus-visible</button>

(From https://*.com/a/50571098/2460034. Thank you Aaron!)

(来自https://*.com/a/50571098/2460034。谢谢Aaron!)