框阴影和变换的堆栈不正确
Incorrect stack with box-shadow and transform
我创建了一个形状,代表一个页面,其阴影向底部逐渐变大。
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>
我需要旋转它,但是当我尝试添加 transform: rotate(10deg)
时,box-shadow
错觉被破坏并位于父层之上。
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);
}
<div></div>
我发现了这个问题:Which CSS properties create a stacking context? 但似乎没有针对我的要求的建议解决方案。
是否有任何好的解决方案适用于我的情况。我不介意它们是 SVG
、filter
、canvas
还是其他任何东西,只要它得到合理的支持即可。
如果您使用另一个 div
它可以解决您遇到的问题,因此背景颜色位于内部 div
并且旋转位于外部 div
。
否则您可能需要使用其他方法才能获得相同的结果。
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);
}
<div class="one">
<div class="two">
</div>
</div>
Note: This answer does not describe how to fix the stacking context problem that is seen in your approach. This just provides a couple of alternate approaches that could be used to achieve a similar effect. Advantage of these approaches is that they should work in IE10+ and does not require any extra elements.
I would still recommend vals' answer if IE support is not mandatory.
方法一:透视变换
这与您使用的几乎相似,不同之处在于它使用一个随透视旋转的伪元素来产生阴影。由于只使用了一个伪元素,因此可以使用另一个伪元素在阴影上方添加白色前景。
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>
方法二:线性渐变
我们可以使用 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>
当您进入变换世界时,变换本身将解决它们所产生的一些问题。
您可以使用 z-index 的 3d 等价物 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>
我创建了一个形状,代表一个页面,其阴影向底部逐渐变大。
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>
我需要旋转它,但是当我尝试添加 transform: rotate(10deg)
时,box-shadow
错觉被破坏并位于父层之上。
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);
}
<div></div>
我发现了这个问题:Which CSS properties create a stacking context? 但似乎没有针对我的要求的建议解决方案。
是否有任何好的解决方案适用于我的情况。我不介意它们是 SVG
、filter
、canvas
还是其他任何东西,只要它得到合理的支持即可。
如果您使用另一个 div
它可以解决您遇到的问题,因此背景颜色位于内部 div
并且旋转位于外部 div
。
否则您可能需要使用其他方法才能获得相同的结果。
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);
}
<div class="one">
<div class="two">
</div>
</div>
Note: This answer does not describe how to fix the stacking context problem that is seen in your approach. This just provides a couple of alternate approaches that could be used to achieve a similar effect. Advantage of these approaches is that they should work in IE10+ and does not require any extra elements.
I would still recommend vals' answer if IE support is not mandatory.
方法一:透视变换
这与您使用的几乎相似,不同之处在于它使用一个随透视旋转的伪元素来产生阴影。由于只使用了一个伪元素,因此可以使用另一个伪元素在阴影上方添加白色前景。
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>
方法二:线性渐变
我们可以使用 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>
当您进入变换世界时,变换本身将解决它们所产生的一些问题。 您可以使用 z-index 的 3d 等价物 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>