裁切路径 ( clip-path )
clip-path 是个特别的 CSS 样式属性,可以在网页元素里定义一出个“裁切形状”,让元素只显示裁切形状的内容,裁切形状外围都会变成透明背景,这篇教学会介绍如何使用 clip-path 裁切路径,绘制各种正多边形以及不规则的图形,最后还会介绍使用 url() 搭配 SVG 的 path,制作可缩放的裁切路径。
这篇教学只会介绍非 SVG 元素的用法,但
clip-path也有针对 SVG 元素的属性值,可先从这篇文章了解更多:SVG 研究之路 (9) - Clipping and Masking
快速导览:
clip-path 裁切形状
通常使用 clip-path 会先透过下列的 CSS 定义形状函数 ( 点击函数名称可以查看详细教学 ),裁切出特定的形状,定义形状之后,套用 clip-path 的元素只有裁切形状的部分会显示,裁切形状外围都会变成透明背景。
| CSS 函数 | 说明 |
|---|---|
| circle() | 圆形 |
| ellipse() | 椭圆形 |
| rect() | 四边形 |
| polygon() | 多边形 |
| inset() | 内缩边距和圆角 |
| xywh() | 虚拟矩形 |
| path() | 路径 |
定义形状时,需要注意下列几点:
- 单位通常使用
px或%。- 若单位使用
%,x 座标和左右长度为元素宽度的百分比,y 座标和上下长度为高度的百分比。
下方范例会呈现四种不同的裁切形状,并分别呈现 px 和 % 单位的差异 ( 使用另外的 div 呈现元素的实际大小 ),从中可以看出不只背景颜色被裁切,连同元素内容显示的文字都会一起被裁切。
<!-- HTML 程式碼-->
clip-path: circle(50px at 50px 50px);
<div><div>oxxo</div></div>
clip-path: circle(50% at 50% 50%);
<div><div>oxxo</div></div>
clip-path: ellipse(50px 10px at 50px 40px);
<div><div>oxxo</div></div>
clip-path: ellipse(50% 10% at 50% 40%);
<div><div>oxxo</div></div>
clip-path: inset(10px 20px 30px 40px round 10px 20px 30px 40px);
<div><div>oxxo</div></div>
clip-path: inset(10% 20% 30% 40% round 10% 20% 30% 40%);
<div><div>oxxo</div></div>
clip-path: polygon(0 0, 200px 20px, 100px 150px);
<div><div>oxxo</div></div>
clip-path: polygon(0 0, 200% 20%, 100% 150%);
<div><div>oxxo</div></div>
<!-- CSS 程式碼 -->
<style>
body > div {
width: 200px;
height:150px;
border: 2px solid #000;
margin: 10px;
}
div div {
width: 100%;
height: 100%;
border: none;
font-size: 40px;
}
div:nth-of-type(1) div {
clip-path: circle(50px at 50px 50px);
background: #f55;
}
div:nth-of-type(2) div {
clip-path: circle(50% at 50% 50%);
background: #f55;
}
div:nth-of-type(3) div {
clip-path: ellipse(50px 10px at 50px 40px);
background: #090;
}
div:nth-of-type(4) div {
clip-path: ellipse(50% 10% at 50% 40%);
background: #090;
}
div:nth-of-type(5) div {
clip-path: inset(10px 20px 30px 40px round 10px 20px 30px 40px);
background: #f90;
}
div:nth-of-type(6) div {
clip-path: inset(10% 20% 30% 40% round 10% 20% 30% 40%);
background: #f90;
}
div:nth-of-type(7) div {
clip-path: polygon(0 0, 200px 20px, 100px 150px);
background: #f09f;
}
div:nth-of-type(8) div {
clip-path: polygon(0 0, 200% 20%, 100% 150%);
background: #f09f;
}
</style>
撰写座标或宽度时,如果是“inset 内置矩形”,可以在“数值相同”的情况使用“缩写”写法:
- “边距”遵守“
上 右 下左”顺时钟写法,缩写为“上 左右 下”、“上下 左右”或“上右下左”。- “圆角半径”遵守“
左上 右上 右下 左下”顺时钟写法,缩写为“左上 右上左下 右下”、“左上右下 右上左下”或“四角”。
下方范例会使用缩写的方式呈现同样的结果。
<!-- HTML 程式碼-->
inset(10xp 20px 50px 20px round 10px 20px 50px 20px)
<div><div>oxxo</div></div>
inset(10px 20px 50px round 10px 20px 50px)
<div><div>oxxo</div></div>
inset(10px 50px 10px 50px round 10px 50px 10px 50px)
<div><div>oxxo</div></div>
inset(10px 50px round 10px 50px)
<div><div>oxxo</div></div>
inset(10px 10px 10px 10px round 10px 10px 10px 10px)
<div><div>oxxo</div></div>
inset(10px round 10px)
<div><div>oxxo</div></div>
<!-- CSS 程式碼 -->
<style>
body>div {
width: 200px;
height:150px;
border: 2px solid #000;
margin: 10px;
}
div div {
width: 100%;
height: 100%;
border: none;
font-size: 40px;
}
div:nth-of-type(1) div {
clip-path: inset(10px 20px 50px 20px round 10px 20px 50px 20px);
background: #f55;
}
div:nth-of-type(2) div {
clip-path: inset(10px 20px 50px round 10px 20px 50px);
background: #f55;
}
div:nth-of-type(3) div {
clip-path: inset(10px 50px 10px 50px round 10px 50px 10px 50px);
background: #090;
}
div:nth-of-type(4) div {
clip-path: inset(10px 50px round 10px 50px);
background: #090;
}
div:nth-of-type(5) div {
clip-path: inset(10px 10px 10px 10px round 10px 10px 10px 10px);
background: #f90;
}
div:nth-of-type(6) div {
clip-path: inset(10px round 10px);
background: #f90;
}
</style>
clip-path 绘制正多边形
运用 clip-path 里的 polygon 函数,搭配一些数学计算公式,就能绘制各种正多边形,使用 polygon 属性值可借助“CSS clip-path maker”这个网站,快速产生裁切形状所需的座标位置。
下方范例会展示透过 polygon 函数绘制各种正多边形的效果,使用时需要注意“采用顺时针方向绘制”,避免线段重叠时,发生面积区域相减的状况。
<!-- HTML 程式碼-->
正三角形<div></div>
正方形<div></div>
正五邊形<div></div>
正六邊形<div></div>
正七邊形<div></div>
正八邊形<div></div>
<!-- CSS 程式碼 -->
<style>
div {margin: 10px;}
div:nth-of-type(1) {
width: 100px;
height: 87px;
background: #c00;
clip-path: polygon(0% 100%, 50% 0%,100% 100%);
}
div:nth-of-type(2) {
width: 100px;
height: 100px;
background: #069;
clip-path: polygon(0% 0%,100% 0%,100% 100%, 0% 100%);
}
div:nth-of-type(3) {
width: 162px;
height: 154px;
background: #095;
clip-path: polygon(0% 38.31%, 50% 0%,100% 38.31%,80.86% 100%,19.14% 100%);
}
div:nth-of-type(4) {
width: 200px;
height: 174px;
background: #f80;
clip-path:polygon(25% 0%, 75% 0%,100% 50%,75% 100%,25% 100%,0% 50%);
}
div:nth-of-type(5) {
width: 224px;
height: 218px;
background: #09c;
clip-path: polygon(50% 0%, 90.18% 19.72%,100% 64.22%,72.32% 100%,27.68% 100%,0% 64.22%,10.09% 19.72%);
}
div:nth-of-type(6) {
width: 242px;
height: 242px;
background: #f69;
clip-path: polygon(29.34% 0%, 70.66% 0%,100% 29.34%,100% 70.66%,70.66% 100%,29.34% 100%,0% 70.66%,0% 29.34%);
}
</style>
clip-path 正多边形变换动画
如果已经可以使用 clip-path 制作正多边形,就能参考下方程序码,搭配 animation 做出正多边形变化的动画效果,范例中使用的技巧是先绘制出正八边形的“八个座标点”,依序将这些座标点改变座标并互相“重叠”,就能做出正多边形变换动画。
延伸阅读:动画 animation
<!-- HTML 程式碼-->
<div>oxxo</div>
<!-- CSS 程式碼 -->
<style>
div{
width: 115px;
height: 100px;
font-size: 45px;
text-align: center;
clip-path: polygon(0% 100%, 50% 0%,100% 100%,100% 100%,100% 100%,100% 100%,100% 100%,100% 100%);
animation-name: size, oxxo;
animation-duration: 5s;
animation-direction: alternate;
animation-timing-function: linear;
animation-iteration-count: infinite ;
}
@keyframes size{
5% {width: 115px;}
24% {width: 100px;}
43% {width: 105px;}
62% {width: 114px;}
81% {width: 103px;}
95%, 100% {width: 100px;}
}
@keyframes oxxo {
0%, 5% {
background: #c00;
clip-path: polygon(0% 100%,50% 0%,100% 100%,100% 100%,100% 100%,100% 100%,100% 100%,100% 100%);
}
24% {
background: #069;
clip-path: polygon(0% 100%,0% 0%,100% 0%,100% 100%,100% 100%,100% 100%,100% 100%,100% 100%);
}
43% {
background: #095;
clip-path: polygon(19.14% 100%,0% 38.31%,50% 0%,100% 38.31%,80.86% 100%,80.86% 100%,80.86% 100%,80.86% 100%);
}
62% {
background: #f80;
clip-path: polygon(25% 100%,0% 50%,25% 0%,75% 0%,100% 50%,75% 100%,75% 100%,75% 100%);
}
81% {
background: #09c;
clip-path: polygon(27.68% 100%,0% 64.22%,10.09% 19.72%,50% 0%,90.18% 19.72%,100% 64.22%,72.32% 100%,72.32% 100%);
}
95%, 100%{
background: #f69;
clip-path: polygon(29.34% 100%,0% 70.66%,0% 29.34%,29.34% 0%,70.66% 0%,100% 29.34%,100% 70.66%,70.66% 100%);
}
}
</style>
clip-path 三角形组合动画
下方范例会运用 clip-path 做出四个等腰三角形组成正方形,接着透过 animation 让四个等腰三角形分别变成四个正三角形。
<!-- HTML 程式碼-->
<div>O</div>
<div>X</div>
<div>O</div>
<div>X</div>
<!-- CSS 程式碼 -->
<style>
div{
position: absolute;
top: 50px;
left: 250px;
font-size: 30px;
box-sizing: border-box;
background: #c00;
}
div:nth-of-type(1){
padding: 27px 0 0 7px;
width: 50px;
height: 100px;
clip-path: polygon(0% 0%, 0% 100%, 100% 50%);
animation:a 2s infinite alternate;
}
div:nth-of-type(2){
padding: 0 0 0 40px;
width: 100px;
height: 50px;
clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
animation:b 2s infinite alternate;
}
div:nth-of-type(3){
padding: 27px 0 0 22px;
left: 300px;
width: 50px;
height: 100px;
clip-path: polygon(0% 50%, 100% 0%, 100% 100%);
animation:c 2s infinite alternate;
}
div:nth-of-type(4){
padding: 10px 0 0 40px;
top: 100px;
width: 100px;
height: 50px;
clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
animation:d 2s infinite alternate;
}
@keyframes a {
90%, 100% {
padding: 27px 0 0 40px;
left: 100px;
width: 100px;
height: 87px;
background:#09f;
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}
}
@keyframes b {
90%, 100% {
padding: 27px 0 0 40px;
left: 200px;
width: 100px;
height: 87px;
background: #0a0;
clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
}
}
@keyframes c {
90%, 100% {
left: 400px;
padding: 27px 0 0 40px;
width: 100px;
height: 87px;
background: #f09;
clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
}
}
@keyframes d {
90%, 100% {
left: 300px;
top: 50px;
padding: 27px 0 0 40px;
width: 100px;
height: 87px;
background: #f90;
clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
}
}
</style>
clip-path 使用 path 绘制不规则形状
从“CSS 路径 path”教学中可以知道,透过 CSS 的 path() 函数可以使用类似 SVG 的 path 路径,而动画 animation 和裁切路径 clip-path 都能运用这些路径做出特别的效果,举例来说,先透过 Vectorpea 这套线上向量绘图工具 ( 也可以自行使用 Illustrator ),使用“钢笔工具”绘制一段路径,绘制完成后储存为 SVG 文件,使用浏览器打开这个 SVG 观察源代码,在 d 属性里的就是路径编码。
注意:
- 文件尺寸先不要设定太大,建议长宽使用 100px~300px 进行测试。
- 套用于
clip-path的路径必须是“封闭”路径。
- 前往 Vectorpea:https://www.vectorpea.com/
- 参考:CSS 路径 path
下方范例会使用两个自订的路径产生出两个不规则形状。
<!-- HTML 程式碼-->
<div class="a"></div>
<div class="b"></div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
width: 200px;
height: 200px;
float: left;
margin: 5px;
background: repeating-linear-gradient(
orange 0%, orange 10%,
black 10%, black 20%);
}
.a {
clip-path: path("m97 47c0 0-5.1-32.4-40-24-34.9 8.4-43.3 38.1-26 75 17.3 36.9 83.2 79.2 83.2 79.2 0 0 1.6-47.3 41.1-51.5 59.4-6.3-17.9-33.5-33.2-42.5-15.3-8.9 48.2-93.5-25.1-36.2z");
}
.b {
clip-path: path("m96 161c-36.9-17.3-56.4-25-70-51-13.6-26-12-52.2 2-66 14-13.8 50.2-22.6 66 16 18.9-41.4 56.7-50.8 80-24 23.3 26.8-0.4 92.5-31 115-30.6 22.5-10.1 27.3-47 10z");
}
</style>
clip-path 搭配 SVG path 制作可缩放形状
虽然透过 path() 可以产生不规则形状,但单纯使用 path() 产生的形状却“无法缩放”,如果要产生可以缩放的形状,就必须透过 SVG 才能实现,首先运用向量绘图软件绘制形状取得路径后,运用 AI 将路径转换成 0~1 之间的“比例”数值,下图透过 ChatGPT 转换路径比例。
接着将下方 SVG 程序码中的路径替换为自己的路径,运用 SVG clipPath 元素中 clipPathUnits="objectBoundingBox" 的属性设置。
<svg height="0" width="0">
<clipPath id="path" clipPathUnits="objectBoundingBox">
<path d="你的形狀路徑"></path>
</clipPath>
</svg>
剪裁路径设定完成后,就能参考下方范例,改用 url() 读取剪裁路径的 id,读取会自动适应宽度的 SVG 剪裁路径,就能让三个尺寸不同的 div,读取画面中尺寸为 0 的 SVG 里头的 path,裁切出来的形状就会按照元素本身尺寸进行缩放。
<!-- HTML 程式碼 -->
<svg height="0" width="0">
<clipPath id="path" clipPathUnits="objectBoundingBox">
<path d="M0.1597,0.5192C0.3311,0,1,0.5018,0.7705,0.6451S0.4239,0.3767,0.3626,0.5836S0,1,0.1597,0.5192z"></path>
</clipPath>
</svg>
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<!-- CSS 程式碼 -->
<style>
div {
background: red;
clip-path: url(#path);
}
.a {
width: 100px;
height: 100px;
}
.b {
width: 200px;
height: 100px;
}
.c {
width: 300px;
height: 100px;
}
</style>
小结
clip-path 是一个非常有趣的样式属性,虽然过去的浏览器对于这个样式的支援度不高,但随着科技的进步,目前大部分浏览器都已经支援,也可以开始使用这个样式属性,做出各种有趣的动画效果!
微信扫码关注
抖音扫码关注