基本介绍
简介 : 这个插件主要用于判断标签的聚焦方式,如果聚焦是由鼠标或触屏的点击导致的,被聚焦的标签会被添加 xj-focus-ontap
的类名,如果聚焦是由于按了键盘的 Tab 键导致的,被聚焦的标签会被添加 xj-focus-ontab
的类名,你可以简单的将这个插件当作是 :focus-visible
伪类的 Polyfill 方案,用它来区分设置不同聚焦方式下的 outline
外边框,为用户提供更好的样式和交互体验。
兼容 : IE10+ / Edge12+ / Firefox / Chrome / Safari / Opera / IOS Webkit / Android Platform
更新 : https://github.com/xjZone/xj.focus/blob/master/upgrade.md
源码 : https://github.com/xjZone/xj.focus/
协议 : Apache License 2.0
版本 :
引入插件
首先是引入相关的文件,推荐使用带 immutable 的 JSDelivr CDN:
常规标签
在引入插件之后,那些可被聚焦的元素,如果是通过点击导致的聚焦,就不会显示出外边框,如果是通过键盘的 Tab 键导致的聚焦,就会显示出外边框,但允许用户输入的那些可编辑的元素如 input[type="text"]
或 textarea
是例外,它们被聚焦的时候总会显示出外边框,这和 :focus-visible
伪类的表现是相同的,但这种特例你也可以通过 # 配置列表 里的 ontabSelector
参数进行修改。
媒体标签
根据 whatwg 描述,audio
和 video
标签的点击事件和键盘事件都不会传递到上层,也就是无法冒泡或捕获,这导致我们无法根据用户的操作方式来判断聚焦的形式,插件采取的做法是将它们的聚焦都当作由点击导致,所以不显示外边框,再用 :focus-visible
这个伪类选择器进行补充设置,如果你想了解更多相关信息或者希望改变这个设置,可以查看 # 配置列表 里的 ontapSelector
参数。
异形标签
两个特殊的标签 svg a
和 map area
,由于它们可能呈现不规则形状,所以如果对它们的设置 outline
或 box-shdoaw
样式,在 IE 和 Firefox 中可能不会生效,且可能导致浏览器原本自带的聚焦样式失效,考虑到兼容,所以插件没对它们设置聚焦样式,聚焦后的样式会保持浏览器的默认状态,如果你不需要兼容 IE 或 Firefox,可以通过 # 配置列表 里的 otherSelector
参数进行控制。
参数设置
插件提供了一些参数,用于定义聚焦的各种细节,而这些参数都可通过使用目标容器上的 xj-focus="{}"
这个内联属性来完成设置,下面是一个简单的例子,使用 ontabAlways
参数可让聚焦总被当作是按了 Tab 键导致的,从而显示出外边框,使用 ontapAlways
参数可让聚焦总被当作是通过点击导致的,从而不显示外边框,使用 otherAlways
参数可让插件什么也不做,保持浏览器默认状态。
测试状态
默认的情况下,当节点失焦后插件设置的相关类名就会同时被移除,这是为了避免聚焦状态继续被延续,但立即移除相关类名也导致了我们很难在 DevTool 面板中检查并调试它,所以插件提供了 debug
参数,当这个参数被设为 true
时,类名就不会被自动移除了,正如下面的例子中,第二个 input[type="text"]
由于设置了 debug:true
参数,所以在节点失焦之后插件相关的类名也不会被移除。
边框选择
插件提供了 style
参数,用于控制生成外边框所使用的样式,该参数默认值是 'auto'
,也就是除 Safari 之外的浏览器,默认都使用 box-shadow
样式来生成外边框,这是因为 box-shadow
能兼容圆角,而 Safari 则默认使用 outline
样式来生成外边框,这是因为 Safari 的表单控件没设置 -webkit-appearance:none;
则 box-shadow
样式就无法生效,下面是使用这些参数的简单案例。
内嵌模式
聚焦元素所在的父节点被设置了 overflow:hidden;
,那么聚焦后外边框就可能被裁剪而看不到,此时可使用 inset:true
的设置,来让边框变成内嵌模式,这样就不用担心因为裁剪而看不到的问题了,Firefox 默认的表单控件被设置了background-color:field;
,此时 inset
模式的 box-shadow
样式会无效,因此当使用了 style:'auto'
时,Firefox 会自动改用 outline
来生成内边框。
参数继承
内联属性 xj-focus="{}"
不是非得设置在被聚焦的节点上,其实设置在目标节点的上层节点也是可以的,只要 inherit
参数不明文设为 false
,那么这个内联属性的设置就可被继承,当目标节点和它的上层节点设置了同个属性时,层级越低的属性权重越高,继承的好处是如果想定义某个区域的边框,无需逐个设置,只需要设置父容器然后继承就行,下例展示了通过继承设置不同的 inset
参数。
针对 Firefox 的设置
下面的两段样式都是属于可选的,前者用于去掉 Firefox 聚焦后显示的多余边框,后者用于避免 Firefox(MacOS) 在聚焦后边框样式变成 ThreeDLightShadow
导致边框和外边框混在一起的问题,实际上不少框架如 Bootstrap 或 ElementUI 等都会帮我们完成这些样式重置的工作,所以实际上你也未必需要用到它们,尤其是第二段代码,如果你已经定义过这些表单控件的边框,那就不需要再设置了。
自定义边框的样式
xj.focus 主要用于区分 focus
事件的触发模式,至于说插件所提供的 xj.focus.css 样式文件,其实未必合适你的项目,毕竟不同项目的主色调都不一样,好在这个文件也不复杂,你可以选择忽略这个文件,然后自己重新定义一些更合适你的项目的样式规则,下面的代码就是 xj.focus.css 文件的所有内容了,如果不喜欢这个 #3399ff
既 rgba(51,153,255,0.750);
蓝色,就自定义其他的颜色吧。
xj.focus 对象
全局中的 xj.focus
对象上存放着一些属性和方法,version
属性会返回当前插件的版本,ontab
, ontap
, other
这三个属性可用于判断当前聚焦的类型,ontabSet()
, ontapSet()
, otherSet()
这三个方法则是可让节点进入对应的 focus
状态,并不是说真的会有聚焦操作的表现,只是节点上会出现对应的类名而已,下面是一个例子,你得审查元素,才能在点击按钮后看到对应的结果。
配置列表
以下 Demo 罗列了本插件所有可用的配置,并且展示了插件进行全局配置的具体操作方法,需要注意的是,全局配置得在引入插件之前就设置好,否则插件加载并执行的时候找不到配置,就会认为配置不存在,并且版本号也要对得上,否则插件也是不理会的,例如本页面使用的插件是 0.4.0
的版本,在 xj.focusConfig
对象后面跟着的就是 ['0.4.0']
,版本匹配是考虑到插件多版本并存而设计的。
参数列表
以下 Demo 罗列了本插件所有可用的参数,并且展示了插件进行参数预设的具体操作方法,需要注意的是,参数预设得在引入插件之前就设置好,否则插件加载并执行的时候找不到预设,就会认为预设不存在,并且版本号也要对得上,否则插件也是不理会的,例如本页面使用的插件是 0.4.0
的版本,在 xj.focusOption
对象后面跟着的就是 ['0.4.0']
,版本匹配是考虑到插件多版本并存而设计的。
项目备注
01. 使用 dispatchEvent()
方法触发的 focus
事件并不会真的在 UI 上实现聚焦,所以之后也不会触发 blur
事件,这就导致如果聚焦是由该方法触发的,那么 xj-focus-other
类名可能会长期存在,直到页面上某个节点真实触发了 blur
事件,才会被去掉。
02. 有疑问或者发现 BUG,可到 GitHub 提 Issue,如果觉得插件写得还行,在 GitHub 中为本项目点个 ★Star 吧,感谢啦 ಠ‿ಠ ❤。
推荐阅读
XJ.Chen - 浅谈 :focus 伪类选择器和聚焦后 outline 边框的设置问题