10 月 23 - 25 日,QCon 上海站即将召开,现在大会已开始正式报名,可以享受 8 折优惠 了解详情
写点什么

CSS 层叠上下文和层叠顺序原理分析及实战

作者:王丹丹

  • 2020-06-28
  • 本文字数:4082 字

    阅读完需:约 13 分钟

CSS层叠上下文和层叠顺序原理分析及实战

1. 问题现象

最近在做一个网站的首页,首页的右上角有一个绝对定位的大动画,同时首页还有三个小动画,小动画部分的效果是:鼠标滑入特定区域(如下图),展示动画。


由于 UI 提供的动画画布很大,所以遮盖住了下图所示特定区域的 div 元素;最外层 div 元素,包括三个部分:头部标题、设置了透明度的文本以及一段文本。


在 div 元素上设置 onmouse 事件后,诡异的事情发生了:只有鼠标滑入设置透明度的文本时,小动画才出现,滑入其他部分,小动画不出现。


这是为什么?



探究原因,是因为大动画部分设置了绝对定位以及 z-index,形成了层叠上下文,层叠水平高于普通元素,遮盖了 div 中的部分元素。


要解决上述问题,咱们需要先翻开书本,从层叠上下文和层叠顺序说起。

2. 层叠相关概念和原理

2.1 层叠上下文

它是一个三维的概念,在 CSS2.1 规范中,每个盒模型都可看做一个三维空间,分别为平铺在画布上的 X 轴、Y 轴以及表示层叠的 Z 轴。一般情况下,元素在页面上沿 X 轴 Y 轴平铺,用户察觉不到它们在 Z 轴上的层叠关系。而一旦元素发生堆叠,这时就能发现某个元素可能覆盖了另一个元素或者被另一个元素覆盖。


如果一个元素含有层叠上下文,那么这个元素则为层叠上下文元素。我们可以理解为这个元素比普通元素在 Z 轴上距离用户更近一些。


层叠上下文规则:


  • 层叠上下文的层叠水平比普通元素要高;

  • 层叠上下文可以嵌套,内部层叠上下文及其子元素的层叠水平受制于外部的层叠上下文;

  • 层叠上下文和其兄弟元素相互独立,即在不同的层叠上下文中,元素的层叠顺序没有可比性;

  • 不同的层叠上下文元素发生层叠的时候,元素的层叠水平由父级层叠上下文的层叠顺序决定;

2.2 层叠等级

在同一个层叠上下文中,它描述定义的是该层叠上下文中的层叠上下文元素在 Z 轴上的上下顺序。


当然,在普通元素中,也可以有层叠顺序,这时它描述定义的是这些普通元素在 Z 轴上的上下顺序。z-index 属性可以影响层叠水平,注意是“影响”,不是“决定”。

2.3 层叠顺序

以上的层叠上下文和层叠等级是概念,层叠顺序是指元素遵循的规则。在同一个层叠上下文中,其中的元素遵循下图的规则:



其中,border/background 为装饰属性,float 浮动盒子和 block 块状元素一般用作布局,inline/inline-block 内联元素包含的是网页内容。在网页中内容最重要,所以 inline/inline-block 的层叠等级顺序更高。


通过实例验证上述规则,结论如下:


1)负 index 的层叠等级大于层叠上下文、小于 block 块级水平盒子


可参考下文中"一些新的 css 属性会形成层叠上下文"中的第一个例子;


2)float 浮动盒子的层叠等级大于 block 水平盒子



<div style="background: green;width: 100px;height: 100px;float: left"></div><div style="margin-left: -30px;width: 400px;height: 50px;background: red">111111111111</div>
复制代码


3)inline/inline-block 水平盒子的层叠等级大于 float 浮动盒子



<div style="background: green;width: 100px;height: 100px;float: left"></div><span style="margin-left: -30px;background: red">111111111111</span>
复制代码


