3D盒子阴影效果

16

我知道如何使用CSS3实现基本的盒子阴影,您可以在下面的图形顶部看到。

我想要实现的效果是一个三维盒子阴影,如下图底部所示。

有没有关于如何使用CSS3盒子阴影实现这个效果的想法?

3D box shadow effect


通常情况下,我看到这种效果是通过多个box-shadow创建的。 - Marcelo
你为什么只限制在盒子阴影上,而不使用已经引入的几个3D特定的CSS3属性呢? - Josh Burgess
1
@JoshBurgess,请给我讲解一下!只要它具有相同的浏览器兼容性,我全听你的! - Corey
1
嗯,有很多关于使用基于深度的CSS创建3D元素的例子。这是我在另一个问题上最近得到的答案 - https://dev59.com/Q4Xca4cB1Zd3GeqPF0by#27046256,这里还有一个关于Web上虚拟物体的绝佳资源:http://www.creativebloq.com/3d/how-create-impressive-3d-graphics-css3-21410672 - Josh Burgess
7个回答

23

不幸的是,盒子阴影实际上只是平面层。但是您可以应用多个盒子阴影来创建此效果。

.box-shadow-3d{
    box-shadow: 1px 1px 0px #999,
                2px 2px 0px #999,
                3px 3px 0px #999,
                4px 4px 0px #999,
                5px 5px 0px #999,
                6px 6px 0px #999;
}

21

你可以使用伪元素作为阴影

div {
  background: black;
  height: 100px;
  width: 100px;
  position: relative;
}
div:after,
div:before {
  content: '';
  background: grey;
  position: absolute;
}
div:after {
  width: 100%;
  height: 20px;
  left: 10px;
  bottom: 0;
  transform: translatey(100%) skewx(45deg);
}
div:before {
  width: 20px;
  height: 100%;
  right: 0;
  transform: translatex(100%) skewy(45deg);
  top: 10px;
}
<div></div>


9

这里是用 perspective 和伪元素:before实现的真正的3D阴影。

body {
  background: lightblue;
}
.foo {
  position: relative;
  display: inline-block;
  -webkit-perspective: 1000px;
  -moz-perspective: 1000px;
  persepctive: 1000px;
  margin: 20px;
  margin-top: 50px;
}
.foo .box {
  transform: rotateY(-40deg);
  height: 350px;
  width: 250px;
  background-color: black;
}
.foo:before {
  content: "";
  top: -15px;
  position: absolute;
  width: 50px;
  height: 375px;
  background-color: grey;
  transform: translateX(215px) translateY(2.7px) rotateY(55deg)
}
<div class="foo">
  <div class="box"></div>
</div>


4
您可以叠加多个盒子阴影的水平/垂直偏移量,每个阴影略微比前一个大。添加的阴影越多,效果就越明显。这里是一个示例fiddle
div {
    background: black;
    height: 100px;
    width: 100px;
    box-shadow:  0 01px gray,
                 01px 0 gray,
                 01px 02px gray,
                 02px 01px gray,
                 02px 03px gray,
                 03px 02px gray,
                 03px 04px gray,
                 04px 03px gray,
                 04px 05px gray,
                 05px 04px gray,
                 05px 06px gray,
                 06px 05px gray;
}

我本来会选择这个答案,但不确定为什么这里有交替的阴影?它给人一种锯齿状的感觉。不像@BurpmanJunior的答案那样平滑和直接。 - Corey
1
当您想要为每个侧面应用不同的颜色阴影时,此方法比BurpmanJunior的答案更有用:例如,将lightgray应用于右侧和darkgray应用于下方。 - Aaron Gillion

1

以下是一段小型的实现,受到 @Vitorino Fernandes 的启发,使用 Stylus 实现...

