你知道css3的focus-within选择器吗?

伪元素和伪类

说到这个,咱们先回顾一下,伪类选择器伪元素选择器,老版的浏览器没有严格区分下面 2 种写法。javascript

a:after{}
a::after{}
复制代码

在新的标准中,单冒号(:)用于 CSS3 伪类,双冒号(::)用于 CSS3 伪元素,咱们平时开发时能够注意一下,固然大多数浏览器两种写法都能识别。css

常见伪元素和伪类

伪类

:link, :visited, :hover, :active, :focus, :first-child, :last-child, :nth-child, :nth-last-child, :not()
复制代码

伪类通常用于一个元素的某个状态,好比说鼠标悬浮,按钮点击,连接已经访问,输入框聚焦等,还用于选择某个特殊元素,好比说多个元素中的第一个,最后一个,偶数,奇数等。其做用是对某个符合以上条件的元素添加一些样式。html

a:hover{
        text-decoration: underline;
    }
a:active {
    color: blue;
}
a:link {
    color: red;
}
a:visited {
    color: green;
}
复制代码

上面的例子展现了一个a标签在不一样状态下的不一样样式,在未点击连接以前,a标签呈现红色字体(link),在鼠标移到a标签上是,a标签出现下划线(hover),在鼠标按下的时候,a标签变为蓝色(active),点击完了以后,a标签变为绿色(visited)。能够看到,伪类的做用是为了给不一样状态的标签添加样式。前端

伪元素

::first-letter, ::first-line, ::before, ::after
复制代码

在内容模块中提到,伪元素若是没有设置“content”属性,伪元素是无用的。 使用伪元素插入的内容在页面的源码里是不可见的,只能在 css 里可见。 插入的元素在默认状况下是内联元素(或者,在 html5 中,在文本语义的类别里)。所以,为了给插入的元素赋予高度,填充,边距等等,你一般必须显式地定义它是一个块级元素。 还要注意的是典型的 CSS 继承规则适用于插入的元素。例如,你有字体系列黑体,宋体,无衬线字体应用到 body 元素里,而后伪元素会像其余元素同样继承这些字体系列。 伪元素不会天然继承自父元素(如 padding margins)的样式。 你的直觉是 :before 和 :after 伪元素多是插入的内容会被注入到目标元素的前或后注入。其实不是这样的,注入的内容将是有关联的目标元素的子元素,但它会被置于这个元素的任何内容的“前”或“后”。vue

<head>
    <style type="text/css"> p.box::before { content: "#"; border: solid 1px black; padding: 2px; margin: 0 10px 0 0; } p.box::after { content: "#"; border: solid 1px black; padding: 2px; margin: 0 10px 0 0; } </style>
</head>
<body>
<p class="box">Other content.</p>
</body>
复制代码

运行效果: 运行效果 能够看到,咱们html部分只写了一个元素,可是咱们利用伪元素渲染出来 3 个部分,前中后,这里咱们能够认为,伪元素通常用来辅助html的元素。但在内容页面的源码又看不到,利用伪元素能够实现不少神奇的功能,这里不作具体讲解,后面再出具体教程。html5

神奇的伪类:focus-within

言归正传,回到咱们的主角focus-within,咱们知道,伪类focus是指一个元素得到焦点时,为其添加样式。focus-within的范围更广,它表示一个元素得到焦点,或该元素的后代元素得到焦点。划重点,它或它的后代得到焦点。这也就意味着,它或它的后代得到焦点,均可以触发 :focus-withinjava

这个属性有点相似 Javascript 的事件冒泡,从可获焦元素开始一直冒泡到根元素 html,均可以接收触发 :focus-within 事件,相似下面这个简单的例子这样:css3

