通过设置transform(rotate),z-index被取消。

115

使用 transform 属性可以取消 z-index,并使之在前方显示。(当注释掉 -webkit-transform 时,下面的代码中 z-index 可以正常工作)

.test {
  width: 150px;
  height: 40px;
  margin: 30px;
  line-height: 40px;
  position: relative;
  background: white;
  -webkit-transform: rotate(10deg);
}

.test:after {
  width: 100px;
  height: 35px;
  content: "";
  position: absolute;
  top: 0;
  right: 2px;
  -webkit-box-shadow: 0 5px 5px #999;
  /* Safari and Chrome */
  -webkit-transform: rotate(3deg);
  /* Safari and Chrome */
  transform: rotate(3deg);
  z-index: -1;
}
<html>

<head>
  <title>transform</title>
  <link rel="stylesheet" type="text/css" href="transformtest.css">
</head>

<body>
  <div class="test">z-index is canceled.</div>
</body>

</html>

如何让transform和z-index共同起作用?


这是我制作的fiddle,你想用z-index隐藏文本吗? - Surjith S M
工作正常 http://jsfiddle.net/raunakkathuria/8MQkP/ 实际上有什么疑问吗? - Raunak Kathuria
感谢您制作Fiddle。我想展示文本矩形后面的阴影(就像便笺一样)。 - kbth
7个回答

177

让我们看看发生了什么。首先注意,对于定位元素,z-index 和单独使用的 transform 会在元素上创建新的"堆叠上下文"。以下是正在发生的事情:

您的 .test 元素设置了与 none 不同的 transform,这使它拥有自己的堆叠上下文。

然后添加一个伪元素 .test:after,它是 .test 的子级。这个子元素有 z-index: -1,设置了 .test:after 在 ".test 的堆叠上下文中" 的堆叠级别。在 .test:after 上设置 z-index: -1 并不会将其放在 .test 后面,因为 z-index 只在给定堆叠上下文内有意义。

当您从 .test 中删除 -webkit-transform 时,它将删除其堆叠上下文,导致 .test.test:after 共享堆叠上下文(即 <html>),使 .test:after 出现在 .test 后面。请注意,删除 .test-webkit-transform 规则后,您可以再次通过在 .test 上设置新的 z-index 规则(任何值)(因为它是定位的),为其提供自己的堆叠上下文!

那么我们如何解决您的问题呢?

要让 z-index 按照您的期望工作,请确保 .test.test:after 共享相同的堆叠上下文。问题在于您希望对 .test 进行旋转转换,但这意味着创建它自己的堆叠上下文。幸运的是,将 .test 放入包裹容器中并旋转该容器仍然可以让其子元素共享堆叠上下文,并同时进行旋转。

  • 以下是您开始使用的内容:http://jsfiddle.net/fH64Q/

  • 以下是解决了堆叠上下文问题并保持旋转的一种方法(请注意,由于 .test 具有白色背景,因此阴影被裁剪了一点):

.wrapper {
    -webkit-transform: rotate(10deg);
}
.test {
       width: 150px;
       height: 40px;
       margin: 30px;
       line-height: 40px;
       position: relative;
       background: white;
}
.test:after {
       width: 100px;
       height: 35px;
       content: "";
       position: absolute;
       top: 0;
       right: 2px;
       -webkit-box-shadow: 0 5px 5px #999; /* Safari and Chrome */
       -webkit-transform: rotate(3deg); /* Safari and Chrome */
       transform: rotate(3deg);
       z-index: -1;
}
<div class="wrapper">
    <div class="test">z-index is canceled.</div>
</div>

有其他更好的方法来实现这个效果,甚至更好的方式。我可能会将“便利贴”背景设置为容器元素,然后在其中放置文本,这可能是最简单的方法,并且会减少您所拥有的复杂性。

请查看本文以获取有关z-index和堆叠顺序的更多详细信息,或者查看工作中的W3C CSS3规范关于堆叠上下文的部分


8
这是对CSS布局中最复杂的方面之一的很好解释。以后阅读时,可以查看W3规范 - AndyBean
太棒了,讲解得非常好。我正在父元素上使用 transform,并且想知道为什么我的 ::before 元素没有堆叠在父元素后面。 - OGreeni
我正在伪元素中使用它,但无法使其保持其“z-index”值。 - SalahAdDin

29

将需要保持在顶部的div设置为position:relative


2
它对我起作用了。它是否与上面提到的堆栈上下文有关?如果有人能帮忙澄清,将不胜感激。 - glihm
也许与相对(或绝对)定位和设置z-index时有关,会创建一个新的堆叠上下文? - nCardot
谢谢!在尝试为未选择相同类的元素设置CSS后,它非常有效! - zqlimy

11

我曾经遇到一个类似的问题,在使用transform: translate()后,无法使用z-index

最简单的解决方案是在所有兄弟元素上设置position: relative,然后z-index就可以正常工作了。


我猜这会为每个兄弟元素创建一个新的堆叠上下文,因此 z-index 只能在父级内起作用,但不能重叠父级的兄弟元素,对吗?至少这是我正在努力实现的。 - tgikf

6

快速解决方案:您可以将另一个元素旋转0度。


这对我在无法旋转容器的情况下起作用。 - Daniel Flippance
1
我遇到了一个奇怪的问题,z-index没有被观察到,然后应用样式transform:rotate(0.0rad)解决了它。我无法通过CSS规则应用它,它必须直接应用于元素上。这毫无意义,但感谢您发布了让我尝试的答案。 - Andrew Shepherd

5
对于那些仍在寻找解决方案的人,我发现了这篇文章,介绍了如何解决transformz-index问题,链接在这里
简单的使用方法是这样的:
.parent { transform-style: preserve-3d; }
.parent:before { transform: translateZ(-1em); }

1
我遇到了类似的问题。 我的解决方法是,在文本周围添加一个包装器div,并将transform属性应用于包装器div。
.wrapper{
    transform: rotate(10deg);
}

这里有一个 jsfiddle 的链接 http://jsfiddle.net/KmnF2/16/


-4

将您想要保持在顶部的 div 设置为 position:absolute


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接