offset = 10
border = 3
.offsetbox
   margin offset
   padding offset
   text-align center
   box-shadow inset 0 0 0 unit(border,px) black
   background white
   display inline-block
   position relative
   &:after,
   &:before
      content ''
      background black
      position absolute
   &:after
      width 100%
      height offset
      transform translatey(100%) skewx(-45deg)
      right (offset/2)
      bottom 0
   &:before
      height 100%
      width offset
      transform: translatex(-100%) skewy(-45deg)
      left 0
      top (offset/2)

enter image description here


嗨,你能给右上角和左下角添加一个80像素的边框半径吗?阴影也应该遵循左下角的半径。我在做这个的时候也遇到了困难,谢谢你的代码。 - rj.learn

1
我在这两个选项中遇到了一些问题,所以我从Lea Verou的优秀书籍CSS Secrets中改编了一些对角渐变。我考虑通过border-image创建一个右边和底部边框内的渐变,但是该属性不允许像border-right-image等一样的边缘定位。因此,我决定使用带有两个截断角的伪元素,这似乎效果很好。您必须小心调整渐变的宽度为填充的一半大小的1.414倍,因为这将是正方形的对角线(二的平方根)。另外,由于那是一个伪元素,请注意正确的放置位置。很想听听你们的想法。

div {
  background: #bbb;
  padding: 1em 1.2em;
  width: 50%;
  margin: 0 auto;
  color: #111;
  font: 150%/1.2 Georgia, Palatino, Times, serif;
  position: relative;
}

div:after {
  content:" ";
  position:absolute;
  top:0;
  left: 0;
  width:100%;
  height:100%;
  padding: 1.42em; /* (square root of gradient position) */
  background: #000; /* Fallback if not supported */
  background: linear-gradient(-135deg, transparent 2em, #000 0) top right,
    linear-gradient(#000, #000) padding-box bottom right,
    linear-gradient(45deg, transparent 2em, #000 0) bottom left; 
    /*I have avoided adding -webkit-, -moz and -0 prefixs for linear-gradient.  You may put them in later to be extra safe*/
    background-size: 50% 50%; /* There is no reason to paint the upper left quadrant, so I didn't. */
    background-repeat: no-repeat;
    -webkit-box-sizing: content-box;  -moz-box-sizing: content-box;  box-sizing: content-box; 
    /*  Many people use border-box as default these days. Unfortunately, the box cannot be sized using border-box settings with the combination of padding in ems and percentages.  So this is reset to content-box, just in case.   */
    z-index: -1; /* To keep the shadow behind the div*/
<div>This is a short sentence to demonstrate that our little div is responsive.</div>


0
我在@Vittorino fernandes的代码中添加了一些剪贴路径,以避免伪元素之间的空白,并使其更加锐利。 我添加了一些1像素的调整,以避免SVG渲染问题。
您可以使用名为 shadow-dimension 的变量来设置阴影的宽度和高度。
我将它放在了CodePen上: https://codepen.io/silviamalavasi/pen/XWqeWEq
:root {
    --shadow-dimension: 20px;
    --blue: #0039a6;
}
.box-container {
    position: relative;
 }
.box-container>div {
    border: 2px solid var(--blue);
}
.box-container>div:after, .box-container>div:before {
    content: '';
    background-color: var(--blue);
    position: absolute;
}
.box-container>div:before {
    width: calc(var(--shadow-dimension) + 1px);
    height: calc(100% +  100px + 1px);
    left: calc(var(--shadow-dimension) * -1);
    transform: skewy(-45deg);
    top: calc(0.5*var(--shadow-dimension));
    clip-path: polygon(0% 0%, 100% 0%, 100% calc(100% - 100px - 2px + var(--shadow-dimension)), 0% calc(100% - 100px - 2px));
}
.box-container>div:after {
    width: calc(100% + 100px);
    height: calc(var(--shadow-dimension) + 1px);
    left: calc(-0.5*var(--shadow-dimension) - 100px);
    bottom: 1px;
    transform: translateY(100%) skewx(-45deg);
    clip-path: polygon(100px 0%, 100% 0%, 100% 100%, calc(100px + 2px) 100%);
}

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