神奇的选择器 :focus-within

(点击上方公众号,可快速关注)


作者:伯乐在线/chokcoco

http://web.jobbole.com/95025/


CSS 的伪类选择器和伪元素选择器,让 CSS 有了更为强大的功能。


伪类大家听的多了,伪元素可能听到的不是那么频繁,其实 CSS 对这两个是有区分的。


有个错误有必要每次讲到伪类都提一下,有时你会发现伪类元素使用了两个冒号 (::) 而不是一个冒号 (:),这是 CSS3 规范中的一部分要求,目的是为了区分伪类和伪元素,大多数浏览器都支持下面这两种表示方式。


通常而言,


#id:after{

...

}

#id::after{

...

}


符合标准而言,单冒号(:)用于 CSS3 伪类,双冒号(::)用于 CSS3 伪元素。


当然,也有例外,对于 CSS2 中已经有的伪元素,例如 :before,单冒号和双冒号的写法 ::before 作用是一样的。


所以,如果你的网站只需要兼容 webkit、firefox、opera 等浏览器或者是移动端页面,建议对于伪元素采用双冒号的写法,如果不得不兼容低版本 IE 浏览器,还是用 CSS2 的单冒号写法比较安全。


伪类选择器 :focus-within


言归正传,今天要说的就是:focus-within 伪类选择器。


它表示一个元素获得焦点,或,该元素的后代元素获得焦点。划重点,它或它的后代获得焦点。


这也就意味着,它或它的后代获得焦点,都可以触发 :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;

}


640?wx_fmt=gif


CodePen Demo — :focus-within 冒泡触发(https://codepen.io/Chokcoco/pen/gjeoPg)


这个选择器的存在,让 CSS 有了进一步的让元素持久停留在一种新状态的的能力。


下面几个例子,看看 :focus-within 可以提供什么能力,做些什么事情。


感应用户聚焦区域


它或它的后代获得焦点,这一点使得让感知获焦区域变得更大,所以,最常规的用法就是使用 :focus-within 感应用户操作聚焦区域,高亮提醒。


下面的效果没有任何 JS 代码:


640?wx_fmt=gif


这里是什么意思呢?: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 {

        ....

    }

}


DEMO — CSS focus-within INPUT(https://codepen.io/Chokcoco/pen/rrJeLj)


运用上面思想,我们可以把效果做的更炫一点点,在某些场景制作一些增强用户体验的效果:


640?wx_fmt=gif


DEMO — PURE CSS FOCUS By :focus-within(https://codepen.io/Chokcoco/pen/EpEjQX?editors=1100)


TAB导航切换


在之前的一篇文章里,介绍了两种纯 CSS 实现的 TAB 导航栏切换方法:


纯CSS的导航栏Tab切换方案


现在又多了一种方式,利用了 :focus-within 可以在父节点获取元素获得焦点的特性,实现的TAB导航切换:


640?wx_fmt=gif


DEMO — focus-within switch tab(https://codepen.io/Chokcoco/pen/RJEpaP)


主要的思路就是通过获焦态来控制其他选择器,以及最重要的是利用了父级的 :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 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 {

        ...

    }

}


实际效果如下:


640?wx_fmt=gif


可以看到,上面的效果没有用到任何 JS,可以实现:


  1. 整个 input(包括父元素所在区域)获焦与非获焦样式控制

  2. placeholder 属性设置的文字出现与消失后样式控制


CodePen Demo — :placeholder-shown && :focus-within(https://codepen.io/Chokcoco/pen/xJWwyB)


实现离屏导航


这个是其他很多文章都有提到过的一个功能,利用 focus-within 便捷的实现离屏导航,可以说将这个属性的功能发挥的淋漓尽致,这里我直接贴一个 codepen 上 Dannie Vinther 对这个效果的实现方案:


640?wx_fmt=gif


CodePen Demo — Off-screen nav with :focus-within [PURE CSS](https://codepen.io/dannievinther/pen/NvZjvz)


实现掘金登录动效切换


juejin.im是我很喜欢的一个博客网站,它的登录有一个小彩蛋,最上面的熊猫在你输入帐号密码的时候会有不同的状态,效果如下:


640?wx_fmt=gif


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


640?wx_fmt=gif


感兴趣的可以戳这里看看完整的Demo代码:


CodePen Demo — 掘金登录效果纯CSS实现(https://codepen.io/Chokcoco/pen/yqKrPR?editors=1100)


兼容性


好了,例子举例的也差不多了,下面到了杀人诛心的兼容性时刻,按照惯例,这种属性大概率是一片红色,看看 CANIUSE,截图日期(2018/08/02),其实也还不算特别惨淡。


640?wx_fmt=jpeg

 

最后


感谢耐心读完。本文只是抛砖引玉,期待发掘 focus-within 更多有意义的用法。


更多精彩 CSS 技术文章汇总在我的 Github — iCSS ,持续更新,欢迎点个 star 订阅收藏。


好了,本文到此结束,希望对你有帮助 :)


如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。



【关于投稿】


如果大家有原创好文投稿,请直接给公号发送留言。


① 留言格式:
【投稿】+《 文章标题》+ 文章链接

② 示例:
【投稿】《不要自称是程序员,我十多年的 IT 职场总结》:http://blog.jobbole.com/94148/

③ 最后请附上您的个人简介哈~



觉得本文对你有帮助?请分享给更多人

关注「前端大全」,提升前端技能

640?wx_fmt=png

640?wx_fmt=jpeg

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值