普通的box-shadow会在图片四周生成规则阴影,看起来更像一张悬浮卡片。如果希望图片像纸张一样,两侧或某个角微微翘起,就需要使用伪元素制作不规则阴影。

实现思路并不复杂:给图片添加一个外层容器,在容器底部放置两个经过旋转的伪元素,再把伪元素产生的阴影压到图片后方。

CSS box-shadow与伪元素制作图片翘边效果

可以直接使用的完整代码

先给图片增加一个外层元素。不要直接把伪元素写在img上,因为img属于替换元素,通常不能可靠生成::before和::after。

<div class="curl-shadow">
  <img src="photo.jpg" alt="示例图片">
</div>

对应的CSS如下:

.curl-shadow {
  position: relative;
  display: inline-block;
  max-width: 100%;
  isolation: isolate;
}

.curl-shadow img {
  position: relative;
  z-index: 1;
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: 4px;
}

.curl-shadow::before,
.curl-shadow::after {
  position: absolute;
  z-index: 0;
  bottom: 12px;
  width: 45%;
  height: 20%;
  content: "";
  box-shadow: 0 16px 12px rgba(0, 0, 0, 0.45);
}

.curl-shadow::before {
  left: 10px;
  transform: rotate(-3deg) skewY(-2deg);
}

.curl-shadow::after {
  right: 10px;
  transform: rotate(3deg) skewY(2deg);
}

这段代码会在图片底部左右两侧生成斜向阴影,形成中间贴近页面、两边略微翘起的视觉效果。

翘边效果是怎样形成的

真正显示在页面上的仍然是一张普通图片。::before和::after分别放在图片底部两侧,并通过transform进行小角度旋转。

伪元素本身被图片覆盖,用户主要看到的是它们向外扩散的box-shadow。因为左右伪元素旋转方向相反,阴影也会向不同方向延伸,看起来就像纸张的两个角离开了桌面。

  • position:relative为伪元素提供定位基准。

  • box-shadow负责生成底部投影。

  • rotate控制左右阴影的倾斜方向。

  • skewY让阴影形状不那么规则。

  • z-index让图片显示在阴影上方。

  • isolation:isolate限制内部层叠范围。

如何调整阴影强弱

翘边阴影的主要参数集中在box-shadow中:

box-shadow: 0 16px 12px rgba(0, 0, 0, 0.45);

四组数值依次表示水平偏移、垂直偏移、模糊半径和阴影颜色。

希望效果更轻,可以减少透明度并增加模糊范围:

box-shadow: 0 14px 18px rgba(0, 0, 0, 0.22);

希望翘边更加明显,可以增加垂直偏移和旋转角度:

box-shadow: 0 20px 14px rgba(0, 0, 0, 0.5);
transform: rotate(-5deg);

旋转角度不宜过大。一般使用2deg至5deg已经能够形成明显效果,角度过大容易让阴影看起来像多出了一块黑色图形。

只让右下角翘起

有些设计不需要左右对称,只希望图片右下角产生卷边感。这时可以只保留::after。

.curl-shadow-single {
  position: relative;
  display: inline-block;
  isolation: isolate;
}

.curl-shadow-single img {
  position: relative;
  z-index: 1;
  display: block;
  max-width: 100%;
  height: auto;
}

.curl-shadow-single::after {
  position: absolute;
  z-index: 0;
  right: 8px;
  bottom: 12px;
  width: 55%;
  height: 22%;
  content: "";
  box-shadow: 10px 16px 14px rgba(0, 0, 0, 0.4);
  transform: rotate(4deg) skewY(3deg);
}

这种单侧效果适合文章配图、作品展示和照片墙。多张图片放在一起时,还可以交替设置左右翘角,避免页面显得过于整齐。

增加纸张本身的层次感

翘边阴影可以和普通图片阴影同时使用,但普通阴影不宜太重。可以在图片上增加一层较浅的投影:

.curl-shadow img {
  position: relative;
  z-index: 1;
  display: block;
  max-width: 100%;
  height: auto;
  padding: 6px;
  background: #fff;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.16);
}

白色内边距会让图片更像冲印照片,浅色常规阴影负责表现图片与页面之间的距离,底部伪元素则负责表现翘角。

如果网站背景本身是白色,可以把图片外框改成略带灰度的颜色,避免边界完全消失。

为什么代码没有显示效果

翘边阴影不显示,通常不是box-shadow失效,而是层级或裁剪方式存在问题。

伪元素写在img上

::before和::after应放在图片外层容器上,而不是直接写在img选择器上。

外层设置了overflow:hidden

阴影会延伸到容器外部。如果父元素设置overflow:hidden,超出区域的阴影就会被裁掉。需要圆角裁剪图片时,可以再增加一层内部容器,不要直接裁剪负责显示阴影的外层。

图片没有设置层级

图片应使用position:relative和较高的z-index,否则伪元素可能覆盖在图片上方,显示成灰黑色块。

阴影颜色与背景太接近

深色页面中使用黑色阴影时,效果可能不明显。可以降低页面背景亮度差异,或者根据主题使用带透明度的深灰阴影。

图片容器宽度不正确

容器宽度应跟随图片。如果外层是整行宽度,而图片本身很窄,左右阴影会按照整行容器定位,导致位置偏离。

参考资料

  1. MDN box-shadow属性说明

  2. MDN ::before伪元素说明

  3. MDN transform属性说明

  4. MDN z-index层叠顺序说明