Skip to content

box-shadow

box-shadow 的绘制原理

vue
<template>
  <div class="h-100 box-shadow"></div>
</template>
<style lang="scss" scoped>
.box-shadow {
  margin: 40px;
  box-shadow: 2px 3px 4px rgba(0, 0, 0, 0.5);
}
</style>
  1. 以该元素相同的尺寸和位置,画一个 rgba(0,0,0, .5)的矩形。
  2. 把它向右移 2px,向下移 3px。
  3. 使用高斯模糊算法(或类似算法)将它进行 4px 的模糊处理。这在本质上表示在阴影边缘发生阴影色和纯透明色之间的颜色过渡长度近似于模糊半径的两倍(比如在这里是 8px)。
  4. 接下来,模糊后的矩形与原始元素的交集部分会被切除掉,因此它看起来像是在该元素的“后面”。这跟大多数开发者所理解的情况(元素叠在模糊后矩形的上层)可能稍有不同。不过,在某些场景下,意识到没有任何投影绘制在元素的下层十分重要。举例来说,如果给元素设置一层半透明的背景,我们就看不到它下层有任何投影。这一点跟 text-shadow 不同,因为文字下层的投影不会被裁切。

在元素的框架上添加阴影效果,同一个元素上设置多个阴影效果,并用逗号将他们分隔开。

css
box-shadow: [inset] x y blur spread color, ...;

单侧投影

最终的解决方案来自 box-shadow 鲜为人知的第四个长度参数。这个参数会根据你指定的值去扩大或(当指定负值时)缩小投影的尺寸。

vue
<template>
  <div class="h-100 box-shadow"></div>
</template>

<style lang="scss" scoped>
.box-shadow {
  margin: 40px;
  background-color: #8d6e16;
  box-shadow: 0px 4px 4px -4px rgba(0, 0, 0, 0.9);
}
</style>

模拟外边框

box-shadow 是层层叠加的,第一层投影位于最顶层,依次类推。

注意事项:

  • 投影的行为跟边框不完全一致,它不会影响布局,还是可以通过内边距或外边距(这取决于投影是内嵌和还是外扩的)来额外模拟出边框所需要占据的空间;
  • 不会响应鼠标事件,比如悬停或点击,如果需要可以给 box-shadow 属性加上 inset 关键字,来使投影绘制在元素的内圈。
vue
<template>
  <div class="h-200 box-shadow"></div>
</template>

<style lang="scss" scoped>
.box-shadow {
  margin: 40px;
  background: yellowgreen;
  box-shadow: 0 0 0 10px #655, 0 0 0 15px deeppink, 0 2px 5px 15px rgba(0, 0, 0, 0.6);
}
</style>