跳转到内容

clip-path 实现不规则图形及溢出场景

本章节开始介绍新的属性 clip-path,该元素主要用于裁剪元素的可视区域。

clip-path 基本用法

clip-path 的基本语法如下:

css
clip-path: [ shape() | url()] | none;

clip-path 可以接受一个 shape() 函数,也可以接受一个 url() 函数,还可以接受 none,表示不裁剪。

shape() 函数可以接受 inset(), circle(), ellipse(), polygon() 等函数,这些函数都是裁剪的形状。url() 函数可以接受一个 SVG 的 URL,表示裁剪的形状。

常见的裁剪形状如下:

css
/* 裁剪为圆形 */
clip-path: circle(50px at center);
/* 裁剪为椭圆 */
clip-path: ellipse(50px 30px at center);
/* 裁剪为矩形 */
clip-path: inset(10px 20px 30px 40px);
/* 裁剪为多边形 */
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);

效果如下图所示:

运行效果

具体效果可查看 clip-path 基本用法

clip-path 括号内的参数都是元素的坐标点,这些坐标点都是相对于元素左上角的位置。

clip-path 直接写会不太方便,社区有一些在线生成工具,可以帮助开发者更好的使用 clip-path,比如 CSS clip-path。它包含了多种常用的图形,并且可以调整图形坐标的参数,底部还能实时更新最新的参数代码。

CSS clip-path界面

用 clip-path 实现常见不规则图形

还是用之前的例子,之前使用 mask 实现了内切角的效果,现在可以借助 clip-path 快速实现效果,这样背景色可以直接任意定制,无论是渐变还是纯色都不在话下。