<html>
 <div class="box g-father">
        <div class="box g-children">
            <div class="box button" tabindex="1">button</div>
        </div>
  </div>
  <div class="g-body">HTML</div>
  <style> div { box-sizing: border-box; } .button,.g-children { width: 100%; height: 100%; padding: 20px; border: 1px solid; } .g-father { width: 200px; height: 200px; padding: 20px; border: 1px solid; } .g-body { margin-top: 20px; width: 200px; border: 1px solid; } .g-body:focus-within { background-color: #5daf34; } .g-father:focus-within { background-color: #3a8ee6; } .g-children:focus-within{ background-color: #2c3e50; } .button:focus-within { background-color: #606266; color: red; } </style>
</html>
复制代码

运行结果: 运行结果 能够看到,在button得到焦点时,由于冒泡的缘由,它的父级元素所有应用了:focus-within的样式。这里值得注意的是,正常的div是不能得到焦点的,设置 tabindex 属性才能获取焦点,同时按键盘 Tab 键也可以让其获取焦点,其中 tabindex 的值越小在 tab 键切换的时候就会首先聚焦。根据:focus-within的特性,咱们在不利用 js 的状况下,实现不少实用性的功能。git

感应用户聚焦区域

利用focus-within能够增长用户的感知区域,让用户得到更好的视觉反馈。github

<html>
 <div class="g-container">
      <input type="text" placeholder="user name" class="g_input" >
      <input type="text" placeholder="code" class="g_input" >
  </div>
  <style>
    .g-container {
        margin-top: 10vh;
    }
    .g-container {
        padding: 10px;
        width: 30vw;
        border: 1px solid #eee;
        transition: all .3s;
        text-align: center;
    }
    .g-container:focus-within {
        transform: translateY(-4px);
        box-shadow: 0 0 10px #ddd;
        border-color: hsl(199, 98%, 48%);
    }
    .g_input {
        border: none;
        width: 20vw;
        padding: 15px;
        font-size: 18px;
        box-sizing: border-box;
        border: 1px solid #ddd;
        overflow: hidden;
        transition: 0.3s;
        box-shadow: 0 0 0px #ddd;
        &:focus {
            box-shadow: 0 0 10px #ddd;
            border-color: hsl(199, 98%, 48%);
        }
    }
    </style>
</html>
复制代码

运行效果 能够看到在没有任何javascript逻辑控制状况下,用focus-within就实现了上面的效果。

实现离屏导航

咱们先看一下效果: 效果

能够看到是一个很棒的导航效果,并且真个实现没有使用javascript控制,这无疑在性能和体验上都有很多提高。具体源码能够看下面的地址:地址

实现 B 站,掘金等网站登陆动效切换

咱们平时可能注意到了,B 站和掘金在用户输入密码的时候,上面的图片是捂着眼睛的,这里咱们也能够用focus-within来实现。 掘金效果

<html>
 <div class="g-wrap"></div>
        <div class="g-container">
            <h2>登陆</h2>
            <div class="g-username">
                <input maxlength="64" placeholder="请输入手机号或邮箱" class="input">
                <img src="https://b-gold-cdn.xitu.io/v3/static/img/greeting.1415c1c.png" class="g-username">
            </div>
            <div class="g-password">
                <input type="password" maxlength="64" placeholder="请输入密码" class="input">
                <img src="https://b-gold-cdn.xitu.io/v3/static/img/blindfold.58ce423.png" class="g-password">
            </div>
            <img src="https://b-gold-cdn.xitu.io/v3/static/img/normal.0447fe9.png" class="g-normal">
    </div>
<style> .g-wrap { position: fixed; top: 0; left: 0; bottom: 0; right: 0; background: rgba(0, 0, 0, 0.3); }  .g-container { position: relative; width: 318px; margin: 100px auto; height: 370px; padding: 20px; box-sizing: border-box; background: #fff; z-index: 10; } .g-container h2 { font-size: 20px; font-weight: bold; margin-bottom: 30px; } .g-container input { outline: none; padding: 10px; width: 100%; border: 1px solid #e9e9e9; border-radius: 2px; outline: none; box-sizing: border-box; font-size: 16px; }  img { position: absolute; top: -20%; left: 50%; width: 120px; height: 95px; transform: translate(-50%, 0); }  .g-username { margin-bottom: 10px; } .g-username img { display: none; width: 120px; height: 113px; }  .g-username:focus-within ~ img { display: none; }  .g-username:focus-within input { border-color: #007fff; } .g-username:focus-within img { display: block; }  .g-password { margin-bottom: 10px; } .g-password img { display: none; width: 103px; height: 84px; top: -15%; }  .g-password:focus-within ~ img { display: none; }  .g-password:focus-within input { border-color: #007fff; } .g-password:focus-within img { display: block; } </style> </html> 复制代码

能够看到,在不适用js的状况下,也能实现动态切换图片的效果,可是仍是有一些局限,dom排列只能是父级向上,不能把元素放在focus元素的子元素里面。因此没有js灵活,可是代码量更少。

focus-within 兼容性

由于 css3 的新增特性一直存在兼容问题,这里查询了一下它的兼容性,看到红色区域仍是不算太惨淡,出来 ie,其余浏览器基本都支持了。 兼容性

全部的源码均可以在个人仓库地址:地址

我的博客:地址

文章参考连接:地址

学习如逆水行舟,不进则退,前端技术飞速发展,若是天天不坚持学习,就会跟不上,我会陪着你们,天天坚持推送博文,跟你们一同进步,但愿你们能关注我,第一时间收到最新文章。

公众号: 公众号

相关文章
相关标签/搜索