CSS3 中的层叠上下文初探
2015/10/09 · CSS ·
层叠上下文
原文出处: HaoyCn
前言:关于层叠上下文,笔者还没有去阅读更详细的 W3C
规范来了解更本质的原理(表打我,等我校招拿到 offer 了我就读好伐
T_T)。一直听说 CSS3
里的层叠上下文有新情况,但没找到很好的参考资料,故自己实战一把。鉴于笔者水平有限,如有任何遗漏或者错误,则恳请读者斧正。
深入CSS属性(九):z-index,深入css属性z-index
如果你不是一名csser新手,想必你对z-index的用法应该有个大致的了解了吧,z-index可以控制定位元素在垂直于显示屏方向(Z
轴)上的堆叠顺序,本文不去讲述基本的API如何使用,而是去更深入的了解z-index是如何工作的,使用z-index的时候有哪些问题,以及z-index在日常开发中的使用。
下面我们通过一个例子来引入今天的正文,代码示例:
<style type="text/css">
.red, .green, .blue {
position: absolute;
width: 100px;
height: 100px;
text-align: center;
line-height: 100px;
color: #fff;
}
.red {
background-color: red;
z-index: 1;
}
.green {
background-color: green;
top: 70px;
left: 70px;
}
.blue {
background-color: blue;
top: 140px;
left: 140px;
}
</style>
<div>
Red box
</div>
<div>
Green box
</div>
<div>
Blue box
</div>
如下图:
上述代码通俗易懂,下面有个问题请大家思考:
在遵循下述规则的情况下,如何使用红色span元素在green和blue元素后面?
1) 不能以任何方式更改html标记;
2) 不能增加或改变任何元素的z-index属性;
3) 不恩增加或改变任何元素的position属性;
请大家思考,这个问题改如何解决?说明其原因?
1 CSS2.1 中规定的层叠上下文
Background and borders — of the element forming the stacking
context. The lowest level in the stack.Negative Z-Index — the stacking contexts of descendants elements
with negative z-index.Block Level Boxes — in-flow non-inline-level non-positioned
descendants.Floated Boxes — non-positioned floats
Inline Boxes — in-flow inline-level non-positioned descendants.
Z-index: 0 — positioned elements. These form new stacking
contexts.Positive Z-index — positioned elements. The highest level in the
stack.图文来源:http://webdesign.tutsplus.com/articles/what-you-may-not-know-about-the-z-index-property–webdesign-16892
现在该笔者上场翻译了!在解释上面术语之前,需要阐明两个术语:“定位”指的是 position
为 relative
、absolute
、fixed
的元素,“非定位”则相反。
- 背景和边框:建立层叠上下文元素的背景和边框。层叠中的最低级
- 负 Z-index:
z-index
为负的后代元素建立的层叠上下文 - 块级盒:文档流内非行内级非定位后代元素
- 浮动盒:非定位浮动元素(笔者注:即排除了
position: relative
的浮动盒) - 行内盒:文档流内行内级非定位后代元素
- Z-index:
0:定位元素。这些元素建立了新层叠上下文(笔者注:不一定,详见后文) - 正 Z-index:(
z-index
为正的)定位元素。层叠的最高等级
引文如上所表。但笔者提醒各位读者一点,“Z-index:
0”级的定位元素不一定就会建立新的层叠上下文。因为:
CSS2.1:(z-index: auto)The stack level of the generated box in the
current stacking context is 0. The box does not establish a new
stacking context unless it is the root element.
当定位元素 z-index: auto
,生成盒在当前层叠上下文中的层级为
0。但该盒不建立新的层叠上下文,除非是根元素。
规范是这样,但 IE6-7 有个
BUG,定位元素即便 z-index: auto
照样创建层叠上下文。
以上是基于 CSS2.1 的层叠上下文介绍。下面要阐述的是在 CSS3
新环境下,层叠上下文的新变化。
———————————– 分割线
2 CSS3 带来的变化
总的来说变化可以归为两点,我们之后一一探讨:
- CSS3 中许多属性会创建局部层叠上下文
tranform
属性改变绝对定位子元素的包含块
一、z-index 黄金法则及stack context
1) 一个box和它的父亲有相同的堆叠级别(stack
level),除非该box被通过z-index属性赋予了不同的stack level;
2)
z-index属性只适应于position属性为relative、absolute、fixed的元素对象;
3)
给一个被定位(positioned)元素设置小于1的opacity属性值,意味着创建了一个堆叠上下文(stack
context),就像给该元素增加了一个z-index值;
4) 对于一个被positioned box,如果指定了z-index属性,意味着:
->该box的stack level 在当前的stack context中;
->该box建立了个本地stack context;
5)
如果box没有指定z-index,元素将被按下面的顺序堆叠(stacked)(从后到前):
-> 正常流中的boxes,根据在源代码中的序列;
-> 浮动boxes;
-> computed后display属性值为inline/inline-block/inline-table的boxes;
-> positioned boxes 和boxes
设置opacity值小于1,根据在源代码中的序列;
因此,当我们给一个positioned元素设置了z-index时,我们做了两件事:
1) 该元素与在它前面或者后面的元素共享着相同的stack
context,这也就是我们改变z-index的值,元素会移动其他元素前后者后的原因。
2) 为该元素内的任何元素创建了一个新的stack
context,一旦你创建了一个stack context,内部的任何有(stack
context)的任何层都会停留在这个stack context。
通过上述的黄金法则,也许你已经知道上面那个问题的答案了。在黄金法则里,我们提到了个新名词“stack
context”,下面我们通过一个实例来介绍它:
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>z-index example</title>
</head>
<body>
<h1>Header</h1>
<p>I am paragraph. <em> I am em</em></p>
</body>
</html>
一个很特殊的情况是,在一个document中,没有任何定位,document有且只有一个堆叠环境
-
通过HTML创建。 下面我们给上例添加如下样式:
h1, p { position: relative; } h1 { z-index: 2; } p { z-index: 1; }
在这种情况下,h1,p都创建了一个stack context,这两个stack
context都在document的stack
context内。增加样式后h1在p元素之上。如果我们给em元素增加如下样式结果又会怎样:
h1, p, em {
position: relative;
}
h1 {
z-index: 2;
background-color: #f0f;
}
p {
z-index: 1;
background-color: #00f;
line-height: 40px;
}
em {
z-index: 1;
background-color: #f00;
}
增加此样式后em创建了stack
context,由于em的z-index属性,它的内部的text比p标签中的其它text更接近用户。因为它是在p的stack
context内部,它是一直比h1中的text低的。
注意:如果你增加z-index的值,是不能使用em位于h1之上的。如果你想一个context的元素位于另一个context中的元素之上,你必须提升整个context或者设置它们为相同的context。
下面是两种解决方案: 方案一:
h1, p, em {
position: relative;
}
h1 {
z-index: 2;
background-color: #f0f;
}
p {
/* raise the entire context,p and em 都在h1 之上了*/
z-index: 3;
background-color: #00f;
line-height: 40px;
margin-top: -40px;
}
em {
z-index: 1;
background-color: #f00;
}
方案二:
h1, p, em {
position: relative;
}
h1 {
z-index: 2;
background-color: #f0f;
}
p {
background-color: #00f;
line-height: 40px;
margin-top: -40px;
}
em {
/* put them into the same context */
z-index: 2;
background-color: #f00;
}
2.1 产生新层叠上下文的情况
以下情况会产生新的层叠上下文:
- 根元素(HTML)
- 绝对或相对定位且
z-index
值不为auto
- 一个伸缩项目
Flex Item
,且z-index
值不为auto
,即父元素display: flex|inline-flex
- 元素的
opacity
属性值小于 1 - 元素的
transform
属性值不为none
- 元素的
mix-blend-mode
属性值不为normal
- 元素的
filter
属性值不为normal
- 元素的
isolation
属性值为isolate
position: fixed
will-change
中指定了上述任意属性,即便你没有直接定义这些属性- 元素的
-webkit-overflow-scrolling
属性值为touch
以上列表译自:
,提醒广大读者,别看中文版,因为中文版并非实时跟进更新的,且翻译不太准确
二、创建stack context及注意事项
那么创建stack context的方式有哪些?
1) When an element is the root element of a document (theelement)
2) When an element has a position value other than static and a z-index
value other than auto
3) When an element has an opacity value less than 1
Update: In addition to opacity, several newer CSS properties also create
stacking contexts. These include: transforms, filters, css-regions,
paged media, and possibly others. As a general rule, it seems that if a
CSS property requires rendering in an offscreen context, it must create
a new stacking context.
In WebKit, styling a box with position:fixed or
-webkit-overflow-scrolling:touch implicitly creates a stacking context,
just like adding a z-index value.
Also, be aware of these CSS3 “triggers”:
transform != none
transform-style: preserve-3d
filter != none clip-path, mask
Lastly, even though a relatively positioned element without a z-index
set does not establish a stacking context… A common IE bug, often seen
in drop-down menus, is that any relatively positioned element that has
haslayout set to true establishes a stacking context. One may visualize
this bug by setting [A] and [B] to position:relative, while [a]
gets position:relative; z-index:1. Now, dragging [A] under [B] hides
[a] – in Internet Explorer, that is. Any positioned child with a
z-index is caught by this wrong stacking context of its parent.
2.2 提升层叠上下文中的层级
以上元素建立新层叠上下文的同时,也会提升元素自身所在层叠上下文中的层级。
我们以 opacity
为例。来看下 CSS3 规范中的话:
If an element with opacity less than 1 is not positioned,
implementations must paint the layer it creates, within its parent
stacking context, at the same stacking order that would be used if it
were a positioned element with ‘z-index: 0’ and ‘opacity: 1’. If an
element with opacity less than 1 is positioned, the ‘z-index’ property
applies as described in [CSS21], except that ‘auto’ is treated as
‘0’ since a new stacking context is always created.
如果元素 opacity
小于 1
且未定位,则必须在其父层叠上下文中,按其在定位了的、z-index: 0
且 opacity: 1
的情况中的层叠顺序绘制。如果 opacity
小于
1 且已定位,z-index
属性按 CSS2.1
应用,但 auto
要视为 0
,因为新的层叠上下文总是创建了的。
如下案例:
CSS
div { width: 100px; height: 100px; } #box1 { position: absolute;
background: red; top: 40px; left: 40px; } #box2 { background: blue; }
<body> <div id=”box1″></div> <div
id=”box2″></div> <body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
div {
width: 100px;
height: 100px;
}
#box1 {
position: absolute;
background: red;
top: 40px;
left: 40px;
}
#box2 {
background: blue;
}
<body>
<div id="box1"></div>
<div id="box2"></div>
<body>
|
以上 CSS 和 HTML 片段中,由于 box1 是绝对定位(层级为“Z-index:
0”级),而 box2 是文档流内块级盒(层级为“块级盒”级),因此 box1 会层叠在
box2 之上。下面添加如下 CSS 规则:
CSS
#box2 { opacity: .5; }
1
2
3
|
#box2 {
opacity: .5;
}
|
这时候, box2 则会层叠在 box1 之上了。因为 box2 的 opacity
为
0.5(小于 1),故视其为“Z-index: 0”级,也就和 box1
同级了。同级情况下,按照二者在源代码中的顺序,居后的 box2
又重新占领高地了。
读者可以取下面规则之任意一条实验,都能达到同样效果:
CSS
#box2 { transform: scale(1); mix-blend-mode: difference; isolation:
isolate; -webkit-filter: blur(5px); }
1
2
3
4
5
6
|
#box2 {
transform: scale(1);
mix-blend-mode: difference;
isolation: isolate;
-webkit-filter: blur(5px);
}
|
三、z-index在某些浏览器中的问题
1) IE6中的
select元素是一个窗口控件,所以它总是出现在层叠顺序的顶部而不会顾及到自然层叠顺序、position属性或者是z-index。可以在div元素上添加一个iframe设置为position:absolute,并设置div的z-index比iframe的高。
2) 因父容器(元素)被定位的缘故,IE6/7会错误的对其stacking
context进行重置。
3) 在Firefox2版本中,一个负的z-index值会使元素位于stacking
context的后面,而不是位于公认的背景和边框这样的元素stacking
context之前。 本文到此结束,最后附上本文开始时提出的问题的答案:
/* add this */
div:first-child {
opacity: .99;
}
感谢您的阅读,文中不妥之处,还望批评指正。
2.3 transform 改变绝对定位子元素包含块
transform
除了建立新的局部层叠上下文外,还会干一件事:改变绝对定位子元素的包含块。须注意的是,固定定位也是绝对定位的一种。
什么是包含块?有时候一些盒子根据矩形盒计算自身定位和大小,此矩形盒即包含块。更多详情请阅读视觉格式化模型详述。
固定定位元素
固定定位元素的包含块由视口创建(如果读者了解视觉格式化模型详述的信息,也就知道这一点:在计算其“静态位置”的时候,则以初始化包含块作为其计算包含块)。现在我们看以下源代码:
CSS
div { width: 100px; height: 100px; } #fixed { position: fixed; width:
100%; height: 100%; top: 0; left: 0; background: blue; } #transform {
background: red; padding: 20px; } <body> <div
id=”transform”> <div id=”fixed”></div> </div>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
div {
width: 100px;
height: 100px;
}
#fixed {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: blue;
}
#transform {
background: red;
padding: 20px;
}
<body>
<div id="transform">
<div id="fixed"></div>
</div>
</body>
|
这个时候,以视口为包含块进行定位和大小计算, fixed 将会铺满整个屏幕。
但现在,我们加上如下规则:
CSS
#transform { transform: scale(1); }
1
2
3
|
#transform {
transform: scale(1);
}
|
此时,fixed 的包含块不再是视口,而是 transform
的内边距盒的边缘盒了。故此时 fixed 的宽高均为 140px。
绝对定位元素
我们举一个例子:
CSS
#relative { position: relative; width: 100px; height: 100px;
background: green; } #absolute { position: absolute; width: 100%;
height: 100%; top: 0; left: 0; background: blue; } #transform {
background: red; width: 50px; height: 50px; } <div id=”relative”>
<div id=”transform”> <div id=”absolute”></div>
</div> </div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#relative {
position: relative;
width: 100px;
height: 100px;
background: green;
}
#absolute {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: blue;
}
#transform {
background: red;
width: 50px;
height: 50px;
}
<div id="relative">
<div id="transform">
<div id="absolute"></div>
</div>
</div>
|
此时 absolute 的包含块为 relative 的内边距盒的边缘盒。由此 absolute
的宽高均为 100px。然后我们添加如下规则:
CSS
#transform { transform: scale(1); }
1
2
3
|
#transform {
transform: scale(1);
}
|
由于 transform 创建了局部层叠上下文,absolute 的包含块不再是 relative
而是 transform 了,根据这一新的包含块,得新宽和高为 50px。
1 赞 1 收藏
评论
四、参考链接:
Find out how elements stack and start using low z-index values
The Z-Index CSS Property: A Comprehensive Look
Elaborate description of Stacking Contexts
Overlapping And ZIndex
CSS/Properties/z-index
Understanding CSS z-index(MDN)
What No One Told You About Z-Index
测试Demo:
原载于: Benjamin
本文链接:
如需转载请以链接形式注明原载或原文地址。
CSS中z-index属性具体是什?
层相对于屏幕纵深方向的顺序。你用几个层叠在一起就可看出它的含义。
如以下是相关测试代码
<永利开户送38元体验金,!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“www.w3.org/…al.dtd”>
<html xmlns=”www.w3.org/1999/xhtml”>
<head>
<title>无标题页</title>
</head>
<body>
<div style=”position:relative; width:150px; height:100px; z-index:2;
background-color:Red;”></div>
<div style=”position:relative; width:150px; height:100px; z-index:1;
top:-20px; background-color:Blue;”></div>
</body>
</html>
说明:
第一个DIV模块中,我们定义了宽度为150,高度为100,背景色为红色,z-index:2
inherit;此DIV的级别为2
第二个DIV模块中,我们定义了宽度亦为150,高度为100,背景色为蓝色,z-index:1
inherit;此DIV级别为1,top:-20px垂直向上-20象素.
2>1
上面的DIV模块级别高于下面的DIV模版级别.所以,我们在position:relative;中可以体会到是上一层遮住了下一层.并且遮住了我们设定的20象素的区域.
CSS样式中z-index属性
定义和用法z-index
属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。注释:元素可拥有负的
z-index 属性值。注释:Z-index 仅能在定位元素上奏效(例如
position:absolute;)!
如果你不是一名csser新手,想必你对z-index的用法应该有个大致的了解了吧,z-index可以控制定位元…