惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

有赞技术团队
有赞技术团队
G
Google Developers Blog
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
J
Java Code Geeks
P
Proofpoint News Feed
V
Visual Studio Blog
爱范儿
爱范儿
The Cloudflare Blog
博客园 - 叶小钗
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
M
MIT News - Artificial intelligence
Microsoft Security Blog
Microsoft Security Blog
博客园 - 聂微东
H
Help Net Security
B
Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 【当耐特】
量子位
宝玉的分享
宝玉的分享
WordPress大学
WordPress大学
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

张鑫旭-鑫空间-鑫生活

1分钟速度了解text-align match-parent声明 « 张鑫旭-鑫空间-鑫生活 光标的形状也能设置了,就是CSS caret-shape属性 « 张鑫旭-鑫空间-鑫生活 pretext与文字四面环绕效果的实现 « 张鑫旭-鑫空间-鑫生活 JSON.rawJSON方法的作用是什么? « 张鑫旭-鑫空间-鑫生活 如何使用CSS判断鼠标从哪个方向进入元素? « 张鑫旭-鑫空间-鑫生活 借助mediabunny纯JS实现视频水印、剪裁、合成等功能 « 张鑫旭-鑫空间-鑫生活 务必谨慎使用JS WeakRef弱引用 « 张鑫旭-鑫空间-鑫生活 CSS六边形头像的实现与蜂巢布局 « 张鑫旭-鑫空间-鑫生活 CSS corner-shape与背景底纹技术 « 张鑫旭-鑫空间-鑫生活 浅学WebTransport API:下一代Web双向通信技术 « 张鑫旭-鑫空间-鑫生活 HTML dialog元素新支持了closedBy属性 « 张鑫旭-鑫空间-鑫生活 HTML interestfor属性与悬停popover交互效果 « 张鑫旭-鑫空间-鑫生活 CSS3模拟window7炫酷界面效果展示 « 张鑫旭-鑫空间-鑫生活 图片旋转+剪裁js插件(兼容各浏览器) « 张鑫旭-鑫空间-鑫生活 纯js无图片无外链CSS图片幻灯片播放插件 « 张鑫旭-鑫空间-鑫生活 CSS border三角、圆角图形生成技术简介 « 张鑫旭-鑫空间-鑫生活 CSS “渐进增强”在web制作中常见应用举例 « 张鑫旭-鑫空间-鑫生活 让IE6/IE7/IE8浏览器支持CSS3属性 « 张鑫旭-鑫空间-鑫生活 jQuery – 高亮动态显示页面HTML代码插件 « 张鑫旭-鑫空间-鑫生活 翻译 – 逐渐消失的Flash网站 « 张鑫旭-鑫空间-鑫生活 CSS reset的重新审视 – 避免样式重置 « 张鑫旭-鑫空间-鑫生活 新浪微博插入话题后部分文字选中的js实现 « 张鑫旭-鑫空间-鑫生活 JavaScript实现http地址自动检测并添加URL链接 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变背景(gradient)效果 « 张鑫旭-鑫空间-鑫生活 CSS content内容生成技术以及应用 « 张鑫旭-鑫空间-鑫生活 CSS gradient渐变之webkit核心浏览器下的使用 « 张鑫旭-鑫空间-鑫生活 CSS渐变之CSS3 gradient在Firefox3.6下的使用 « 张鑫旭-鑫空间-鑫生活 区分IE8/IE7/IE6及其他浏览器-CSS “\9″hack « 张鑫旭-鑫空间-鑫生活 CSS实现跨浏览器兼容性的盒阴影效果 « 张鑫旭-鑫空间-鑫生活 CSS3&HTML5各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活
如何在CSS中实现父选择器效果? « 张鑫旭-鑫空间-鑫生活
张鑫旭,zhangxinxu · 2016-08-07 · via 张鑫旭-鑫空间-鑫生活

by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=5559
本文全文转载需购买版权(500¥),摘要引流则免费,具体参见这里

一、为何CSS不支持父选择器?

为何CSS不支持父选择器

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

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

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

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

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

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

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

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

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

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

您狠狠地点击这里:子元素focus,容器边框高亮demo

下图为默认态效果:
默认态

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

一般而言,输入框藏在姓名列表的后面,就像这样:
输入框位置

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

请问如何实现?

根据我的妄加推断,市面上,90%及其以上都是使用JS实现的,类似这样:

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

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

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

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

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

例如,下图这个效果就是纯CSS实现的,通用DOM结构设计和其他选择器实现的:
focus输入框,父级元素高亮

那具体原理是怎样的呢?

大致分为下面3步:

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

    其中,这里的z-index:1用来创建新的层叠上下文,这样子元素的z-index:-1不会超出容器,具体可参见“深入理解CSS中的层叠上下文和层叠顺序”一文。

  2. 新建一个元素负责容器的外观,放置在输入框的后面,使用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的盒尺寸计算,某些情况下,就可以使用绝对定位拉伸,别说我没告诉你哦!

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

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

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

更新于2022年7月21日

现在,在现代浏览器下,可以使用 :focus-within 伪类更方便的实现类似父选择器的效果,详见这篇文章:“详细了解CSS :focus-within伪类及其交互应用”。

类似的选择器还有 :target-within 伪类,不过兼容性还不是很好。

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

此处八卦知识采撷自知乎“CSS 中能否选取父元素?”这个问题一丝的回答。

总结一下就是2个槽点:

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

    • 2011年,语法是$E > F,例如:
      $input:focus > .container {}

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

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

      昙花一现。

    • 2014年,语法使用:has()伪类(Relational Pseudo-class),例如:
      .container:has(> input:focus) {}
  2. 最后一次的变身:has推迟到CSS5了。

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

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

所以大家还是醒醒,学学本文提供的实现思路吧!

醒醒

本文为原创文章,尊重辛勤劳动,可以免费摘要、推荐或聚合,但完整转载需付费购买版权,详见转载协议声明
本文地址:http://www.zhangxinxu.com/wordpress/?p=5559

(本篇完)