4)不依赖于 z-index 的层叠上下文的层叠等级大于行内元素的层叠等级(注:此处由于 opacity 属性,形成层叠上下文)



<span style="background: green;display:inline-block;width: 100px;height: 100px;opacity:0.8;vertical-align: middle;"></span> <span style="margin-left:-30px; background:red;vertical-align: middle;">111111111111</span> 
复制代码


5)正 index 的层叠等级大于不依赖于 z-index 的层叠上下文的层叠等级



<span style="background: green;display:inline-block;width: 100px;height: 100px;opacity:0.8;vertical-align: middle;"></span> <span style="margin-left:-30px; background:red;vertical-align: middle;position: relative;z-index: 4">111111111111</span>
复制代码

2.4 层叠准则

  • 在同一个层叠上下文中,如果元素具有明显的层叠水平标识时(如 z-index),层叠水平高的元素在上面,距离用户“最近”;

  • 当两个元素的层叠水平一致、层叠顺序相同时,DOM 流后面的元素会覆盖前面的元素

2.5 层叠上下文的形成

1)页面根元素,本身就具有层叠上下文,称为根层叠上下文


2)定位元素的 z-index 为数值时会形成层叠上下文


  • z-index:auto 时



<span style="background: green;display:inline-block;width: 100px;height: 100px;opacity:0.8;vertical-align: middle;"></span> <span style="margin-left:-30px; background:red;vertical-align: middle;position: relative;z-index: 4">111111111111</span>
复制代码


z-index:auto 时未形成层叠上下文,绿色长方形的 z-index 较大,所以绿色长方形遮盖了红色长方形;


  • z-index 的值为数值时



<div style="position: relative;z-index: 2;">    <div style="background-color: red;width: 100px;height: 200px;position: absolute;z-index: 1">
</div></div><div style="position: relative;z-index: 1;"> <div style="background-color: green;width: 200px;height: 100px;position: absolute;z-index: 2">
</div></div>
复制代码


z-index 的值为数值,形成了层叠上下文,绿色和红色长方形的父元素的层叠等级相比,红色长方形父元素的层叠等级更高,所以红色长方形遮盖了绿色长方形。


以上印证了:不同的层叠上下文元素发生层叠时,元素的层叠水平由父级层叠上下文的层叠顺序决定,同时也印证了 z-index 属性可以影响层叠水平,只是影响,不能决定。


3)一些新的 css 属性会形成层叠上下文


  • 元素为 flex 项,z-index 为数值


z-index 为数值的 flex 项,要满足两个条件,父级元素为 flex 或 inline-flex 布局,子元素的 z-index 为数组,方可形成层叠上下文。


情况 1:当父级元素不为 flex 或 inline-flex 布局时



<div>    <div style="background-color: red;width: 100px;height: 200px;z-index: 1">        <div style="background-color: green;width: 200px;height: 100px;position: relative;z-index: -1">        </div>    </div></div>
复制代码


在同一个层叠上下文中,负 index 的层叠顺序小于 block 块级元素,所以,红色长方形覆盖在绿色长方形的上面;


情况 2:当父级元素为 flex 或 inline-flex 布局时



<div style="display: flex;">    <div style="background-color: red;width: 100px;height: 200px;z-index: 1">        <div style="background-color: green;width: 200px;height: 100px;position: relative;z-index: -1">        </div>    </div></div>
复制代码


当最外层父级 div 元素 display:flex 时,第二层 div 元素 z-index:1(数值),则第二层 div 元素为层叠上下文,由下图的层叠顺序规则可知,负 index 的层叠顺序大于层叠上下文,所以绿色长方形覆盖在红色长方形的上面。



  • opacity


当 opacity 值不为 1 时,可形成层叠上下文


情况 1:当外层 div 元素未加透明度 opacity 时



<div style="background-color: red;width: 100px;height: 200px">    <div style="background-color: green;width: 200px;height: 100px;position: relative;z-index: -1">    </div></div>
复制代码


