CSS3 "Lifted Corners"倾斜阴影带有不透明度

12

我一直在尝试一些CSS3阴影效果。我很喜欢“突起角落”的效果,但是当我尝试为元素添加透明度时遇到了问题。我的问题是:有没有办法在具有透明度的元素上创建“突起角落”效果?

http://jsfiddle.net/WAvZu/

.drop-shadow{
    position:relative;
    float:left;
    width:40%;
    padding:1em;
    margin:2em 10px 4em;
    background:#fff;
    -webkit-box-shadow:0 1px 4px rgba(0, 0, 0, 0.3), 0 0 40px rgba(0, 0, 0, 0.1) inset;
    -moz-box-shadow:0 1px 4px rgba(0, 0, 0, 0.3), 0 0 40px rgba(0, 0, 0, 0.1) inset;
    box-shadow:0 1px 4px rgba(0, 0, 0, 0.3), 0 0 40px rgba(0, 0, 0, 0.1) inset;
}
.drop-shadow:before,
.drop-shadow:after{
    content:"";
    position:absolute;
    z-index:-2;
}
.lifted{
    -moz-border-radius:4px;
    border-radius:4px;
}
.lifted:before,
.lifted:after{
    bottom:15px;
    left:10px;
    width:50%;
    height:20%;
    max-width:300px;
    max-height:100px;
    -webkit-box-shadow:0 15px 10px rgba(0, 0, 0, 0.7);
    -moz-box-shadow:0 15px 10px rgba(0, 0, 0, 0.7);
    box-shadow:0 15px 10px rgba(0, 0, 0, 0.7);
    -webkit-transform:rotate(-3deg);
    -moz-transform:rotate(-3deg);
    -ms-transform:rotate(-3deg);
    -o-transform:rotate(-3deg);
    transform:rotate(-3deg);
}
.lifted:after{
    right:10px;
    left:auto;
    -webkit-transform:rotate(3deg);
    -moz-transform:rotate(3deg);
    -ms-transform:rotate(3deg);
    -o-transform:rotate(3deg);
    transform:rotate(3deg);
}

我也想知道答案,但恐怕这是不可能用CSS来实现的。 - Damien Legros
@LinusCaldwell 我认为这不是一个 bug,背景失去了不透明度,所以你看到了它下面的阴影。 - Damien Legros
阴影没有被渲染在顶部。但是一旦你设置了某种透明度,阴影就会透过按钮闪耀出来,因为阴影的颜色比按钮本身更容易看到。当然,当你将不透明度降低时,阴影的颜色也会减弱,但仍然比按钮更容易看到。改变你的颜色方案,你可能能够得到一个更好的解决方案。这里没有错误。 - Sven Bieder
问题可以更精细地表述为“为什么不透明度小于1会导致:before和:after忽略z-index?”这里有一个非常简单的例子。只需将opacity设置为1,就可以看到效果... - Linus Caldwell
1
@SvenBieder, :-) 就我所知并不存在这种情况。请参见此更新,其中甚至没有使用:after。将 opacity 设置为 <1, 黑色的div就到了前面(它不是通过红色的部分略微可见,而是完全在顶部,在Firebug中进行了测试)。也许我只是不明白你的意思。 - Linus Caldwell
显示剩余7条评论
3个回答

9
问题在于理解堆叠上下文及其在浏览器中的呈现方式。
  • 根元素(HTML)
  • 使用z-index值进行定位(绝对或相对定位),
  • 透明度小于1的元素。
  • 在移动端WebKit和Chrome 22+上,即使z-index为“auto”,position:fixed始终创建新的堆叠上下文

9.9.1指定堆叠级别:“z-index”属性

  1. 形成堆叠上下文的元素的背景和边框。
  2. 具有负堆叠级别的子堆叠上下文(最负优先)。
  3. 非行内级、非定位后代的流动内容。
  4. 非定位浮动内容。
  5. 行内级、非定位后代的流动内容,包括行内表格和行内块级元素。
  6. 堆叠级别为0的子堆叠上下文和堆叠级别为0的定位后代。
  7. 具有正堆叠级别的子堆叠上下文(最正优先)。

首先渲染的是 #test 的背景,因为透明度应用于该元素。接着,阴影放在顶部,因为它们处于新的堆叠上下文中(position: absolute)。最后是 div 的文本内容。

一个简单的解决方案:将该 div 包装在另一个 div 中,将透明度应用于 那个 div 而不是 #test

http://jsfiddle.net/WAvZu/3/

另一篇不错的文章:关于Z-Index,没有人告诉你的事情


4
在讨论后,老实说我对此不太确定,但我找到了这篇文章:层叠上下文
据我所知,你的示例中使用 z-index: -2 的技巧之所以有效,仅因为你没有在 .drop-shadow 上设置 z-index,这意味着它没有层叠上下文。通常情况下,子元素(:before:after 也是一种子元素)的 z-index 不能低于其父元素,但如果父元素没有层叠上下文,则可以在其下方。 opacity 的问题在于它形成层叠上下文:

任何文档中的元素都可以形成层叠上下文,只要满足以下条件之一:

  • 根元素(HTML),
  • 定位(绝对或相对)并具有 z-index 值而非 "auto",
  • 不透明度小于 1 的元素(...),
  • ...
话虽如此,你可以通过使用包装器来解决问题
<div class="wrapper">
    <div class="drop-shadow lifted">This is correct with opacity.</div>
</div>

并在那里设置不透明度

.wrapper {
    opacity: .5;
}

不错的发现。这个 jsfiddle 更好地展示了这一点。测试1是两个独立元素,它们定位相同,透明度均为.9,而测试2元素则清晰地显示了渲染差异。测试3元素像测试2一样嵌套,但透明度为1 - ScottS

1
我能够通过在容器内添加一个带有“拐角”的div来假装解决这个问题。这是一种hack方法,我想其他人可能会想出更好的解决方案,但我认为我应该发布我的发现以防有人感兴趣。

http://jsfiddle.net/WAvZu/2/


嘿,只是好奇。你从哪里得到那个背景的? url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9z…0aD0iOTkiIGhlaWdodD0iMjUiIGZpbGw9IiNjZWU2OWIiPjwvcmVjdD4KPC9nPgo8L3N2Zz4="); ? - Chris Bier
@ChrisB 这是一个在CodePen上的SVG游乐场。http://codepen.io/progers/pen/IvHfd - Joe

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