# clip-path 元素裁剪 + shape-outside 文字不规则环绕布局
TIP
几乎所有 Web 应用或网站都需要裁剪图片这一功能。在前端开发中,clip-path
属性被广泛应用于裁剪图片或元素,以创造出独特的视觉效果和 CSS 布局。
本小节我们将专注于
clip-path
的系统讲解,以图解的方式详细讲解clip-path
的 5 种裁剪技术,保证你看得懂,学得会。
同时还会将图片裁剪技术与 transition
结合,实现目前非常流行的滑动动画,让你学完就可以应用于实际的工作。
# 一、clip-path 属性介绍
TIP
- CSS
clip-path
属性功能强大,兼容性好,目前各大浏览器都支持。 - CSS
clip-path
属性使用裁剪方式创建元素的可显示区域。区域内的部分显示,区域外的部分隐藏。 - CSS
clip-path
属性值不为none
时,会创建新的层叠上下文 - CSS
clip-path
属性有很多不同的函数值(下表列出了常用的),可以将元素或图片裁剪成各种不同形状。
属性值(函数) | 说明 |
---|---|
inset() | 将元素或图片裁剪成一个矩形 |
circle() | 将元素或图片裁剪成一个圆形 |
ellipse() | 将元素或图片裁剪成一个椭圆 |
polygon() | 将元素或图片裁剪成一个多边形 |
# 二、inset 矩形裁剪
TIP
CSS clip-path
属性值inset()
函数 用于将一个元素或图片裁剪成一个矩形。
# 1、基本用法
clip-path: inset(偏移量 圆角半径);
TIP
- 偏移量:表示元素上右下左四个方向向内的偏移量。他的写法和内边距 padding 写法一样,支持一个、两个、三个、四个值的写法(具体如何写,看下面示例)
- 圆角半径:是一个可选参数,表示被裁剪的矩形四个角的圆角半径大小,写法是 round 后面跟圆半径值,圆半径值也支持一个、两个、三个、四个值的写法(具体如何写,看下面示例)
<style>
.inset {
width: 200px;
height: 100px;
background-color: #4ccbcd;
/*
10px 50px 20px 100px 表示元素上右下左四个方向向内的偏移量
round 10px 表示被裁剪的矩形四个角的圆角半径大小为 10px
*/
clip-path: inset(10px 50px 20px 100px round 10px);
}
</style>
<body>
<div class="inset"></div>
</body>
裁剪原理示意图 | 裁剪后效果 |
---|---|
![]() |
# 2、矩形裁剪示例
TIP
偏移量 和 圆角半径都支持 1 个,2 个 ,3 个,4 个值的写法
<style>
.layout {
width: 200px;
height: 100px;
background-color: #4ccbcd;
}
.inset1 {
clip-path: inset(50px 20px 10px);
}
.inset2 {
clip-path: inset(20px 50px round 10px 0px 0px);
}
.inset3 {
clip-path: inset(30px round 20px 10px);
}
</style>
<div class="layout inset1"></div>
<div class="layout inset2"></div>
<div class="layout inset3"></div>
裁剪代码 | 裁剪原理示意图 | 裁剪后效果 |
---|---|---|
inset( 50px 20px 10px) | ||
inset( 20px 50px round 10px 0px 0px) | ||
inset(30px round 20px 10px) | ![]() |
# 3、百分比值
TIP
inset
函数中的偏移量与圆角半径值都可以采用 百分比值,百分比值分别相对于元素的 可视宽 和 可视高 而言
<style>
.inset {
width: 200px;
height: 100px;
background-color: #4ccbcd;
/*
上下偏移量(内缩) 100*10%=10px
左右偏移量(内缩) 200 * 30%=60px
圆角水平半径 = 200px * 5%= 10px
圆角垂直半径=100px * 5%=5px
*/
clip-path: inset(10% 30% round 5%);
/* 上面代码,等同于下面写法*/
/* clip-path: inset(10px 60px round 10px/5px); */
}
.layout {
width: 200px;
height: 100px;
background-color: #c6e2e3;
}
</style>
<div class="layout">
<div class="inset"></div>
</div>
# 4、实战应用:展开动画
TIP
可以利用 CSS clip-path:inset()
与 CSS transition
结合实现如下图所示的过渡动画效果
实现原理
- 最开始
clip-path
的属性值是inset(50% 50% 50% 50%)
, 元素被裁剪至完全看不见 - 鼠标移入后,
clip-path
的属性值是inset(0)
,元素相当于没有被裁剪,则全部可见 - 给元素添加
transition:clip-path 0.5s
过渡效果,就可以实现当鼠标移入后,让元素从完全看不见慢慢过渡到完全看得见的动画效果
完整版源码
<style>
h3,
p {
margin: 0;
}
.layout {
width: 300px;
height: 200px;
position: relative;
}
.layout img {
width: 100%;
height: 100%;
object-fit: cover;
}
.content {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
/* clip-path: inset(50% 50% 50% 50%); */
clip-path: inset(50%);
transition: clip-path 0.5s;
color: #fff;
/* 弹性布局 */
display: flex;
/* 主轴为垂直方向 */
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0px 20px;
}
.content h3 {
margin-bottom: 10px;
}
/* 鼠标移入效果 */
.layout:hover .content {
clip-path: inset(0);
}
</style>
<div class="layout">
<img src="./images/ms.jpg" alt="美食" />
<div class="content">
<h3>巨诺西大魔芋低凉皮凉面</h3>
<p>配料:面、胡萝卜、西蓝花、黄瓜、玉米、虾</p>
</div>
</div>
# 4、实战应用:推拉门动画
在上面案例的基础上,把裁剪的代码更改为如下即可
.content {
/* 省略部分css,具体见前面*/
/* clip-path:inset(50% 50% 50% 50%); */
clip-path: inset(0 0 100% 0);
}
你可以通过修改裁剪的代码,实现不同方向的推拉门效果。
# 三、圆形裁剪
TIP
CSS 属性 clip-path:circle()
用于将一个元素或图片裁剪成一个圆形
# 1、基本用法
clip-path: circle(圆半径 at 圆心坐标);
TIP
圆半径可以是以下四种值
- 可以是长度单位 (如:10px)
- 可以是百分比 (如 50%),百分比慎用,因为百比相对谁而言不确定
- 可以是
closest-side
与元素中最近的边相交形成的圆 - 可以是
farthest-side
与元素中最远的边相交形成的圆
圆心坐标可以是以下三种值
- 可以是一个长度单位,如
50px
可以是一个百分比(x 坐标相对宽而言 y 坐标相对高而言),如(50% 50%) - 可以是 left right 与 top bottom 和 center 三组中任意两个关键字组合或一个字,如(left center 或 right bottom)
- 可以是一个长度单位,如
<style>
.circle {
width: 200px;
height: 100px;
background-color: khaki;
/*
将元素裁剪成一个半径为 50px的圆,
圆心位坐标 100px 50px (相对元素左上角而言)
*/
clip-path: circle(50px at 100px 50px);
}
</style>
<div class="circle"></div>
裁剪原理示意图 | 裁剪后效果 |
---|---|
# 2、圆形裁剪示例
TIP
圆的半径 和 圆心坐标的不同值写法
<style>
.layout {
width: 200px;
height: 100px;
background-color: khaki;
}
.circle1 {
/* 裁剪半径为 50px的圆,圆心坐标位于元素中心 */
clip-path: circle(50px at 50% 50%);
}
.circle2 {
/* 裁剪半径为 50px的圆,圆心坐标元素最右边的中心位置 */
clip-path: circle(50px at right center);
}
.circle3 {
/* 在离元素 50px 30px 坐标处,
裁剪一个与当前元素最近的一边相交的圆*/
clip-path: circle(closest-side at 50px 30px);
}
.circle4 {
/* 在离元素 50px 30px 坐标处,
裁剪一个与当前元素最远的一边相交的圆*/
clip-path: circle(farthest-side at 50px 30px);
}
</style>
<div class="layout circle1"></div>
<div class="layout circle2"></div>
<div class="layout circle3"></div>
<div class="layout circle4"></div>
裁剪代码 | 裁剪原理示意图 | 裁剪后效果 |
---|---|---|
clip-path: circle(50px at 50% 50%) | ||
clip-path: circle(50px at right center) | ||
clip-path: circle(closest-side at 50px 30px ) | ||
clip-path: circle(farthest-side at 50px 30px ) |
# 3、实战应用:圆形展开动画
TIP
可以利用 CSS clip-path:circle()
与 CSS transition
过渡动画结合实现如下所示的鼠标悬停动画
我们只需要将前面的推拉门动画中的元素裁剪代码修改成如下即可
.content {
/* 省略部分css,具体见前面 */
/* clip-path:inset(50% 50% 50% 50%); */
clip-path: circle(0px at left top);
}
.layout:hover .content {
/* clip-path:inset(0); */
clip-path: circle(400px at left top);
}
# 四、ellipse 椭圆裁剪
TIP
CSS 属性 clip-path:ellipse()
用于将一个元素裁剪成一个椭圆
# 1、基本使用
clip-path: ellipse(x轴半径 y轴半径 at 椭圆圆心);
ellipse()
函数的用法与 circle()
函数用法相似,唯一的区别在于 ellipse()
函数中椭圆半径值有两个,而circle()
函数中圆的半径只有一个。
<style>
.ellipse {
width: 200px;
height: 100px;
background-color: khaki;
/*
将元素裁剪成一个x轴半径为20px,y轴半为50px的椭圆,
圆心位于元素100px 50px坐标处
*/
clip-path: ellipse(20px 50px at 100px 50px);
/* 也可以用如下百分比值 */
clip-path: ellipse(10% 50% at 100px 50px);
}
</style>
<div class="ellipse"></div>
裁剪原理示意图 | 裁剪后效果 |
---|---|
# 2、椭圆裁剪示例
TIP
椭圆半径和圆心坐标值的不同写法演示
<style>
.layout {
width: 200px;
height: 100px;
background-color: khaki;
}
.ellipse1 {
/*
将元素裁剪成一个x轴半径为20px,y轴半为50px的椭圆,
圆心位于元素左边中间(0px 50px)
*/
clip-path: ellipse(20px 50px at left center);
}
.ellipse2 {
/*
在元素坐标 30px 10px 处裁剪一个椭圆,
椭圆水平与左边相切,垂直与上边相切
*/
clip-path: ellipse(closest-side closest-side at 30px 10px);
}
.ellipse3 {
/*
在元素坐标 30px 50px 处裁剪一个椭圆,
椭圆水平与右边相切,垂直与下边相切
*/
clip-path: ellipse(farthest-side closest-side at 30px 80px);
}
</style>
<div class="layout ellipse1"></div>
<div class="layout ellipse2"></div>
<div class="layout ellipse3"></div>
裁剪代码 | 裁剪原理示意图 | 裁剪后效果 |
---|---|---|
clip-path:ellipse(20px 50px at left center) | ||
clip-path:ellipse(closest-side closest-side at 30px 10px) | ||
clip-path:ellipse(farthest-side closest-side at 30px 80px) |
# 3、实战应用:椭圆卡片悬停效果
TIP
可以利用 CSS clip-path:ellipse()
与 CSS transition
结合实现如下图所示的椭圆过渡动画
<style>
.list {
width: 100px;
height: 150px;
background-color: khaki;
clip-path: ellipse(130% 100% at top center);
/* transition: height cubic-bezier(0.08, 1.42, 0, 2.13) 0.3s; */
transition: transform cubic-bezier(0.08, 1.42, 0, 2.13) 0.3s;
transform-origin: top center;
}
.list:hover {
transform: scaleY(1.5); /* 拉伸高度 */
/* height: 200px; */
}
</style>
<div class="list"></div>
也可以元素的高度变化,改为改变 height 属性
.list {
/* 省略部分代码 */
transition: height cubic-bezier(0.08, 1.42, 0, 2.13) 0.3s;
}
.list:hover {
height: 200px;
}
# 五、polygon 多边形裁剪
TIP
CSS 属性 clip-path:polygon()
用于将一个元素裁剪成一个多边形
:::
# 1、基本使用
clip-path: polygon(x1 y1, x2 y2, ......., xn yn);
polygon()
函数内至少要 3 对坐标,这些坐标相互连接形成一个多边形,多边形内的区域显示,外的区域隐藏。
坐标可以是固定的长度单位,也可以是百分比(x% 相对宽度计算,y%相对高度计算)
<style>
.layout {
width: 200px;
height: 200px;
background-color: tomato;
}
.triangle {
/* 裁剪三角形 */
clip-path: polygon(100px 0, 200px 200px, 0 200px);
}
.rhombus {
/* 裁剪菱形 */
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0% 50%);
}
</style>
<div class="layout triangle"></div>
<div class="layout rhombus"></div>
裁剪代码 | 裁剪原理示意图 | 裁剪后效果 |
---|---|---|
clip-path: polygon(100px 0, 200px 200px , 0 200px) | ||
clip-path: polygon(50% 0, 100% 50% , 50% 100% , 0% 50%) |
# 2、多边形裁剪示例
以上多边形裁剪,大家可以利用 CSS clip-path 多边形生成器来帮助我们完成
CSS clip-path 生成器:https://css.bqrdh.com/clip-path/editor (opens new window)
# 3、实战应用:蜂巢布局
body {
margin: 0;
overflow: hidden;
}
.container {
margin: 0 auto;
--size: calc(100vw / 8);
}
.row {
display: flex;
}
.col {
width: var(--size);
height: var(--size);
flex-shrink: 0;
border: 1px solid red;
background-color: skyblue;
clip-path: polygon(50% 5%, 95% 25%, 95% 75%, 50% 95%, 5% 75%, 5% 25%);
transition: all 0.5s;
}
/* 偶数行 */
.row:nth-child(2n) {
transform: translateX(calc(var(--size) / 2 * -1));
}
/* 从第二行开始, 下面的第一行往上移一定距离 */
.row {
margin-bottom: calc(var(--size) / 4.6 * -1);
}
.row .col img {
width: 100%;
height: 100%;
object-fit: cover;
}
<div class="container">
<div class="row">
<div class="col"><img src="./images/01.png" /></div>
<div class="col"><img src="./images/02.png" /></div>
<div class="col"><img src="./images/03.png" /></div>
<div class="col"><img src="./images/04.png" /></div>
<div class="col"><img src="./images/05.png" /></div>
<div class="col"><img src="./images/06.png" /></div>
<div class="col"><img src="./images/07.png" /></div>
<div class="col"><img src="./images/08.png" /></div>
</div>
<div class="row">
<div class="col"><img src="./images/10.png" /></div>
<div class="col"><img src="./images/11.png" /></div>
<div class="col"><img src="./images/12.png" /></div>
<div class="col"><img src="./images/13.png" /></div>
<div class="col"><img src="./images/14.png" /></div>
<div class="col"><img src="./images/15.png" /></div>
<div class="col"><img src="./images/16.png" /></div>
<div class="col"><img src="./images/17.png" /></div>
<div class="col"><img src="./images/06.png" /></div>
</div>
<div class="row">
<div class="col"><img src="./images/01.png" /></div>
<div class="col"><img src="./images/02.png" /></div>
<div class="col"><img src="./images/03.png" /></div>
<div class="col"><img src="./images/04.png" /></div>
<div class="col"><img src="./images/05.png" /></div>
<div class="col"><img src="./images/06.png" /></div>
<div class="col"><img src="./images/07.png" /></div>
<div class="col"><img src="./images/08.png" /></div>
</div>
<div class="row">
<div class="col"><img src="./images/01.png" /></div>
<div class="col"><img src="./images/02.png" /></div>
<div class="col"><img src="./images/03.png" /></div>
<div class="col"><img src="./images/04.png" /></div>
<div class="col"><img src="./images/05.png" /></div>
<div class="col"><img src="./images/06.png" /></div>
<div class="col"><img src="./images/07.png" /></div>
<div class="col"><img src="./images/08.png" /></div>
<div class="col"><img src="./images/05.png" /></div>
</div>
</div>
# 六、shape-outside 属性
TIP
CSS 属性 shape-outside
定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。
# 1、基本用法
TIP
shape-outside
属性指定使用下面列表的值来定义浮动元素的浮动区域。这个浮动区域决定了行内内容(浮动元素)所包裹的形状。
语法
/* 关键字值 */
shape-outside: none;
shape-outside: margin-box;
shape-outside: content-box;
shape-outside: border-box;
shape-outside: padding-box;
/* 函数值 */
shape-outside: circle();
shape-outside: ellipse();
shape-outside: inset(10px 10px 10px 10px);
shape-outside: polygon(10px 10px, 20px 20px, 30px 30px);
/* <url> 值 */
shape-outside: url(image.png);
/* 渐变值 */
shape-outside: linear-gradient(45deg, rgba(255, 255, 255, 0) 150px, red 150px);
# 2、值为关键值
TIP
根据浮动元素的边缘形状计算出浮动的区域。
margin-box
定义一个由外边距的外边缘封闭形成的形状border-box
定义一个由边界的外边缘封闭形成的形状padding-box
定义一个由内边距的外边缘封闭形成的形状content-box
定义一个由内容区域的外边缘封闭形成的形状none
: 该浮动区域不产生影响,行内元素以默认的方式包裹着该元素的 margin box
<style>
.circle {
width: 50px;
height: 50px;
background-color: red;
border: 30px solid blue;
padding: 10px;
margin: 30px;
border-radius: 50%;
/* 浮动 */
float: left;
/* 将属性值更换为以下值,查看效
none,margin-box,border-box,padding-box,content-box
*/
shape-outside: content-box;
}
</style>
<div class="container">
<div class="circle"></div>
<p>
shape-outside 的 CSS
属性定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。默认情况下,内联内容包围其边距框;
shape-outside提供了一种自定义此包装的方法,可以将文本包装在复杂对象周围而不是简单的框中。
</p>
<p>
shape-outside 的 CSS
属性定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。默认情况下,内联内容包围其边距框;
shape-outside提供了一种自定义此包装的方法,可以将文本包装在复杂对象周围而不是简单的框中。
</p>
</div>
值 | 渲染的效果 |
---|---|
none | ![]() |
margin-box | ![]() |
border-box | ![]() |
padding-box | ![]() |
content-box | ![]() |
# 3、值为绘制形状的函数
TIP
基于 inset()
、circle()
、ellipse()
或 polygon()
其中一个创造出来的形状计算出浮动区域。这个浮动区域决定了行内内容(浮动元素)所包裹的形状。
<style>
.shape {
width: 200px;
height: 200px;
margin-right: 20px;
background-image: url("./images/ms.jpg");
float: left;
/* 长方形 4个角为圆角*/
/*
shape-outside: inset(50px 10px round 10px);
clip-path:inset(50px 10px round 10px) ;
*/
/* 半圆 */
/*
shape-outside: circle(50% at left center);
clip-path:circle(50% at left center);
*/
/* 椭圆 */
/* shape-outside: ellipse(100px 40px at 50%);
clip-path:ellipse(100px 40px at 50%); */
/* 五角星形状 */
shape-outside: polygon(
50% 0%,
60% 35%,
100% 35%,
70% 60%,
75% 100%,
50% 70%,
20% 100%,
30% 60%,
0% 35%,
40% 35%
);
clip-path: polygon(
50% 0%,
60% 35%,
100% 35%,
70% 60%,
75% 100%,
50% 70%,
20% 100%,
30% 60%,
0% 35%,
40% 35%
);
}
</style>
<div class="container">
<div class="shape"></div>
<p>
shape-outside 的 CSS
属性定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。默认情况下,内联内容包围其边距框;
shape-outside提供了一种自定义此包装的方法,可以将文本包装在复杂对象周围而不是简单的框中。
</p>
<p>
shape-outside 的 CSS
属性定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。默认情况下,内联内容包围其边距框;
shape-outside提供了一种自定义此包装的方法,可以将文本包装在复杂对象周围而不是简单的框中。
</p>
</div>
属性值 | 渲染效果 |
---|---|
inset(50px 10px round 10px) | ![]() |
circle(50% at left center) | ![]() |
ellipse(100px 40px at 50%) | ![]() |
polygon(50% 0%, 60% 35%, 100% 35%, 70% 60%, 75% 100%, 50% 70%, 20% 100%, 30% 60%, 0% 35%, 40% 35%) | ![]() |
# 4、值是 url 图片地址
准备的图片素材:
<style>
.shape {
width: 200px;
height: 200px;
float: left;
/* 一张不规则图形的图片 */
shape-outside: url(./images/shape.png);
}
</style>
<div class="container">
<img src="./images/shape.png" class="shape" />
<p>
shape-outside 的 CSS
属性定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。默认情况下,内联内容包围其边距框;
shape-outside提供了一种自定义此包装的方法,可以将文本包装在复杂对象周围而不是简单的框中。
</p>
<p>
shape-outside 的 CSS
属性定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。默认情况下,内联内容包围其边距框;
shape-outside提供了一种自定义此包装的方法,可以将文本包装在复杂对象周围而不是简单的框中。
</p>
</div>
# 5、值是绘制的渐变背景图
TIP
CSS 属性 shape-image-threshold
通过设定一个 alpha 通道的界限值来提取shape-outside
(opens new window) 值为图像的形状。
所有 alpha 值比这个界限值 大 的像素都会被当做形状的一部分,以此确定形状的边界。
<style>
.shape {
width: 200px;
height: 200px;
float: left;
background-image: linear-gradient(
-45deg,
rgba(0, 255, 255, 0.5) 150px,
red 150px
);
shape-outside: linear-gradient(
-45deg,
rgba(0, 255, 255, 0.5) 150px,
red 150px
);
/*
shape-outside 中绘制背景图形透明度大于0.6的部分为形状区域*/
shape-image-threshold: 0.6;
}
</style>
<div class="container">
<div class="shape"></div>
<p>
shape-outside 的 CSS
属性定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。默认情况下,内联内容包围其边距框;
shape-outside提供了一种自定义此包装的方法,可以将文本包装在复杂对象周围而不是简单的框中。
</p>
<p>
shape-outside 的 CSS
属性定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。默认情况下,内联内容包围其边距框;
shape-outside提供了一种自定义此包装的方法,可以将文本包装在复杂对象周围而不是简单的框中。
</p>
</div>
将上面案例代码的background-image
和 shape-outside
值修改成如下
background-image: linear-gradient(skyblue, transparent);
shape-outside: linear-gradient(skyblue, transparent);
最终渲染效果如下
# 6、shape-margin
TIP
CSS 属性 shape-margin
用于设定由 shape-outside
创建的 CSS 形状的外边距。
<style>
.shape {
width: 200px;
height: 200px;
float: left;
background-color: khaki;
/* 效果1 代码 */
/*
clip-path: circle(50px at 50%);
shape-outside: circle(50px at 50%);
*/
/* 效果2 代码 */
clip-path: polygon(0 0, 100% 0, 0 100%);
shape-outside: polygon(0 0, 100% 0, 0 100%);
/*
形状与环绕文字的外间距
*/
shape-margin: 20px;
}
</style>
<div class="container">
<div class="shape"></div>
<p>
shape-outside 的 CSS
属性定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。默认情况下,内联内容包围其边距框;
shape-outside提供了一种自定义此包装的方法,可以将文本包装在复杂对象周围而不是简单的框中。
</p>
<p>
shape-outside 的 CSS
属性定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。默认情况下,内联内容包围其边距框;
shape-outside提供了一种自定义此包装的方法,可以将文本包装在复杂对象周围而不是简单的框中。
</p>
</div>
效果一 | 效果 2 |
---|---|
![]() | ![]() |
大厂最新技术学习分享群

微信扫一扫进群,获取资料
X