page contents

在CSS中实现定位父级选择器效果

为何CSS不支持父选择器? 这个问题的答案和“为何CSS相邻兄弟选择器只支持后面的元素,而不支持前面的兄弟元素?”是一样的。 浏览器解析HTML文档,是从前往后,由外及里的。所以,我们时常会...

attachments-2021-05-nP8wpAuR60b1b5917a07e.png

为何CSS不支持父选择器?

这个问题的答案和“为何CSS相邻兄弟选择器只支持后面的元素,而不支持前面的兄弟元素?”是一样的。

浏览器解析HTML文档,是从前往后,由外及里的。所以,我们时常会看到页面先出现头部然后主体内容再出现的加载情况。

但是,如果CSS支持了父选择器,那就必须要页面所有子元素加载完毕才能渲染HTML文档,因为所谓“父选择器”,就是后代元素影响祖先元素,如果后代元素还没加载处理,如何影响祖先元素的样式?于是,网页渲染呈现速度就会大大减慢,浏览器会出现长时间的白板。加载多少HTML就可以渲染多少HTML,在网速不是很快的时候,就显得尤为的必要。比方说你现在看的这篇文章,只要文章内容加载出来就可以了,就算后面的广告脚本阻塞了后续HTML文档的加载,我们也是可以阅读和体验。但是,如果支持父选择器,则整个文档不能有阻塞,页面的可访问性则要大大降低。

有人可能会说,要不采取加载到哪里就渲染到哪里的策略?这样子问题更大,因为会出现加载到子元素的时候,父元素本来渲染的样式突然变成了另外一个样式的情况,体验非常不好。

“相邻选择器只能选择后面的元素”也是一样的道理,不可能说后面的HTML加载好了,还会影响前面HTML的样式。

所以,从这一点来讲,CSS支持“父选择器”或者“前兄弟选择器”的可能性要比其他炫酷的CSS特性要低,倒不是技术层面,而是CSS和HTML本身的渲染机制决定的。当然,以后的事情谁都说不准,说不定以后网速都是每秒几个G的,网页加载速度完全就忽略不计,说不定就会支持了。

如何在CSS中实现父选择器效果?

虽然说至今尚无浏览器支持原生的父选择器效果,但是,我们是可以通过其他手段来实现父选择器效果的,虽说不是100%完全,但是,一般的项目需求都是可以满足的,如何实现呢?如果用一句话解释原理就是“把兄弟元素作为祖先元素使用”。

本文介绍的“父选择器”技术,涉及多个技术tips,但是,幸运的是,这些特性从IE7浏览器开始都是支持的,因此,本文的模拟父选择器效果兼容IE7+浏览器。

类似这样的技术tips学习,你唾沫横飞说得天花乱坠也不如一个活蹦乱跳的实例效果好。

.container {
    min-height: 120px;
    /* z-index用来创建新的层叠上下文,这样子元素的z-index:-1不会超出容器 
       具体可参见:http://www.zhangxinxu.com/wordpress/?p=5115
    */
    position: relative; z-index: 1;
}
.list {
    /* 已经输入的姓名列表 */
    display: inline-block; background-color: #f0f3f9;
}
.list:after {
    content: '×';
}
.input {
    /* 去掉输入框默认UI */
    width: 80px; border: 0; background: none;  
}
.border {
    /* 尺寸永远和容器一样大,假装是容器 */
    position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -1;
    border: 1px solid #bbb;
}
.input:focus + .border {
    /* 模拟父选择器效果精髓所在 */
    border-color: #1271E0;    
}
HTML代码:
<div class="container">
    <span class="list">李易峰</span>
    <span class="list">赵丽颖</span>
    <span class="list">杨紫</span><input id="input" class="input">
    <label class="border" for="input"></label>
</div>

类似这种效果大家一定见过,就是我们在写邮件的时候,在输入收件人的时候,会自动匹配名字,当我们选中此名字后,就会在输入区域的前面显示。实际在web网页开发的时候,这种交互也是会遇到的,比方说一次性给多个好友发送私信的时候,或者类似demo这里给《楚乔传》添加主演姓名信息。

一般而言,输入框藏在姓名列表的后面。

