焦点元素的选择

通常,我们可以使用Tab键和Shift+Tab键,来进行焦点元素的选择。除了浏览器默认提供的input、button之类的元素,你也可以给其他元素添加tabindex属性,使其成为焦点元素,如下面的div元素,我们给它添加了tabindex属性,使其成为焦点元素,从而可以通过tab键来聚焦到它上面,再通过enter键来触发它的点击事件

<div id="test001" tabindex="0">点一下这个div</div>
点一下这个div

聚焦时的样式

使用focus伪类选择器,可以设置元素在被聚焦时的样式,如下面的button元素

button{
  outline: 4px solid red;
}

通常情况下,对于组件化开发,我们通常会将可交互的元素进一步封装成组件,而此时我们希望focus样式凸显出来的不是一个单独的交互元素,而是整个组件本身,这时候就需要使用:focus-within伪类选择器,它可以选择到当前元素或其子元素处于focus的状态,比如,博客的导航栏,当聚焦到导航栏的子元素a时,导航栏就会被选中,从而展示子导航栏(可尝试使用tab或shift+tab聚焦到导航栏体验)

/* 当menu-items内部的menu-item被tab选中聚焦时,父容器就会显现 */
.menu-trigger .menu-items:focus-within {
    display: block;
}

这个伪类将聚焦元素焦点的来源进行了区分,只会在通过键盘聚焦到此元素的时候才会被此伪类选中,通过鼠标点击触发的聚焦则不会被选中。

#test002:focus {
  outline: 4px solid green;
}
#test002:focus-visible {
  outline: 4px solid red;
}

使用这个伪类,就可以之将聚焦样式绑定到键盘交互上面,对于鼠标交互,则另外通过hover进行相应实现。

聚焦时的行为

Enter\Space与Escape

默认情况下,enter键和space空格键会触发焦点元素的click点击事件。在自定义组件中,我们可以通过监听click或者keydown事件,来实现自定义操作,如打开弹窗、侧边栏等。不过需要注意的是,由于我们通过自定义操作打开了新的组件,所以我们需要在监听回调中实现焦点元素的转移,即聚焦到新打开的组件中(escape也是一样,退出组件后,需要将焦点还给触发元素)

可使用tab键聚焦到我博客导航栏中的搜索键或面板键,enter打开,escape退出,体验一下


// 打开弹窗
triggerElement.addEventListener('keydown', (e) => {
  if (e.key === 'Enter') {
    // 打开弹窗
    // ...
    // 聚焦到弹窗元素
    modalElement中某个可聚焦元素.focus();
  }
})

// 退出弹窗
modalElement.addEventListener('keydown', (e) => {
  if (e.key === 'Escape') {
    // 关闭弹窗
    // ...
    // 聚焦到触发弹窗的元素
    triggerElement.focus();
  }
})

方向键与空格

通常,使用方向键和空格,可以进行表单项的选择

Apple Orange Banana

1 2

上述为一些常用表单元素,可尝试,一般我喜欢使用radio来设计组件(因为它可以使用方向键进行选择),比如下面的tabs组件,可以使用方向键切换tab

tabPane1
tabPane2
tabPane3
tabPane4
结语、方向键与其他按键

其实常用的交互按键,就是上面的tab、shift+tab、enter、escape、空格,而方向键则是用于操作焦点元素,如单选框、复选框等,还有就是页面滚动。这里就不再赘述了。 对于其他按键,你可以在自定义组件中通过监听事件来实现更多功能(比如我这里有一个代办计划就是,当聚焦到某个元素身上的时候,通过Capslock键来唤起相应的右键菜单(全局右键菜单,然后读取组件实现的特定接口,来展示相应的右键菜单))

DORAKIKA
我是一个喜欢折腾的前端工程师,对一切新鲜事物充满好奇,希望我的文章能给你带来思考和帮助
👋我是DORAKIKA
分享作者『DORAKIKA』发表的文章『元素focus与键盘交互』https://blog.dorakika.cn/post/20230408/
© 请您在需要时著名本文内容来源信息,若在文末注明“参考、扩展”等字样涉及转载第三方内容,请您一同复制
2023年
2023年
学业、工作、生活
grid布局实现自适应分栏组件
grid布局实现自适应分栏组件
需求来自于博客写作的自定义组件,想实现一个用于分栏展示的组件,综合考虑之后选择了实现一个grid布局组件(除了实现基本的分栏外,还可用于其他常见grid布局)