最近要实现一个类似下面的层叠的效果,需要带一个hover
缓动效果。
第一反应就是直接使用:before
&:after
伪元素,配合绝对定位加z-index
轻松实现,实际操作发现并不是这么一回事。
代码如下
.box{
width:100px;
height:100px;
position:relative;
z-index:2;
box-shadow:0 3px 5px #eee;
background-color:#fff;
}
.box:before{
content:"";
position:absolute;
top:5px;
left:5px;
right:5px;
bottom:-5px;
box-shadow:0 3px 5px #eee;
background-color:#fff;
z-index:1;
}
但是得到的确实下面的效果
也就是:before
跑到上面来了,检查.box
也有postion
属性赋值,当时就有点懵逼了。因为和层叠有关,所以就翻了一些和z-index
相关的资料,也就是层叠顺序,网上相关资料很多,本文主要说说伪元素的层叠上下文。
解决方案
.box{
width:100px;
height:100px;
position:relative;
top:0;
box-shadow:0 3px 5px #eee;
background-color:#fff;
transiton:.5s;
}
.box:before{
content:"";
position:absolute;
top:5px;
left:5px;
right:5px;
bottom:-5px;
box-shadow:0 3px 5px #eee;
background-color:#fff;
z-index:-1;
}
.box:hover{
top:-5px;
}
父元素不设置z-index
值,伪元素设置负z-index
值,父元素位移效果不使用transform
,简单说下原因。
- 同一个层叠上下文里面, 层叠顺序从后向前依次是: 背景和边框、负z-index、块级盒、浮动盒、行内盒、z-index:0、正z-index.
- 伪元素相当于子元素,也就是包含在元素内的,二者不在同一个层叠上下文中。
如果想实现层叠效果,需要元素和对应的伪元素在同一层叠上下文中,所以不能让元素创建层叠上下文。以下情况会创建层叠上下文
- 即便是
position
不为static
的元素, 如果没有指定一个非auto
值的z-index
, 该元素就不会建立一个层叠上下文。 - 元素的
transform
值不是none
。
当然还有其他情况本文就不列出了,因为transform
会创建层叠上下文,所以缓动的时候只能使用top 进行变换了。
这里有点的是,top
bottom
等属性如果没有设置初始值transition
是不会生效的,所以代码中设置了初始值top:0
。