长度不会很长,因为容易换到下一行。好了,现在需求来了,交互设计师希望用户focus这个小小输入框的时候,外面容器的灰色边框要高亮。

请问如何实现?

市面上,90%及其以上都是使用JS实现的,类似这样:

$('input').focus(function() {
    $(this).parent().addClass('highlight');
});

因为没办法呀,没有浏览器支持父选择器!

此时,广大CSSer的心中一定在呐喊,如果天降一个父选择器该多好啊!这就是为何父选择器呼声很高的原因之一,因为确实有广泛的应用场景。

好了,回到现实,浏览器支持父选择器遥遥无期!

是固执地希望用纯CSS实现还是妥协JS实现?OK,告诉大家,纯CSS是可以实现的,而且就是一些简单的CSS特性组合而成实现的,没有什么高深难懂的地方,而且兼容性出奇的好,IE7+浏览器都支持。

focus输入框,父级元素高亮

大致分为下面3步:

  1. 原先的父级容器只处理结构,不负责外观。CSS代码如下:
.container {
    min-height: 120px;
    position: relative; z-index: 1;
}

其中,这里的z-index:1用来创建新的层叠上下文,这样子元素的z-index:-1不会超出容器

  1. 新建一个元素负责容器的外观,放置在输入框的后面,使用absolute拉伸和容器尺寸一致。于是HTML结构变成这样:
<div class="container">
    <input id="input" class="input">
    <!-- 下面的label就是新建的负责容器外观的元素 -->
    <label class="border" for="input"></label>
</div>

CSS:

.border {
    /* 尺寸自适应容器大小,假装是容器 */
    position: absolute; left: 0; right: 0; top: 0; bottom: 0; 
    /* 在输入框的下面 */
    z-index: -1;
    /* 外观模拟 */
    border: 1px solid #bbb;
}

绝对定位元素,如果没有具体的width/height限定,left/right以及top/bottom对立方位的数值会拉伸元素的尺寸。这里这里,全部都设为0,和.container所在元素组合,就形成了类似宽高100%同时box-sizing:border-box;的效果,所以,如果你想让IE7浏览器实现类似border-box的盒尺寸计算,某些情况下,就可以使用绝对定位拉伸,是张鑫旭告诉我的!

  1. 通过相邻兄弟选择器,控制容器的样式变化,CSS代码如下:
.input:focus + .border {
    /* 容器边框颜色高亮 */
    border-color: #1271E0;    
}

于是乎,当我们focus输入框的时候,那个大大的灰色边框就高亮了!看上去高亮的是外部的容器,实际上是输入框的兄弟元素,这就是上面所说的“把兄弟元素作为祖先元素使用”!

小结
基本上,所以需要使用父选择器控制样式的地方,都可以使用这种策略实现。本文的例子就全当是抛砖引玉,当在座的诸位以后遇到类似需求的时候,希望可以想起这篇文章,说不定会对你的实现带来全新的思路。

关于父选择器的一些八卦知识

总结一下就是2个槽点:

CSS4中父选择器的语法变身了3次:

2011年,语法是$E > F,例如:

$input:focus > .container {}

这种语法是网络上流传最多的用法,实际上,早就淘汰很久了,大家要明鉴啊!

  • 2012-2013年的语法是!E > F,例如:
!input:focus > .container {}

昙花一现

  • 2014年,语法使用:has()伪类(Relational Pseudo-class),例如:
container:has(> input:focus) {}

最后一次的变身:has推迟到CSS5了。

恩,大家这下都明白了吧!

哈?明白什么?这还要问吗,那就是至少10年之内不会出现CSS父选择器了呀!还CSS5呢,也不看看CSS4这会儿才刚刚开始长毛呢!

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

程序员编程交流QQ群:805358732

如果你想用Python开辟副业赚钱,但不熟悉爬虫与反爬虫技术,没有接单途径,也缺乏兼职经验
关注下方微信公众号:Python编程学习圈,获取价值999元全套Python入门到进阶的学习资料以及教程,还有Python技术交流群一起交流学习哦。

attachments-2022-06-gHBQ4NGK62ac1a885e3f3.jpeg

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1312 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章