在同一个层叠上下文中,负 index 的层叠顺序小于 block 块级元素,所以,红色长方形覆盖在绿色长方形的上面;


情况 2:当外层 div 元素加了透明度 opacity 时



<div style="background-color: red;width: 100px;height: 200px;opacity: 0.5">    <div style="background-color: green;width: 200px;height: 100px;position: relative;z-index: -1">    </div></div>
复制代码


当最外层父级 div 元素 opacity:0.5 时,子元素的 z-index:-1,由层叠顺序规则可知,负 index 的层叠顺序大于层叠上下文,所以绿色长方形覆盖在红色长方形的上面;


  • 其他属性


transform 不是 none、mix-blend-mode 不是 normal、filter 不是 none、isolation:isolate 和-webkit-overflow-scrolling:touch,都可形成层叠上下文,此时与 opacity 值不为 1 的情况相同。

3. 解决办法

针对文章开篇提到的问题,有三种解决方案:


方案一:给外层 div 元素设置 position:relative,使 div 元素和绝对定位大动画的层叠水平相等


元素一旦成为定位元素,其 z-index 就会自动生效,且默认值为 auto,也就是 0 级别。由于绝对定位的大动画的 z-index 为 0,也就意味着层叠上下文的大动画元素和 div 定位元素是一个层叠顺序的。


于是当他们发生层叠时,遵循层叠准则第二条,div 元素可正常响应鼠标划入事件。


方案二:通过设置外层 div 元素 position:relative,z-index 为非 auto,形成层叠上下文


当 z-index 的值大于等于绝对定位的大动画的 z-index 值时,当他们发生层叠时,遵循层叠准则第一条,div 元素可正常响应鼠标划入事件。


方案三:通过设置父元素 display: flex|inline-flex,子元素作为 flex 项,z-index 值是不为 auto 的数值时,子元素可形成层叠上下文


可给外层 div 元素设置 diaplay:flex 属性,内层元素设置 z-index 不为 auto,则内层元素为层叠上下文元素,遵循层叠准则第二条,div 元素可正常响应鼠标划入事件。


以上方案是基于绝对定位大动画的 z-index 为 0 时。若绝对定位大动画的 z-index 值大于 0 时,方案一就不生效了,方案二和方案三的 z-index 需大于等于大动画的 z-index 值。

4. 总结

一旦普通元素具有了层叠上下文,其层叠顺序就会变高。它的层叠顺序依赖以下两个原则:


  • 如果层叠上下文元素不依赖 z-index 数值,则其层叠顺序 z-index:auto 可看成 z-index:0 级别;

  • 如果层叠上下文元素依赖 z-index 数值,则其层叠顺序由 z-index 值决定


当遇到页面中有元素发生重叠,或者元素不能正常响应鼠标等事件时,可检查下该元素以及其父元素和兄弟元素所在的层叠上下文。遵循文中所说的规则,设置对应的 css 属性,改变元素层叠顺序,即可解决相应的问题。


本文转载自公众号贝壳产品技术(ID:beikeTC)。


原文链接


https://mp.weixin.qq.com/s?__biz=MzIyMTg0OTExOQ==&mid=2247485712&idx=2&sn=d788cf74f5d806636d54b6fd30b6025f&chksm=e8373a60df40b3763973faddf3d4db114591a07b3c4158ee1f939aefcab057e5afb939ada720&scene=27#wechat_redirect


2020-06-28 14:073062

评论

发布
暂无评论
发现更多内容

AI-Compass GraphRAG技术生态:集成微软GraphRAG、蚂蚁KAG等主流框架,融合知识图谱与大语言模型实现智能检索生成

汀丶人工智能

​​从数据到决策:低代码+AI如何简化并加速可视化工作流?

不在线第一只蜗牛

看板管理解析,给生产一点小小震撼!

积木链小链

