::在子边框后面的伪元素之前

Que*_*lef 1 html css border css3

我有一个h1标签,我正在尝试添加一个很酷的动画,边框将从左上角和右下角"增长".

我被我的包裹这样h1两个divS,每个div::before::after伪元素.

当根div被碾过时,这些div的伪元素将"收缩",露出下面的边界.

问题是,::before我的根div 的伪元素在边框后面,因此鼠标悬停时立即显示边框.设置z-index的的::beforeS和::after小号解决它; 但是,我不想这样做 - 这是我正在复制/粘贴的代码片段.没有z-index设置,所以我很困惑为什么会发生这种情况.

在此之前,div除了动画需要的东西之外,我没有其他功能,并且它工作得很好 - 但是它与它有什么关系呢?

这似乎是问题:::在伪元素堆叠顺序问题之前.

但是,没有建议如何解决它的答案.当然,我可以添加第三个div,但我想保留它作为最后的手段.

小问题:https://jsfiddle.net/zppqgn6s/

看到它固定z-index; 看看它应该是什么样子,取消注释第34行.

Har*_*rry 7

伪元素边界低于子元素的原因:

回答关于为什么伪元素的(:before)背景落后于child(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 */
Run Code Online (Sandbox Code Playgroud)

现在基于视觉渲染层的规范,下面是发生的事情:

#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) */
Run Code Online (Sandbox Code Playgroud)

可以看出,基于图层编号(在内联注释中提供),h1元素位于上方#anim:before(但在产生边框收缩效果的所有其他三个元素之下).

解决方案:

解决这个问题的唯一方法是让child(h1)在:before元素后面绘制.这可以通过执行以下任一操作来实现(但它们都需要z-index设置):

  • 设置h1position: relativez-index: -1(,以使其背后#anim:before)
  • 设置z-index: 1(或以上)#anim:before元素(使其高于h1)

替代解决方案/方法:

实际上,您不需要此特定动画的所有额外元素(边界从左上角和右下角聚合以相互会合).它们可以使用单个h1元素本身来实现,我发布这个答案来说明其中的两个方法.虽然你没有要求其他方法,但我喜欢这种效果,它似乎是发布这个答案的好地方.

通过使用 linear-gradient 背景图像:

在这种方法中,我们为边框的每一边创建一个渐变(实际上只是一个纯色,因为它不会改变颜色),适当地定位它们然后将尺寸从转换0%100%.对于顶部和底部边框,在X轴的尺寸应该从改变0%100%hover而左右边框,Y轴的尺寸应该从改变0%100%.

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 */
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


通过使用伪元素:

这也可以通过使用伪元素转换它们的高度和宽度来完成hover.你已经在这里的正确课程,但不需要额外的元素.

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 */
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

即使div添加了额外的元素,这两种方法都可以工作(从片段中可以看出).