形状 (Shapes) 和 遮罩 (Masking) 的主要属性及其属性值。这些特性允许你改变元素的可见区域形状,或者让内容环绕非矩形区域,以及使用图像或渐变作为遮罩来控制元素的可见部分。
一、 CSS 形状 (CSS Shapes)
CSS Shapes 主要用于让内联内容 (inline content) 能够环绕浮动元素的非矩形轮廓。核心属性是 shape-outside。
-
shape-outside
-
作用: 定义一个形状,内联内容将围绕这个形状进行流动。这个属性通常应用于浮动元素 (float: left 或 right) 。
-
值:
-
none: (默认值) 不应用任何形状,内容按正常矩形边界环绕。
-
<shape-box>: 定义形状的参考框。内容会环绕这个框定义的形状。值可以是:- margin-box: 使用外边距框。
- border-box: 使用边框框。
- padding-box: 使用内边距框。
- content-box: 使用内容框。
- 通常需要与
<basic-shape>或 url() 结合使用,或者单独使用时,如果元素有 border-radius,会基于该圆角创建形状。
-
<basic-shape>: 使用 CSS 基本形状函数来定义形状。- inset(
<top> <right> <bottom> <left> round <border-radius>?): 定义一个矩形(或圆角矩形)的内嵌形状。值可以是长度或百分比。 - circle(
<radius>? at <position>?): 定义一个圆形。<radius>是半径 (长度、百分比、closest-side, farthest-side)。<position>是圆心位置 (类似 background-position)。 - ellipse(
<radius-x> <radius-y>? at <position>?): 定义一个椭圆形。<radius-x/y> 是 X/Y 轴半径。 - polygon(
<fill-rule>?, [<x> <y>]#): 定义一个多边形。提供一系列顶点的 X/Y 坐标(长度或百分比),用逗号分隔。<fill-rule>可选 (nonzero 或 evenodd)。 - path(
<string>): (实验性) 使用 SVG路径数据 (d 属性的值) 定义形状。
- inset(
-
url(
<url>) : 使用一个图像来提取形状。浏览器会分析图像的 alpha 通道 (透明度) 来确定形状区域。可以通过 shape-image-threshold 控制阈值。图像需要满足 CORS 策略才能跨域使用。
-
-
组合: 可以将
<basic-shape>或url()与<shape-box>结合使用,例如shape-outside: circle(50%) margin-box;(基于外边距框创建一个圆形)。 -
示例:
- shape-outside: circle(50%); (创建一个圆形形状)
- shape-outside: ellipse(40% 50%); (创建一个椭圆)
- shape-outside: polygon(0 0, 100% 0, 100% 80%, 50% 100%, 0 80%); (创建一个梯形或房子形状)
- shape-outside: url('shape.png'); (使用图片的 alpha 通道)
- shape-outside: inset(10px 20px 30px 40px round 5px);
-
-
shape-margin
- 作用: 在 shape-outside 定义的形状周围添加一个外边距。内联内容会从这个外边距之外开始环绕。
- 值: 或 。
- 示例: shape-margin: 10px;
-
shape-image-threshold
- 作用: 当使用 shape-outside: url(
<url>) 时,设置用于从图像 alpha 通道提取形状的不透明度阈值。像素的不透明度高于此阈值的部分被视为形状内部。 - 值:
<number>: 从 0.0 (完全透明) 到 1.0 (完全不透明)。默认值为 0.0。 - 示例: shape-image-threshold: 0.5; (只有不透明度大于 50% 的部分才构成形状)
- 作用: 当使用 shape-outside: url(
二、 CSS 遮罩 (CSS Masking)
CSS 遮罩允许你使用图像、渐变或 SVG 来定义一个遮罩层,只有遮罩层非透明的部分对应的元素内容才会显示出来。
-
mask-image
-
作用: 设置用作遮罩层的图像源。可以设置一个或多个遮罩层(逗号分隔)。
-
值:
- none: (默认值) 无遮罩图像。
- url(
<url>): 指定图像文件的 URL。图像的亮度或 alpha 通道(取决于 mask-type)会被用作遮罩。 <gradient>: 使用 CSS 渐变作为遮罩。渐变的颜色亮度或透明度决定遮罩效果。<element>(): (实验性) 使用其他元素作为遮罩。
-
示例: mask-image: url('mask.png');, mask-image: linear-gradient(black, transparent);
-
-
mask-mode
-
作用: 定义 mask-image 是应该被视为亮度遮罩 (luminance mask) 还是 alpha 遮罩 (alpha mask) 。可以为多层遮罩分别设置。
-
值:
- alpha: (默认值,通常情况下) 使用图像的 alpha 通道(透明度)作为遮罩。越不透明,对应元素部分越可见。
- luminance: 使用图像的亮度(灰度值)作为遮罩。越亮(接近白色),对应元素部分越可见;越暗(接近黑色),越不可见。
- match-source: 如果 mask-image 是一个 CSS 类型(如 SVG
<mask>元素引用),则使用该源定义的类型;否则行为同 alpha。
-
示例: mask-mode: luminance;
-
-
mask-repeat
- 作用: 控制遮罩图像如何重复平铺。语法和值与 background-repeat 完全相同。可以为多层遮罩分别设置。
- 值: repeat (默认), repeat-x, repeat-y, no-repeat, space, round。
- 示例: mask-repeat: no-repeat;
-
mask-position (也可以用 mask-position-x, mask-position-y)
- 作用: 设置遮罩图像的初始位置。语法和值与 background-position 完全相同。可以为多层遮罩分别设置。
- 值: 关键字 (top, center, bottom, left, right)、长度、百分比组合。
- 示例: mask-position: center;
-
mask-clip
- 作用: 指定遮罩效果应用的区域(遮罩层本身被裁剪到哪个盒子)。语法和值与 background-clip 类似。可以为多层遮罩分别设置。
- 值: border-box (默认), padding-box, content-box, margin-box, fill-box, stroke-box, view-box, no-clip。
- 示例: mask-clip: content-box;
-
mask-origin
- 作用: 指定 mask-position 的原点(遮罩图像从哪个盒子边缘开始定位)。语法和值与 background-origin 相同。可以为多层遮罩分别设置。
- 值: border-box, padding-box (默认), content-box, margin-box, fill-box, stroke-box, view-box。
- 示例: mask-origin: border-box;
-
mask-size
- 作用: 设置遮罩图像的尺寸。语法和值与 background-size 完全相同。可以为多层遮罩分别设置。
- 值: auto (默认), cover, contain,
<length>,<percentage>及其组合。 - 示例: mask-size: contain;
-
mask-composite
-
作用: 定义当有多个遮罩层时,它们应该如何相互组合。
-
值:
- add: (默认值) 遮罩层效果相加。
- subtract: 上层减去下层。
- intersect: 取上层和下层的交集。
- exclude: 取上层和下层不相交的部分(异或)。
-
示例: mask-composite: intersect;
-
-
mask-type
- 作用: (已并入 mask-mode) 旧规范中用于区分 alpha 和 luminance 遮罩的属性,现在推荐使用 mask-mode。
- 值: luminance, alpha (默认)。
-
mask (简写属性)
- 作用: 在一个声明中设置一个或多个遮罩属性 (mask-image, mask-mode, mask-repeat, mask-position, mask-clip, mask-origin, mask-size, mask-composite)。
- 语法: 类似于 background 简写,可以包含上述属性的值。mask-position 和 mask-size 之间用 / 分隔。
- 重要: 简写会重置未指定的属性为其初始值。
- 示例: mask: url('star.svg') center / contain no-repeat;
三、 剪切路径 (Clipping Path)
剪切路径定义了一个区域,只有区域内的部分元素内容是可见的,区域外的部分会被完全裁剪掉(变得透明)。
-
clip-path
-
作用: 创建一个剪切区域,只有元素在这个区域内的部分才会被渲染。
-
值:
-
none: (默认值) 不应用剪切路径。
-
<clip-source>:- url(
<url>): 使用一个 SVG<clipPath>元素来定义剪切路径。URL 指向 SVG 文件中的<clipPath>元素 ID。
- url(
-
<basic-shape>: 使用 CSS 基本形状函数定义剪切区域(与 shape-outside 的<basic-shape>值相同):- inset(...)
- circle(...)
- ellipse(...)
- polygon(...)
- path(
<string>) (实验性)
-
<geometry-box>: 定义形状函数所参照的盒子。值可以是:- margin-box
- border-box
- padding-box
- content-box
- fill-box (SVG)
- stroke-box (SVG)
- view-box (SVG, 默认)
-
组合: 可以将
<basic-shape>和<geometry-box>结合,如 clip-path: polygon(...) margin-box;。
-
-
示例:
- clip-path: circle(40% at 50% 50%); (裁剪成一个圆形)
- clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); (裁剪成一个菱形)
- clip-path: inset(20px round 10px); (向内裁剪 20px,带 10px 圆角)
- clip-path: url(#myClipPath); (使用 SVG 定义的剪切路径)
-
-
clip (已废弃 - Deprecated)
- 作用: 旧的裁剪属性,只能裁剪绝对定位 (position: absolute 或 fixed) 的元素,并且只能裁剪成矩形。
- 值: auto (默认) 或 rect(
<top>, <right>, <bottom>, <left>)。 - 强烈不推荐使用,应使用 clip-path 替代。
总结:
- CSS Shapes (shape-outside) 主要影响浮动元素周围内容的环绕方式。
- CSS Masking (mask-*) 使用图像或渐变作为遮罩,控制元素自身哪些部分可见。
- CSS Clipping (clip-path) 定义一个硬性边界,裁剪掉边界之外的元素自身内容。
案例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS 形状、遮罩与剪切示例</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>CSS 形状 (Shapes), 遮罩 (Masking) 与剪切 (Clipping) 演示</h1>
<!-- 示例 1: CSS Shapes (shape-outside) -->
<section class="container">
<h2>CSS 形状 (<code>shape-outside</code>) - 文字环绕</h2>
<div class="shape-container">
<div class="shape shape-circle"></div>
<p>这段文字将环绕左侧浮动的圆形。Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<div class="shape-container">
<div class="shape shape-polygon"></div>
<p>这段文字将环绕左侧浮动的多边形(梯形)。Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis risus a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue, eros est euismod turpis, id tincidunt sapien risus a quam.</p>
</div>
<div class="shape-container">
<div class="shape shape-image"></div>
<p>这段文字将环绕基于图像 alpha 通道的形状。需要图像满足 CORS 策略或同源。Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus blandit dui, id egestas quam mauris ut lacus. Donec leo, vivamus fermentum nibh in augue praesent a lacus at urna congue rutrum. Nulla enim eros, porttitor eu, tempus id, varius non, nibh.</p>
</div>
</section>
<!-- 示例 2: CSS Masking (mask-*) -->
<section class="container">
<h2>CSS 遮罩 (<code>mask-*</code>)</h2>
<div class="mask-grid">
<div class="masked-element mask-gradient">
<p>使用<br>渐变<br>遮罩</p>
</div>
<div class="masked-element mask-image-star">
<p>使用<br>星形<br>遮罩</p>
</div>
<div class="masked-element mask-image-text">
<p>使用<br>SVG文字<br>遮罩</p>
</div>
<div class="masked-element mask-multiple">
<p>使用<br>多个<br>遮罩</p>
</div>
</div>
</section>
<!-- 示例 3: CSS Clipping Path (clip-path) -->
<section class="container">
<h2>CSS 剪切路径 (<code>clip-path</code>)</h2>
<div class="clipping-grid">
<div class="clipped-element clip-circle">圆形剪切</div>
<div class="clipped-element clip-ellipse">椭圆剪切</div>
<div class="clipped-element clip-polygon">多边形剪切</div>
<div class="clipped-element clip-inset">内嵌矩形剪切</div>
</div>
</section>
<!-- 用于遮罩和形状的 SVG 资源 -->
<svg width="0" height="0" style="position:absolute;z-index:-1;">
<defs>
<!-- 用于遮罩的星形 -->
<mask id="star-mask">
<polygon points="50,0 61.8,38.2 100,38.2 69.1,61.8 80.9,100 50,76.4 19.1,100 30.9,61.8 0,38.2 38.2,38.2" fill="white"/>
<!-- 遮罩中白色代表可见,黑色代表不可见 -->
</mask>
<!-- 用于遮罩的文字 -->
<mask id="text-mask">
<rect width="100%" height="100%" fill="black"/> <!-- 背景设为黑色(不可见) -->
<text x="50%" y="50%" dy=".3em" text-anchor="middle" font-size="40" font-weight="bold" fill="white">MASK</text> <!-- 文字设为白色(可见) -->
</mask>
<!-- 用于 clip-path 的 SVG 路径 -->
<!-- (clip-path: url() 示例暂时省略,因其设置相对复杂) -->
</defs>
</svg>
</body>
</html>
body {
font-family: sans-serif;
line-height: 1.6;
margin: 20px;
color: #333;
background-color: #f4f4f4;
}
h1, h2 {
text-align: center;
color: #333;
margin-bottom: 30px;
}
h2 { margin-top: 40px; border-bottom: 1px solid #ccc; padding-bottom: 10px; text-align: left;}
.container {
background-color: #fff;
padding: 20px;
margin-bottom: 30px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
overflow: hidden; /* 清除浮动或防止内容溢出影响布局 */
}
/* --- 示例 1: CSS Shapes --- */
.shape-container {
margin-bottom: 30px;
overflow: hidden; /* 包含浮动 */
border-bottom: 1px dashed #eee;
padding-bottom: 20px;
}
.shape-container p {
text-align: justify; /* 两端对齐效果更好 */
color: #555;
}
.shape {
float: left; /* 关键:shape-outside 通常应用于浮动元素 */
width: 120px;
height: 120px;
margin-right: 20px; /* 形状和文字之间的距离 */
margin-bottom: 10px; /* 底部留点空间 */
background-color: lightcoral; /* 形状的背景色 */
}
.shape-circle {
shape-outside: circle(50%); /* 定义圆形形状 */
clip-path: circle(50%); /* 同时将元素本身裁剪成圆形 */
/* 或者 border-radius: 50%; */
}
.shape-polygon {
/* 定义一个梯形或类似房子的多边形 */
/* 顶点坐标: 左上(0,0), 右上(100%,0), 右下偏内(100%,80%), 中下(50%,100%), 左下偏内(0,80%) */
shape-outside: polygon(0 0, 100% 0, 100% 80%, 50% 100%, 0 80%);
clip-path: polygon(0 0, 100% 0, 100% 80%, 50% 100%, 0 80%);
}
.shape-image {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path fill="lightcoral" d="M50,0 L100,100 L0,100 Z" /></svg>'); /* 使用一个带透明区域的SVG做背景 */
background-color: transparent; /* 背景设为透明 */
background-size: contain;
background-repeat: no-repeat;
/* 使用图像的 alpha 通道来定义形状 */
shape-outside: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path fill="lightcoral" d="M50,0 L100,100 L0,100 Z" /></svg>');
shape-image-threshold: 0.1; /* 不透明度大于 10% 的部分构成形状 */
shape-margin: 10px; /* 在形状外添加 10px 边距 */
}
/* --- 示例 2: CSS Masking --- */
.mask-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 20px;
text-align: center;
}
.masked-element {
width: 150px;
height: 150px;
background: linear-gradient(45deg, #f06, #9f6); /* 用渐变填充元素 */
color: white;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
margin: 0 auto; /* 网格内居中 */
}
.mask-gradient {
mask-image: linear-gradient(to bottom, black 60%, transparent 100%); /* 底部渐隐 */
/* mask-mode 默认为 alpha,这里渐变颜色只有黑白,透明度决定遮罩 */
}
.mask-image-star {
/* 使用 SVG 中定义的星形遮罩 */
mask-image: url(#star-mask);
mask-size: contain; /* 遮罩适应元素大小 */
mask-repeat: no-repeat;
mask-position: center;
}
.mask-image-text {
/* 使用 SVG 中定义的文字遮罩 */
mask-image: url(#text-mask);
mask-size: cover; /* 遮罩覆盖元素 */
mask-repeat: no-repeat;
mask-position: center;
}
.mask-multiple {
/* 叠加两个遮罩:一个圆形,一个从左到右的渐变 */
mask-image: radial-gradient(circle at 30% 30%, black 30%, transparent 31%),
linear-gradient(to right, black 50%, transparent 51%);
mask-size: 60% 60%, 100% 100%; /* 分别设置大小 */
mask-position: top left, top left; /* 分别设置位置 */
mask-repeat: no-repeat, no-repeat;
mask-composite: subtract; /* 组合模式:渐变减去圆形 */
/* 试试 add, intersect, exclude */
}
/* --- 示例 3: CSS Clipping Path --- */
.clipping-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 20px;
text-align: center;
}
.clipped-element {
width: 150px;
height: 150px;
background-color: dodgerblue;
background-image: url('https://picsum.photos/id/10/150/150'); /* 加个背景图看效果 */
background-size: cover;
color: white;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
margin: 0 auto;
transition: clip-path 0.3s ease; /* 给剪切路径加过渡 */
}
.clipped-element:hover {
clip-path: none; /* 悬停时移除剪切 */
}
.clip-circle {
/* 裁剪成一个半径为 40% 的圆,中心在 50% 50% */
clip-path: circle(40% at center);
}
.clip-ellipse {
/* 裁剪成一个椭圆,X轴半径 50%,Y轴半径 30% */
clip-path: ellipse(50% 30% at center);
}
.clip-polygon {
/* 裁剪成一个五角星形状 */
clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}
.clip-inset {
/* 向内裁剪,上10px,右20px,下30px,左40px,带5px圆角 */
clip-path: inset(10px 20px 30px 40px round 5px);
}