数字化 智能制造 生产管理 生产看板

WebGL开发3D展览馆

北京木奇移动技术有限公司

软件外包公司 webgl开发 webgl外包

误操作后快速恢复数据 binlog 解析为反向 SQL

GreatSQL

AI-Compass Embedding模型模块:15+主流向量化技术的多模态语义表示生态

汀丶人工智能

以故事+动画,让PID知识通俗易懂部分二

芯动大师

类似腾讯会议的私有化音视频会议软件,BeeWorks Meet

BeeWorks

即时通讯 IM 私有化部署

StarRocks × MinIO:打造灵活高效的存算分离方案

StarRocks

Docker 存算分离 StarRocks minlo quickstart

Parrot和DJI系列无人机操作系统内核崩溃漏洞利用分析

qife122

漏洞利用 无人机安全

等保测评对互联网企业的重要作用和影响

等保测评

半夜服务器告警不再错过!运维人员必备的语音通知方案

外滩运维专家

电话报警 电话推送 电话接口 监控电话 语音监控

【跨国数仓迁移最佳实践2】MaxCompute SQL执行引擎对复杂类型处理全面重构,保障客户从BigQuery平滑迁移

阿里云大数据AI技术

人工智能 大数据 数据处理 数据迁移

WebGL开发数字孪生项目

北京木奇移动技术有限公司

软件外包公司 webgl开发 webgl外包

AI-Compass前沿速览:ChatGPT Agent、Kimi2、Mistral语音模型、Grok AI情感陪伴、百度Tizzy、有言数字人

汀丶人工智能

人工智能 大模型

AI-Compass NLP2SQL模块:集成Chat2DB、DB-GPT、MindsDB等核心工具,实现自然语言到SQL转换的智能化数据查询生态系统

汀丶人工智能

AI-Compass LLM合集-多模态模块:30+前沿大模型技术生态,涵盖GPT-4V、Gemini Vision等国际领先与通义千问VL等国产优秀模型

汀丶人工智能

阿里巴巴为什么禁止超过3张表join?

量贩潮汐·WholesaleTide

前端

MIAOYUN | 每周AI新鲜事儿(07.11-07.18)

MIAOYUN

云计算 AI AI 大模型 AI Agent,

漏洞赏金猎手入门指南:从零开始赚取高额奖金的核心方法论

qife122

渗透测试 漏洞挖掘

大数据-47 Redis 内存控制、Key 过期与数据淘汰策略详解

武子康

Java redis 大数据 分布式 后端

破局传统采购!采购文件编制审核系统为烟草行业数智化加速

中烟创新

AI-Compass LLM训练框架生态:整合ms-swift、Unsloth、Megatron-LM等核心框架

汀丶人工智能

AI-Compass RLHF人类反馈强化学习技术栈:集成TRL、OpenRLHF、veRL等框架,涵盖PPO、DPO算法实现大模型人类价值对齐

汀丶人工智能

淘宝商品图片搜索API响应数据解析

tbapi

淘宝API接口 天猫API接口 淘宝图片搜索接口 淘宝拍立淘接口 天猫拍立淘接口

黑龙江地区等保测评中常用的安全产品

等保测评

AI-Compass(AI百科全书开源):构建最全面的AI学习与实践生态,服务AI全群体

汀丶人工智能

人工智能 大模型

以故事+动画方式,让PID知识通俗易懂部分一

芯动大师

AI-Compass DeepSearch深度搜索生态:集成阿里ZeroSearch、字节DeerFlow、MindSearch等前沿平台,实现超越传统关键词匹配的智能信息检索革命

汀丶人工智能

暑热能耗管理成难题?这套智慧方案高效破局!

极客天地

除了企微钉钉,有什么企业 IM 性价比高一点的吗?

BeeWorks

即时通讯 IM 私有化部署

CSS层叠上下文和层叠顺序原理分析及实战_大前端_InfoQ精选文章