先看这样一个需求
页面如图:
div A是一个悬浮磁条,固定宽度居中。有个子元素A-child右浮动。浏览器向下滚动时实现下图效果:
B挡住A,A-child挡住B。
dom结构:
正常的实现方式很容易:因为B本身就在A的后面,当A和B都设置了position属性(非static),且没有设置z-index的时候,其层叠关系是后面的元素覆盖前面的元素,这样只需要给A-child设置z-index属性值即可。less代码:
#wrap{ position: relative; width: 1200px; margin: 0 auto; height: 100%; text-align: center; color:#000000; font-size:50px; #a{ position: fixed; top: 50px; width: 950px; height: 100px; background-color: red; padding: 20px; #a-1{ position:relative; font-size:30px; float:right; width:100px; height:100px; background-color: #cc0000; z-index: 1; } } #b{ position:absolute; left: 0px; top:550px; background-color: #0000f6; width: 990px; height: 100%; } } |
出现的问题
除chrome浏览器以外,IE8+和其它浏览器效果正常(当然IE6,7也有问题)。chrome下如图:
A-child无法覆盖B元素。
原因
后来发现是chrome22+以后的一个改动,参考链接:The stacking
context
关键内容:
这段话主要说明在什么情况会创建层叠上下文(The stacking context)。
红线部分说的就是移动端webkit的浏览器和chrome22+的浏览器,position:fixed的时候也会创建一个层叠上下文。这里面层叠上下文的概念很重要,z-index的相关内容很多,如果对z-index的使用不清楚,可先参考这篇文章:CSS
z-index 属性的使用方法,z-index详细内容可参考如下系列文章:Understanding CSS
z-index。
chrome的这个改变就会造成A元素形成一个新的层叠上下文,并且当成一个整体在父层叠上下文中进行比较,A-child因为设置了z-index属性,所以也会创建一个层叠上下文,但是它的父层叠上下文变成了A,所以它只能在A的内部进行层叠比较。这也就是很多文章中所说的“从父原则”。其它的浏览器,position:fixed不会创建层叠上下文,因此整个页面只有root和A-child两个层叠上下文,所有层叠元素都在root层叠上下文中进行比较。
chrome浏览器这种变动的原因
我的理解就是为了在移动端浏览器滚动时达到性能最优化,使得页面有更强大的响应性。我想其性能提升可能体现在页面滚动渲染的时候,position:fixed的元素当成一个整体的层叠上下文进行比较,而不需要考虑其内部子元素和整个页面其它部分的层叠关系,但是我并未感觉这会带来多大的提升……。而PC端之所以改变是为了不和移动端相悖而产生两个版本。
参考资料:Stacking Changes Coming to position:fixed elements
解决方案
想过一些解决方案,比如只fixed定位A-child元素,但是在响应式的时候对于始终右浮动的定位计算很麻烦,且需要resize事件不断计算。
最终灵机一动想到一个办法:很简单,当滚动到蓝色区域时,设置A元素的z-index,让它覆盖B元素,同时把A元素的高度设为0,只让A-child显示出来;也可以设置A的visiblity:hidden,A-child的visiblity:visible(opacity代替visible不可以)。less代码:
#wrap{
position: relative;
width: 1200px;
margin: 0 auto;
height: 100%;
text-align: center;
color:#000000;
font-size:50px;
#a{
position: fixed;
top: 50px;
width: 950px;
//height: 100px;
height:0;
background-color: red;
//padding: 20px;
z-index:1;
#a-1{
position:relative;
font-size:30px;
float:right;
width:100px;
height:100px;
background-color: #cc0000;
//z-index: 1;
}
}
#b{
position:absolute;
left: 0px;
top:550px;
background-color: #0000f6;
width: 990px;
height: 100%;
}
} |
总结
chrome浏览器和移动端基于webkit的浏览器,position:fixed会创建新的层叠上下我,注意对样式的影响。
关于z-index几点常见问题
1、z-index只有在设置了position为relative,absolute,fixed时才会有效。
2、z-index的“从父原则”。当你发现把z-index设的多大都没用时,看看其父元素是否设置了有效的z-index,当然别忘了先看看自身是否设置了position。
3、不要乱用z-index,否则层叠关系会把你搞晕,且难以维护。只在必要的情况下设置,目前我想到的必要的时候只有:悬浮层、负margin产生的覆盖情况。
position:fixed
发现position:fixed不设置left,top的时候,其默认值并非0,0。而是根据其父元素边界确定的,请自行测试,还未具体查看资料。
opacity和visiblity
设置父元素透明,再设置子元素不透明将失效。设置父元素不可见,再设置子元素可见,可以成功。 |