我有一个h1
代码,我试图为其添加一个很酷的动画,边框会在那里生长。从左上角和右下角开始。
我通过将h1
封装在两个div
中来实现此目的,并且每个div
都有一个::before
和::after
伪元素
当根div
被鼠标悬停时,这些div的伪元素将缩小',显示下面的边框。
问题是,我的根div的::before
伪元素在边框后面是,因此鼠标悬停时会立即显示边框。设置z-index
和::before
的::after
将修复它;但是,我不想这样做 - 这是我正在复制/粘贴的代码片段。没有设置z-index
,所以我很困惑为什么会发生这种情况。
之前,除了动画所需的内容之外,我没有div
,并且它运行良好 - 但是它会如何与它有关?
这似乎是个问题:::before pseudo-element stacking order issue。
但是,没有建议如何解决它的答案。当然,我可以添加第三个div,但我希望将其作为最后的手段。
小问题:https://jsfiddle.net/zppqgn6s/
要使用z-index
修复此问题;看看它应该是什么样子,取消注释第34行。
答案 0 :(得分:7)
伪元素边框低于儿童的原因:
回答关于为什么伪元素(:before
)背景落后于孩子(h1
)的原始问题可以在BoltClock的答案中找到(你是在问题中有联系)。 :before
伪元素实际上是在根div
(包括h1
)的内容之前插入的。
以下是演示中使用的元素的一般结构:
#anim /* This is the first element inside root and is positioned (relative) */
#anim:before /* This is positioned absolutely with respect to the parent */
div /* This element is positioned relatively */
div:before /* This element is positioned absolutely with respect to the div */
h1 /* This element doesn't have any positioning */
div:after /* This element is positioned absolutely with respect to the div */
#anim:after /* This is positioned absolutely with respect to the parent */
现在based on the specs for the visual rendering layers,以下是发生的事情:
#anim /* Parent element and its background, border gets painted first (Layer 0) */
#anim:before /* Positioned descendant, creates stacking context nested within parent (Layer 0.1)*/
div /* Positioned descendant of #anim, second child in flow (Layer 0.2) */
div:before /* Positioned descendant of div, first child in flow (Layer 0.2.2) */
h1 /* Non positioned, as per Point 3 gets positioned lowest (Layer 0.2.1) */
div:after /* Positioned descendant of div, second such child in flow (Layer 0.2.3) */
#anim:after /* Positioned descendant of #anim, third child in flow (Layer 0.3) */
根据图层编号(内联注释中提供)可以看出,h1
元素位于#anim:before
之上(但低于产生边框收缩效果的所有其他三个元素)。< / p>
<强>解决方案:强>
唯一的解决方案是让孩子(h1
)在:before
元素之后绘制。这可以通过执行以下任一操作来实现(但它们都需要设置z-index
):
h1
设置为position: relative
z-index: -1
(使其落后#anim:before
)z-index: 1
(或以上)设置为#anim:before
元素(以使其超越h1
)替代解决方案/方法:
实际上,你并不需要这个特定动画的所有额外元素(边界从左上角和右下角汇聚以相互碰到)。它们可以使用单个h1
元素本身来实现,我发布这个答案来说明其中的两个方法。虽然你没有要求其他方法,但我喜欢这种效果,它似乎是发布这个答案的好地方。
使用 linear-gradient
背景图片:
在这种方法中,我们为边框的每一边创建一个渐变(实际上只有一个纯色,因为它不会改变颜色),适当地定位它们,然后将大小从0%
转换为100%
。对于顶部和底部边框,X轴的大小应在0%
上从100%
更改为hover
,而对于左右边框,Y轴的大小应更改为{ {1}}至0%
。
100%
&#13;
h1 {
position: relative;
display: inline-block;
padding: 4px;
background: linear-gradient(to right, #000, #000), linear-gradient(to right, #000, #000), linear-gradient(to bottom, #000, #000), linear-gradient(to bottom, #000, #000);
background-position: 0% 0%, 100% 100%, 0% 0%, 100% 100%;
background-size: 0% 2px, 0% 2px, 2px 0%, 2px 0%; /* 2px is border thickness */
background-repeat: no-repeat;
transition: all 1s;
}
h1:hover {
background-size: 100% 2px, 100% 2px, 2px 100%, 2px 100%; /* 2px is border thickness */
}
&#13;
使用伪元素:
这也可以通过在<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<h1>Hover me</h1>
<br>
<h1>How about me?<br>I have dynamic height!</h1>
<div id="wrap">
<h1>Look at me, I am responsive!!!</h1>
</div>
上转换它们的高度和宽度来使用伪元素来完成。你已经在这里的正确课程,但不需要额外的元素。
hover
&#13;
h1 {
position: relative;
display: inline-block;
padding: 4px;
}
h1:after,
h1:before {
position: absolute;
content: '';
height: 0%;
width: 0%;
transition: width 1s, height 1s, border .01s 1s; /* border has a delay because it should become invisible only after height and width become 0 */
}
h1:before {
left: 0;
top: 0;
border-top: 2px solid transparent;
border-left: 2px solid transparent;
}
h1:hover:before {
border-top: 2px solid black;
border-left: 2px solid black;
}
h1:after {
bottom: 0;
right: 0;
border-right: 2px solid transparent;
border-bottom: 2px solid transparent;
}
h1:hover:after {
border-right: 2px solid black;
border-bottom: 2px solid black;
}
h1:hover:before,
h1:hover:after {
height: calc(100% - 2px);
width: calc(100% - 2px);
transition: width 1s, height 1s, border .01s; /* border has a shorter duration because it immediately needs to change colors */
}
&#13;
即使添加了额外的<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<h1>Hover me</h1>
<br>
<h1>How about me?<br>I have dynamic height!</h1>
<div id="wrap">
<h1>Look at me, I am responsive!!!</h1>
</div>
元素,这两种方法也都有效(从片段中可以看出)。