包含阴影和变换的堆栈不正确

时间:2015-07-24 10:38:18

标签: css css3 css-shapes css-transforms box-shadow

我创建了一个形状,表示一个阴影朝向底部变大的页面。



body {
  background: #dddddd;
}
div {
  background: white;
  margin: 40px auto;
  height: 300px;
  width: 300px;
  position: relative;
  padding: 10px;
}
div:before,
div:after {
  height: 96%;
  z-index: -10;
  position: absolute;
  content: "";
  left: 8px;
  top: 2%;
  width: 30%;
  max-width: 300px;
  background: transparent;
  box-shadow: -10px 0px 10px rgba(0, 0, 0, 0.5);
  transform: rotate(1.5deg);
}
div:after {
  transform: rotate(-1.5deg);
  right: 8px;
  left: auto;
  box-shadow: 10px 0px 10px rgba(0, 0, 0, 0.5);
}

<div></div>
&#13;
&#13;
&#13;

我需要将其旋转,但是当我尝试添加transform: rotate(10deg)时,box-shadow错觉会被破坏并进入父图层。

&#13;
&#13;
body {
  background: #dddddd;
}
div {
  background: white;
  margin: 40px auto;
  height: 300px;
  width: 300px;
  position: relative;
  padding: 10px;
  transform: rotate(10deg);
}
div:before,
div:after {
  height: 96%;
  z-index: -10;
  position: absolute;
  content: "";
  left: 8px;
  top: 2%;
  width: 30%;
  max-width: 300px;
  background: transparent;
  box-shadow: -10px 0px 10px rgba(0, 0, 0, 0.5);
  transform: rotate(1.5deg);
}
div:after {
  transform: rotate(-1.5deg);
  right: 8px;
  left: auto;
  box-shadow: 10px 0px 10px rgba(0, 0, 0, 0.5);
}
&#13;
<div></div>
&#13;
&#13;
&#13;

我发现了这个问题:Which CSS properties create a stacking context?但似乎并没有为我的要求提出解决方案。

在我的案例中是否会有任何好的解决方案。我不介意它们是SVGfiltercanvas还是其他任何东西,只要它得到相当好的支持。

3 个答案:

答案 0 :(得分:4)

如果您使用其他div,则会修复您遇到的问题,以便背景颜色位于内部div上,旋转位于外部div

否则,您可能需要使用其他方法来获得相同的结果。

&#13;
&#13;
body {
  background: #dddddd;
}
.two{
background: white;
height: 300px;
width: 300px;
padding: 10px;
}
div.one {
  margin: 40px auto;
  height: 300px;
  width: 300px;
  position: relative;
  
  transform: rotate(10deg);
}
div.one:before,
div.one:after {
  height: 96%;
  z-index: -10;
  position: absolute;
  content: "";
  left: 8px;
  top: 2%;
  width: 30%;
  max-width: 300px;
  background: transparent;
  box-shadow: -10px 0px 10px rgba(0, 0, 0, 0.5);
  transform: rotate(1.5deg);
}
div.one:after {
  transform: rotate(-1.5deg);
  right: 8px;
  left: auto;
  box-shadow: 10px 0px 10px rgba(0, 0, 0, 0.5);
}
&#13;
<div class="one">
<div class="two">
</div>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:3)

  

注意:此答案未介绍如何修复方法中出现的堆叠上下文问题。这只是提供了几种可用于实现类似效果的替代方法。这些方法的优势应该在IE10 +中工作,不需要任何额外的元素

     

如果IE支持不是强制性的,我仍会推荐vals的答案。

方法1:透视变换

这几乎与您使用的相似,只是它使用一个旋转透视的伪元素来产生阴影。由于只使用了一个伪元素,另一个伪可用于在阴影上方添加白色前景。

