以前作了一个网页,网页中的全部输入框都被设计为“得到鼠标焦点时外边框不变蓝”。忽然某一天,产品以为这样用户体验很差,不能很明显地告诉用户当前鼠标停在哪里,因而要求改成“当输入框得到鼠标焦点时,外边框自动变蓝;失去焦点时外边框恢复原样”。php
浏览器自动会给输入框input
、textarea
的outline
属性设置一个默认值,效果就是当输入框得到鼠标焦点时外边框会自动带上颜色,失去焦点时外边框颜色消失。因为不一样浏览器outline
属性的默认值不一样,致使外边框的颜色也不一样。若是不想要浏览器的outline
默认设置,只须要将 outline
属性设置为none
便可。css
因此一开始听到这个需求,感受特别简单,不就是纯 CSS 的问题嘛!我只要将全部输入框的 outline
属性设置为浏览器默认的值就行了,但我想的太天真了。。。。web
因为网页中已有的输入框的样式遍及在各个文件中,有一种很是机械的办法,那就是到每一个文件中去删除掉输入框的 outline:none
样式,这样输入框就会使用浏览器默认的 outline 样式了。可是这样作要改的地方太多了,会疯掉的!再想一想有没有更省事的方法,有了!在最基本的base.css
样式文件中给输入框添加一个focus
时候的outline
样式不就解决了么。那么问题来了,该将outline
设置何值,才能自动使用浏览器默认的outline
样式呢?浏览器
我第一个想到的方法是将 outline
设置为auto
,但发现只有webkit 内核的浏览器才支持这个属性值,firefox 不支持,由于auto
并非标准的outline
值。因此要想直接复制浏览器默认的outline
样式是作不到的。难道我要针对每一个浏览器设置不一样的outline
值,为了这么一点破需求费那么大工夫?!算了,省事点的方式仍是直接摒弃浏览器的默认outline
样式,统一将outline
设置为一种样式好了。函数
但我发现了新问题,经过设置outline
样式为输入框添加外边框,效果并很差。由于 outline
没有相似 border-radius
的属性来改变边角的弧度。这样就致使了一个问题:当输入框设置了border
颜色,同时border-radius
为3px
以上时,能明显的看到outline
外边框并无和border
重合。看来设置 outline
来达到边框变蓝效果并非最好的选择,为何不选用设置 border
来达到一样的效果呢?只要将border
再设置下 border-shadow
,那么看起来也是和outline
效果同样的,并且border
还能设置border-radius
,显示效果更知足需求。firefox
经过设置 border 解决了大多数输入框,但发现又有了新问题。设计
网页中有些输入框其实并非单一使用 input
/textarea
来实现的,这类“输入框”看起来和通常输入框并没有两样,但其实 HTML 结构是一个 div
里面包含着一个 input
/textarea
来实现的。并且输入框的边框设置在了父元素 div
上,全部当输入框得到焦点时,看到的应该是父元素 div
上的边框变蓝,而不是里面的input
/textarea
的边框变蓝。code
要想得到焦点时父元素 div
的边框变蓝,确定可行的方法是经过 JS 来实现:给input
/textarea
绑定一个 focus
和 一个blur
事件,在focus
事件处理函数中将父元素div
的边框置蓝,在blur
事件处理函数中将父元素div
的边框恢复原样。这种方法时绝对可行的,可是我总以为应该有更简单的,纯粹使用 css 实现的方法。orm
若是想单纯经过css 实现,首先想到的是用选择器div:focus
。可是发现div
上没法使用:focus
伪类。因而我就猜测:可能并非全部的元素都是 focusable的,那么得找一份说明哪些元素 focusable的规范。事件
搜索结果:
根据 DOM Level 2 HTML规范,focusable 的DOM元素都会有一个原生的focus()
方法,只有 focusable 的DOM 元素才有 focus 事件,才能使用:focus
伪类。拥有原生的focus()
方法的DOM元素包括几种:HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement and HTMLAnchorElement。很明显,规范中遗漏了HTMLButtonElement and HTMLAreaElement。
虽然规范这么定义,但浏览器在实现时倒是另一套。浏览器给任何一个 HTMLElement 都定义focus()
方法,但并非任何一个HTMLElement 都能得到焦点(得到焦点术语叫 active, 具体请参考:http://help.dottoro.com/ljqmdirr.php)。通常来讲,任何一个时刻HTML 文档中只会有一个active元素,但并非任何一个元素都能成为active元素。能成为active 的元素包括:
表单元素(form controllers):input/option/textarea/button
连接元素(links):a
标签、area
标签(必需要带 href
属性,包括 href
属性为空)
能够被编辑的元素(包括经过添加 contenteditable = "true"
属性变成可编辑的状况)
设置了 tabindex
属性(tabindex
值非-1)的元素
window
:当页面窗口从隐藏变成前置可见时,focus
事件就会触发
根据搜索结果,要想将父元素div
变成focusable,只须要在元素上设置 tabindex 属性,而后经过:focus
伪类设置父元素div
得到焦点时的border
样式。但我发现当鼠标点击里面的 input
元素时,父元素div
并无得到焦点,得到焦点的是子元素input
。
因此最后仍是没能经过纯 css 的方法来解决这个问题,无奈之下我仍是经过js去解决了。。。。。。