CSS 的伪类选择器和伪元素选择器,让 CSS 有了更为强大的功能。css
伪类你们听的多了,伪元素可能听到的不是那么频繁,其实 CSS 对这两个是有区分的。html
有个错误有必要每次讲到伪类都提一下,有时你会发现伪类元素使用了两个冒号 (::) 而不是一个冒号 (:),这是 CSS3 规范中的一部分要求,目的是为了区分伪类和伪元素,大多数浏览器都支持下面这两种表示方式。git
一般而言,github
web
#id:after{ ... } 复制代码#id::after{ ... } 复制代码复制代码
符合标准而言,单冒号(:)用于 CSS3 伪类,双冒号(::)用于 CSS3 伪元素。浏览器
固然,也有例外,对于 CSS2 中已经有的伪元素,例如 :before,单冒号和双冒号的写法 ::before 做用是同样的。安全
因此,若是你的网站只须要兼容 webkit、firefox、opera 等浏览器或者是移动端页面,建议对于伪元素采用双冒号的写法,若是不得不兼容低版本 IE 浏览器,仍是用 CSS2 的单冒号写法比较安全。svg
伪类选择器 :focus-within
言归正传,今天要说的就是:focus-within
伪类选择器。post
它表示一个元素得到焦点,或,该元素的后代元素得到焦点。划重点,它或它的后代得到焦点。网站
这也就意味着,它或它的后代得到焦点,均可以触发 :focus-within
。
:focus-within
的冒泡性
这个属性有点相似 Javascript 的事件冒泡,从可获焦元素开始一直冒泡到根元素 html
,均可以接收触发 :focus-within
事件,相似下面这个简单的例子这样:
<div class="g-father">
<div class="g-children">
<input type="button" value="Button">
</div>
</div>
复制代码复制代码
html, body, .g-father, .g-children { padding: 30px; border:1px solid #999; }input { ... &:focus { background: #00bcd4; } }
复制代码html:focus-within { background: #e91e63; } body:focus-within { background: #ff5722; } .g-father:focus-within { background: #ffeb3b; } .g-children:focus-within { background: #4caf50; } 复制代码复制代码
就是这样:

CodePen Demo -- :focus-within 冒泡触发
这个选择器的存在,让 CSS 有了进一步的让元素持久停留在一种新状态的的能力。
下面几个例子,看看 :focus-within
能够提供什么能力,作些什么事情。
感应用户聚焦区域
它或它的后代得到焦点,这一点使得让感知获焦区域变得更大,因此,最常规的用法就是使用 :focus-within
感应用户操做聚焦区域,高亮提醒。
下面的效果没有任何 JS 代码:

这里是什么意思呢?:focus-within
作了什么呢?
- 咱们无须去给获焦的元素设置
:focus
伪类,而是能够给须要的父元素设置,这样当元素获焦时,我能够一并控制它的父元素的样式
核心思想用 CSS 代码表达出来大概是这样:
<div class="g-container">
<div class="g-username">
<input type="text" placeholder="user name" class="g_input" >
</div>
<div class="g-username">
<input type="text" placeholder="code" class="g_input" >
</div>
</div>
复制代码复制代码
.g-container:focus-within { ...复制代码input { .... } 复制代码} 复制代码复制代码input { .... } 复制代码
DEMO -- CSS focus-within INPUT
运用上面思想,咱们能够把效果作的更炫一点点,在某些场景制做一些加强用户体验的效果:

DEMO -- PURE CSS FOCUS By :focus-within
TAB导航切换
在以前的一篇文章里,介绍了两种纯 CSS 实现的 TAB 导航栏切换方法:
如今又多了一种方式,利用了 :focus-within
能够在父节点获取元素得到焦点的特性,实现的TAB导航切换:

DEMO -- focus-within switch tab
主要的思路就是经过获焦态来控制其余选择器,以及最重要的是利用了父级的 :not(:focus-within)
来设置默认样式:
.nav-box:not(:focus-within) { // 默认样式 }.nav-A:focus-within ~ .content-box .content-A { display: block; }
复制代码.nav-B:focus-within ~ .content-box .content-B { display: block; } 复制代码复制代码
配合 :placeholder-shown
伪类实现表单效果
:focus-within
一我的能力有限,一般也会配合其余伪类实现一些不错的效果。这里要再简单介绍的是另一个有意思的伪类 :placeholder-shown
。
:placeholder-shown
:The :placeholder-shown CSS pseudo-class represents any<input>
or<textarea>
element that is currently displaying placeholder text.
另外,划重点,这个伪类是仍处于实验室的方案。也就是未归入标准,固然咱们的目的是探寻有意思的 CSS 。
意思大概就是,当 input
类型标签使用了 placeholder 属性有了默认占位的文字,会触发此伪类样式。配合:not()
伪类,能够再改变当默认文字消失后的样式,再配合本文的主角,咱们能够实现表单的一系列效果。
CSS 代码大概呈现成这样:
.g-container { width: 500px; height: 60px;复制代码input { height: 100%; width: 100%; &:not(:placeholder-shown) { ... } &:placeholder-shown { ... } } &:focus-within { ... } 复制代码} 复制代码复制代码input { height: 100%; width: 100%; &:not(:placeholder-shown) { ... } &:placeholder-shown { ... } } &:focus-within { ... } 复制代码
实际效果以下:

能够看到,上面的效果没有用到任何 JS,能够实现:
- 整个 input(包括父元素所在区域)获焦与非获焦样式控制
- placeholder 属性设置的文字出现与消失后样式控制
CodePen Demo -- :placeholder-shown && :focus-within
实现离屏导航
这个是其余不少文章都有提到过的一个功能,利用 focus-within
便捷的实现离屏导航,能够说将这个属性的功能发挥的淋漓尽致,这里我直接贴一个 codepen 上 Dannie Vinther 对这个效果的实现方案:

CodePen Demo -- Off-screen nav with :focus-within [PURE CSS]
实现掘金登陆动效切换
juejin.im是我很喜欢的一个博客网站,它的登陆有一个小彩蛋,最上面的熊猫在你输入账号密码的时候会有不一样的状态,效果以下:

利用本文所讲的 focus-within
,能够不借助任何 Javascript,实现这个动效:

感兴趣的能够戳这里看看完整的Demo代码:
兼容性
好了,例子举例的也差很少了,下面到了杀人诛心的兼容性时刻,按照惯例,这种属性大几率是一片红色,看看 CANIUSE,截图日期(2018/08/02),其实也还不算特别惨淡。

最后
感谢耐心读完。本文只是抛砖引玉,期待发掘 focus-within
更多有意义的用法。
更多精彩 CSS 技术文章汇总在个人 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。
好了,本文到此结束,但愿对你有帮助 :)
若是还有什么疑问或者建议,能够多多交流,原创文章,文笔有限,才疏学浅,文中如有不正之处,万望告知。