body {
  background: #dddddd;
}
div {
  position: relative;
  height: 300px;
  width: 300px;
  padding: 10px;
  margin: 40px auto;
  transform: rotate(10deg);
}
div:before,
div:after {
  position: absolute;
  content: '';
  top: 0px;
}
div:before {
  height: 100%;
  width: 100%;
  left: 0px;
  background: white;
}
div:after {
  height: 98%;
  width: 97%;
  left: 1.5%;
  transform-origin: bottom;
  transform: perspective(125px) rotateX(1deg);
  box-shadow: 10px 0px 10px rgba(0, 0, 0, .5), -10px 0px 10px rgba(0, 0, 0, .5);
  z-index: -1;
}
<div></div>

方法2:线性渐变

我们可以使用linear-gradient背景图像并适当地定位它们以产生类似于盒阴影产生的效果。但正如您在输出中看到的那样,它与阴影不完全匹配,因为模糊区域不一样。

在这里,我们使用以下内容:

  • 一个小角度线性渐变图像(to top left),用于在盒子左侧产生阴影。
  • 另一个小角度线性渐变图像(to top right),用于在盒子的右侧产生阴影。
  • 白色区域的大线性渐变图像(几乎是纯色)。这里使用渐变而不是纯色,因为可以控制渐变图像的大小。

body {
  background: #dddddd;
}
div {
  margin: 40px auto;
  height: 300px;
  width: 300px;
  transform: rotate(10deg);
  backface-visibility: hidden;
  background: linear-gradient(to right, transparent 0.1%, white 0.1%), linear-gradient(to top left, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .3) 5%, transparent 50%), linear-gradient(to top right, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .3) 5%, transparent 50%);
  background-size: 280px 100%, 10px 97%, 10px 97%;
  background-position: 10px 0px, left top, right top;
  background-repeat: no-repeat;
  background-origin: border-box;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div></div>

渐变的底部仍然无法获得box-shadow输出中看到的模糊。如果需要,可以通过添加更多渐变来在某种程度上实现这一点,如下面的代码段所示。

body {
  background: #dddddd;
}
div {
  margin: 40px auto;
  height: 300px;
  width: 300px;
  transform: rotate(10deg);
  backface-visibility: hidden;
  background: linear-gradient(to right, transparent 0.1%, white 0.1%), linear-gradient(to top left, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .3) 5%, transparent 50%), linear-gradient(to top right, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .3) 5%, transparent 50%), linear-gradient(to bottom left, rgba(0, 0, 0, 0), rgba(0, 0, 0, .3) 5%, transparent 60%), linear-gradient(to bottom right, rgba(0, 0, 0, 0), rgba(0, 0, 0, .3) 5%, transparent 70%);
  background-size: 280px 100%, 10px 97%, 10px 97%, 10px 2.5%, 10px 2.5%;
  background-position: 10px 0px, left top, right top, left 99.25%, right 99.25%;
  background-repeat: no-repeat;
  background-origin: border-box;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div></div>

答案 2 :(得分:1)

当你进入变形世界时,变形本身将解决他们创造的一些问题。 您可以使用3d等效的z-index,Z坐标

来解决这个问题

不幸的是,这在IE中不起作用(我相信它们支持保存3d)

body {
  background: #dddddd;
}
div {
  background: white;
  margin: 40px auto;
  height: 300px;
  width: 300px;
  position: relative;
  padding: 10px;
  transform: translateZ(1px) rotate(10deg);
  transform-style: preserve-3d;
}
div:before,
div:after {
  height: 96%;
  z-index: -10;
  position: absolute;
  content: "";
  left: 8px;
  top: 2%;
  width: 30%;
  max-width: 300px;
  background: transparent;
  box-shadow: -10px 0px 10px rgba(0, 0, 0, 0.5);
  transform: translateZ(-1px) rotate(1.5deg);
}
div:after {
  transform: translateZ(-1px) rotate(-1.5deg);
  right: 8px;
  left: auto;
  box-shadow: 10px 0px 10px rgba(0, 0, 0, 0.5);
}
<div></div>