css
div {
  width: 200px;
  height: 100px;
  background: linear-gradient(45deg, #ff7e5f, #feb47b);
  clip-path: polygon(
    15px 0,
    calc(100% - 15px) 0,
    100% 15px,
    100% calc(100% - 15px),
    calc(100% - 15px) 100%,
    15px 100%,
    0 calc(100% - 15px),
    0 15px
  );
}

效果

在实现不规则多边形效果上,clip-pathmask 更为直观,而且代码量更少。如果要实现箭头图形效果:

箭头效果

如果用 mask ,虽然也可以做到,但是代码量会很繁琐,如果用 clip-path,很轻松就能实现效果。

css
div {
  width: 200px;
  height: 100px;
  margin: 0 auto;
  background: linear-gradient(90deg, skyblue, blue);
  clip-path: polygon(
    0 0,
    calc(100% - 50px) 0,
    100% 50%,
    calc(100% - 50px) 100%,
    0 100%,
    50px 50%
  );
}

具体效果可查看 clip-path 实现不规则图形

clip-path 的局限性

clip-path 通过裁剪实现不规则图形效果,但 clip-path 并不是万能的,它也有一些局限性。

它最大的局限性在于,无法作用完整的边框。以上方两个例子为例,各自添加一个边框,看看效果如何。

css
div {
  border: 2px solid #333;
}

.foo {
  width: 200px;
  height: 100px;
  margin: 0 auto 20px;
  background: linear-gradient(45deg, #ff7e5f, #feb47b);
  clip-path: polygon(
    15px 0,
    calc(100% - 15px) 0,
    100% 15px,
    100% calc(100% - 15px),
    calc(100% - 15px) 100%,
    15px 100%,
    0 calc(100% - 15px),
    0 15px
  );
}

.box {
  width: 200px;
  height: 100px;
  margin: 0 auto;
  background: linear-gradient(90deg, skyblue, blue);
  clip-path: polygon(
    0 0,
    calc(100% - 50px) 0,
    100% 50%,
    calc(100% - 50px) 100%,
    0 100%,
    50px 50%
  );
}

加上边框后的效果

这是因为 clip-path 实际做的是切割图形,而边框实际作用在整体 div 上,因此被切割后的部分无法显示边框。

如果在切割裁剪完图形之后,又想要添加边框,该如何实现?

filter: drop-shadow()

box-shadow 是给整个盒子添加阴影效果,而 drop-shadow() 是创建一个符合当前元素本身形状的阴影,因此可以使用这个黑科技,给切割后的图形添加阴影,视觉上实现边框效果。

html
<div class="father">
  <div class="foo"></div>
</div>
<div class="father">
  <div class="box"></div>
</div>
css
.father {
  width: 200px;
  height: 100px;
  background: transparent;
  margin: 0 auto 20px;
  filter: drop-shadow(0 0 1px #000);
}

.foo {
  width: 200px;
  height: 100px;
  margin: 0 auto 20px;
  background: linear-gradient(45deg, #ff7e5f, #feb47b);
  clip-path: polygon(
    15px 0,
    calc(100% - 15px) 0,
    100% 15px,
    100% calc(100% - 15px),
    calc(100% - 15px) 100%,
    15px 100%,
    0 calc(100% - 15px),
    0 15px
  );
}

.box {
  width: 200px;
  height: 100px;
  margin: 0 auto;
  background: linear-gradient(90deg, skyblue, blue);
  clip-path: polygon(
    0 0,
    calc(100% - 50px) 0,
    100% 50%,
    calc(100% - 50px) 100%,
    0 100%,
    50px 50%
  );
}

具体效果可查看 drop-shadow 模拟边框

注意

想要实现效果,需要注意 filter: drop-shadow() 需要添加在父元素上,因为 drop-shadow() 是创建一个符合当前元素本身形状的阴影,因此需要将阴影作用在父元素上。

clip-path 的坐标可以是负数,可以超出 100%

最常见的使用的 clip-path: polygon() 中,polygon() 内需要填入具体的数值,但是这里面的值可以是负数,可以超出 100% 。

下面来举一个例子实现这个功能。

html
<div>
  <img src="https://picsum.photos/100/100?random=2" alt="" />
</div>
less
div {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  width: 100px;
  height: 100px;
  margin: 0 auto;

  &::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    height: 100%;
    transform: translate(-50%, -50%);
    border: 3px solid red;
  }

  img {
    width: 120%;
    height: 120%;
  }
}

普通效果

有一个 img ,宽高都是父盒子的 120%,下面对它做裁剪处理。

less
div {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  width: 300px;
  height: 300px;
  margin: 0 auto;
  clip-path: polygon(-5% -19%, 100% -3%, 100% 128%, -1% 100%); 

  &::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    height: 100%;
    transform: translate(-50%, -50%);
    border: 3px solid red;
  }

  img {
    width: 120%;
    height: 120%;
  }
}

添加后元素实现裁剪的效果,因此可以得出结论,clip-path 不仅仅能控制元素内的裁剪,对超出元素范围的内容一样有裁剪的能力

那么这个能力有什么用呢?下面看一个著名游戏的封面布局图。

封面布局图

可以看到很多图片都是不规则型,且大小超出了父容器。可能会有人想,这个效果直接找 UI 切图不就好了?那如果添加鼠标悬停效果呢?

封面布局图添加鼠标悬停效果

这就没法用切图就直接解决了,这个效果的核心效果就是 display: grid 布局结合 clip-path 裁剪实现的。

用 clip-path 实现指定区域的 overflow: hidden

clip-path 可以控制区域外的裁剪,那么也意味着,可以用来指定溢出隐藏的区域。什么意思呢?下面看看这个效果图。

效果图

可以看到,只有在 y 轴溢出部分才会隐藏,而 x 轴溢出部分则不会隐藏。这个效果直接设置 overflow: hidden 是无法实现的。

css
div {
  width: 200px;
  height: 200px;
  clip-path: polygon(-1000% 0, 1000% 0, 1000% 100%, -1000% 100%);
}

上方代码中,横向用了上一节提到的裁剪可以设为负数和超出 100% 的知识点,裁剪了 1000% ,因此横向溢出部分不会隐藏,而纵向裁剪了 100% ,这样整个裁剪区域画成一个超大的矩形形状,因此纵向溢出部分会隐藏。

以此类推:

css
div {
  clip-path: polygon(0 0, 1000% 0, 100% 1000%, 0 0); /* 只允许右侧溢出 */
}

div {
  clip-path: polygon(
    -1000% 0,
    100% 0,
    100% 1000%,
    -1000% 1000%
  ); /* 只允许左侧和下侧溢出 */
}

具体效果可查看 clip-path 实现指定区域的 overflow: hidden

总结

本章节主要讲了 clip-path 的基本用法和见识了它强大的功能,主要有:

  1. SVG 类似,它是一个通过裁剪来创建可视区域的属性,区域内显示,区域外隐藏,因此可以用来创建不规则图形。属性不需要死记硬背,可以访问在线工具 CSS clip-path 来生成。
  2. clip-path 裁剪后的图形无法添加边框,可以使用 filter: drop-shadow() 来模拟边框效果。
  3. clip-path 的坐标可以是负数,可以超出 100% ,因此可以实现超出父元素范围的裁剪效果。在部分 overflow 属性无法使用的情况下,可以尝试使用 clip-path 来实现。

贡献者

The avatar of contributor named as duyidao duyidao
The avatar of contributor named as 刀刀 刀刀

页面历史

刀刀博客累计访客 人;文档累计访问量共