第七章:CSS 视觉魔法:从阴影、渐变到滤镜
摘要: 恭喜您已经掌握了 CSS 布局!在本章中,我们将开启一段充满创造力的旅程,深入探索 CSS 提供的丰富视觉效果。您将学习如何控制元素的可见性与透明度,如何使用阴影为页面增添立体感,如何用渐变创造绚丽的背景,以及如何像使用 Photoshop 一样,通过滤镜 (filter
) 实时处理元素的视觉表现。本章将是您从“结构工程师”向“视觉设计师”转变的关键一步。
在本章的学习地图中,我们将:
- 首先,学习如何控制元素的显隐与透明,这是实现动态 UI 的基础。
- 接着,我们将掌握阴影效果,为元素和文本赋予深度和立体感。
- 然后,我们将深入探索渐变背景,创造出比单色背景更丰富、更具吸引力的视觉效果。
- 之后,我们将解锁强大的
filter
(滤镜) 属性,实现以往需要制图软件才能完成的特效。 - 最后,我们会学习一些其他实用的 UI 属性,并用一个综合实战案例来巩固所有知识。
7.1. 显隐与透明:控制元素状态
7.1.1. visibility
属性
visibility
属性用于设置元素是否可见。它与 display: none;
的核心区别在于:
visibility: hidden;
: 元素被隐藏,但在页面布局中依然占据着它原来的空间,就像一个“隐形”的占位符。display: none;
: 元素被彻底隐藏,并且从文档流中移除,不占据任何空间。
值 | 描述 |
---|
visible | 默认值,元素可见。 |
hidden | 元素不可见,但仍占据空间。 |
collapse | 主要用于表格行/列,效果类似 hidden 。 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>响应式 Grid 布局</title> <style> .visibility-demo { border: 2px dashed #ccc; padding: 10px; } .visibility-demo div { display: inline-block; width: 100px; height: 100px; background: #add8e6; } .hide-by-visibility { visibility: hidden; } .hide-by-display { display: none !important; } </style> </head>
<body> <strong>visibility: hidden (中间盒子隐身但仍占位)</strong> <div class="visibility-demo"> <div>Box 1</div> <div class="hide-by-visibility">Box 2</div> <div>Box 3</div> </div> <br><br> <strong>display: none (中间盒子彻底消失)</strong> <div class="visibility-demo"> <div>Box 1</div> <div class="hide-by-display">Box 2</div> <div>Box 3</div> </div> </body>
</html>
|
7.1.2. opacity
属性
opacity
属性用于设置一个元素的透明度,值从 0.0
(完全透明) 到 1.0
(完全不透明)。
重要: opacity
会影响元素本身及其所有子元素。如果你只想让背景半透明而文字保持清晰,应该在第五章学过的 background-color: rgba(...)
。
1 2 3 4 5 6 7 8 9 10 11 12
| <style> .opacity-demo { background-color: #2980b9; color: white; padding: 20px; opacity: 0.6; } </style> <div class="opacity-demo"> <h3>标题和段落</h3> <p>这段文字也继承了父元素的透明度,变得有些模糊。</p> </div>
|
7.2. 阴影效果:box-shadow
与 text-shadow
7.2.1. 盒子阴影 (box-shadow
)
为元素添加阴影是增加页面深度感和层次感最有效的方式之一。
语法: box-shadow: <h-offset> <v-offset> <blur> <spread> <color> <inset>;
- h-offset: 水平偏移量 (正值向右)。
- v-offset: 垂直偏移量 (正值向下)。
- blur: 模糊半径 (值越大越模糊)。
- spread: 扩散半径 (正值使阴影扩大)。
- color: 阴影颜色。
- inset: 将外部阴影变为内部阴影。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <style> .shadow-container { display: flex; justify-content: space-around; padding: 20px; background-color: #f4f4f4; } .shadow-box { width: 100px; height: 100px; background-color: white; display: grid; place-items: center; } .s1 { box-shadow: 5px 5px 0px 0px #aaa; } .s2 { box-shadow: 5px 5px 15px 0px #aaa; } .s3 { box-shadow: 0px 0px 15px 5px #aaa; } .s4 { box-shadow: inset 0px 0px 15px 0px #aaa; } </style> <div class="shadow-container"> <div class="shadow-box s1">硬阴影</div> <div class="shadow-box s2">模糊阴影</div> <div class="shadow-box s3">扩散阴影</div> <div class="shadow-box s4">内阴影</div> </div>
|
7.2.2. 文本阴影 (text-shadow
)
text-shadow
的语法更简单,但通过叠加多层阴影,可以创造出惊艳的效果。
语法: text-shadow: <h-offset> <v-offset> <blur> <color>;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <style> .text-shadow-demo h1 { font-size: 50px; text-align: center; padding: 20px; font-family: sans-serif; } .ts1 { background: #333; color: white; text-shadow: 2px 2px 5px black; } .ts2 { background: #2c3e50; color: #4dd0e1; text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 20px #00aeff, 0 0 30px #00aeff; } </style> <div class="text-shadow-demo"> <h1 class="ts1">简单文本阴影</h1> <h1 class="ts2">霓虹灯效果</h1> </div>
|
7.3. 渐变背景 (Gradients)
使用 CSS 渐变可以创建平滑的颜色过渡,替代过去需要用图片才能实现的背景效果。
7.3.1. 线性渐变 (linear-gradient
)
沿直线创建颜色渐变。
1 2 3 4 5 6 7 8 9 10 11
| <style> .gradient-box { width: 22%; height: 100px; float: left; margin: 1.5%; } .lg1 { background: linear-gradient(#3498db, #2980b9); } .lg2 { background: linear-gradient(to right, #e74c3c, #c0392b); } .lg3 { background: linear-gradient(45deg, #f1c40f, #f39c12); } .lg4 { background: linear-gradient(to right, #e74c3c, #f1c40f, #2ecc71); } </style> <div class="gradient-box lg1"></div> <div class="gradient-box lg2"></div> <div class="gradient-box lg3"></div> <div class="gradient-box lg4"></div>
|
其他的渐变语法我们开发中不会太常用,为了避免知识点罗列我们就略过了
7.4. 滤镜 (filter
):CSS 中的 Photoshop
filter
属性可以将各种图形效果应用于元素,就像在 Photoshop 中使用滤镜一样。
函数 | 核心描述 |
---|
blur(px) | 高斯模糊 |
brightness(%) | 亮度 |
contrast(%) | 对比度 |
grayscale(%) | 灰度(黑白) |
invert(%) | 反相 |
saturate(%) | 饱和度 |
sepia(%) | 褐色(复古) |
hue-rotate(deg) | 色相旋转 |
drop-shadow(...) | (常用) 投射阴影 |
7.4.1. 实战:创建交互式图片效果
任务: 创建一个图片廊,默认显示为灰度图片,当鼠标悬停时,平滑地恢复原彩并放大。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <style> .gallery img { width: 200px; margin: 10px; border-radius: 8px; filter: grayscale(100%); transition: all 0.3s ease-in-out; } .gallery img:hover { filter: grayscale(0%); transform: scale(1.1); } </style> <div class="gallery"> <img src="https://picsum.photos/seed/gallery1/400/300"> <img src="https://picsum.photos/seed/gallery2/400/300"> <img src="https://picsum.photos/seed/gallery3/400/300"> </div>
|
7.4.2. drop-shadow()
vs box-shadow
这是两个非常容易混淆的属性,但区别巨大:
box-shadow
: 为元素的矩形边框盒添加阴影。filter: drop-shadow()
: 为元素内容的实际轮廓(包括 PNG 的透明部分)智能地添加阴影。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>响应式 Grid 布局</title> <style> .shadow-compare { display: flex; justify-content: space-around; align-items: center; background: #f4f4f4; padding: 20px; } .shadow-compare img { width: 100px; } .bs-shadow { box-shadow: 10px 10px 10px rgba(0,0,0,0.5); } .ds-shadow { filter: drop-shadow(10px 10px 10px rgba(0,0,0,0.5)); } </style> </head>
<body> <div class="shadow-compare"> <div> <p>box-shadow:</p> <img class="bs-shadow" src="https://picsum.photos/100/100?random=1"> </div> <div> <p>drop-shadow:</p> <img class="ds-shadow" src="https://picsum.photos/100/100?random=2"> </div> </div> </body>
</html>
|
7.5. 裁剪与蒙版:塑造元素的可见区域
摘要: 本节我们将学习两个强大的视觉特效属性:clip-path
和 mask
。您将学习如何使用 clip-path
将元素裁剪成圆形、多边形等任意形状,打破矩形的束缚。同时,我们还将探索如何利用 mask-image
,通过一张图片或渐变来控制元素的像素级可见性,创造出丰富的淡入淡出和镂空效果。
7.5.1. 裁剪路径 (clip-path
)
clip-path
属性通过定义一个裁剪区域,来决定元素的哪一部分是可见的。区域内的部分会被显示,区域外的部分则会被彻底“剪掉”,变得不可见。
在旧的 CSS 版本中曾有一个 clip
属性,但它功能有限且已被废弃。clip-path
是其现代的、功能强大的替代品。
函数 | 核心描述 & 参数解析 |
---|
circle() | 创建圆形。参数为 (半径 at 圆心位置) 。 示例: circle(50% at center) |
ellipse() | 创建椭圆形。参数为 (水平半径 垂直半径 at 中心位置) 。 示例: ellipse(50% 30% at center) |
inset() | 创建内凹矩形。参数为 (内凹值 round 圆角) 。 内凹值遵循 margin 简写,round 可选。 示例: inset(10% 10% round 20px) |
polygon() | (最强大) 用一系列 X Y 坐标点创建任意多边形。 至少需要三个点。 示例 (三角形): polygon(50% 0, 100% 100%, 0 100%) |
url() | 使用一个外部 SVG <clipPath> 元素的 id 作为裁剪路径。 用于实现复杂图形。 示例: url(#my-clip-path) |
- 语法: polygon(x1 y1, x2 y2, x3 y3, …)
- 坐标点: 每一对 x y 值都代表多边形的一个顶点(角)。坐标 0 0 是左上角。
- 至少需要 3 对坐标点才能构成一个面(三角形)。
- 浏览器会自动将最后一个点与第一个点连接起来,形成一个封闭的图形
对于polygon的使用,强烈推荐您收藏 Clippy — CSS clip-path 生成器 网站,他能够快速的帮你创建您几乎所有想创建的图形
实战: 将同一张图片裁剪成不同的形状。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <style> .clip-gallery { display: flex; justify-content: space-around; align-items: center; flex-wrap: wrap; gap: 20px; } .clip-gallery img { width: 150px; height: 150px; object-fit: cover; transition: all 0.3s ease; } .clip-circle { clip-path: circle(50%); } .clip-inset { clip-path: inset(10% 10% round 20px); } .clip-polygon { clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); } .clip-gallery img:hover { transform: scale(1.1); filter: brightness(1.1); } </style> <div class="clip-gallery"> <div> <p>圆形 (circle)</p> <img class="clip-circle" src="https://picsum.photos/seed/clip/300/300"> </div> <div> <p>内凹 (inset)</p> <img class="clip-inset" src="https://picsum.photos/seed/clip/300/300"> </div> <div> <p>多边形 (polygon)</p> <img class="clip-polygon" src="https://picsum.photos/seed/clip/300/300"> </div> </div>
|
7.5.2. 蒙版 (mask
):像素级的视觉控制器
与 clip-path
的硬性裁剪不同,mask
提供了一种更精细、更具艺术性的方式来控制元素的可见性。它不是“剪掉”,而是像透过一块有图案的毛玻璃看东西,玻璃上透明或亮的地方,我们就能看到东西;不透明或暗的地方,东西就被遮挡了。
核心 mask
属性三巨头
在使用蒙版时,我们最先需要掌握的是这三个最核心的属性,它们决定了蒙版的基础形态。
mask-image
(定义蒙版源): 这是最重要的属性,它指定了用作“毛玻璃”的图案。这个图案可以是一张带透明通道的 url()
图片,也可以是一个 CSS 渐变。mask-size
(控制蒙版尺寸): 控制蒙版图案的大小,用法与 background-size
完全相同,contain
和 cover
是最常用的值。mask-repeat
(控制蒙版平铺): 控制蒙版图案是否重复,用法与 background-repeat
完全相同。对于形状遮罩,我们通常使用 no-repeat
。
实战一:SVG 形状蒙版
任务: 将一张头像图片,通过一个五角星形状的 SVG 文件进行遮罩,使其呈现为五角星形状。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <style> .star-mask { width: 300px; height: 300px; } .star-mask img { width: 100%; height: 100%; object-fit: cover; -webkit-mask-image: url('https://mdn.github.io/css-examples/masking/star.svg'); mask-image: url('https://mdn.github.io/css-examples/masking/star.svg'); -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; -webkit-mask-position: center; mask-position: center; -webkit-mask-size: contain; mask-size: contain; } </style> <div class="star-mask"> <img src="https://q7.itc.cn/q_70/images03/20240614/e18a3ca14f82467ba63e93c1cce681ee.jpeg" alt="Profile Picture" /> </div>
|
实战二:渐变蒙版 (淡出效果)
这是 mask
最巧妙的应用之一。我们无需任何图片,仅用 CSS 渐变就可以创造出优雅的淡出效果。
任务: 为一张图片的底部创造出“淡出至透明”的效果。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <style> .fade-out-mask { width: 300px; height: 200px; background-image: url(https://picsum.photos/seed/gradient-mask/400/300); background-size: cover; -webkit-mask-image: linear-gradient(to bottom, black 50%, transparent 100%); mask-image: linear-gradient(to bottom, black 50%, transparent 100%); } </style> <div class="fade-out-mask"></div>
|
微调与进阶属性详解
在掌握了 mask-image
等核心属性后,我们可以通过以下属性,像控制背景图一样,对蒙版进行更精细的调整。
1. mask-position
: 定义蒙版位置
此属性用于设置 mask-image
在元素内的起始位置,其用法与 background-position
完全相同。
值 | 描述 |
---|
关键字 | top , bottom , left , right , center 的组合 |
<percentage> / <length> | 使用百分比或 px 等单位设置 X Y 坐标 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <style> .position-demo { width: 300px; height: 200px; background-image: linear-gradient(45deg, #84fab0 0%, #8fd3f4 100%);
-webkit-mask-image: url('https://mdn.github.io/css-examples/masking/star.svg'); mask-image: url('https://mdn.github.io/css-examples/masking/star.svg'); -webkit-mask-size: 80px 80px; mask-size: 80px 80px; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
-webkit-mask-position: top right; mask-position: top right; } </style> <div class="position-demo"></div>
|
2. mask-origin
与 mask-clip
: 定义蒙版原点与裁剪区域
这两个属性共同决定了蒙版的作用范围,它们的参照物都是元素的盒模型(border-box
, padding-box
, content-box
)。
mask-origin
: 定义 mask-position
的 0 0
坐标从哪里开始计算。mask-clip
: 定义蒙版效果在哪里被裁剪。
值 | 描述 |
---|
border-box | 默认值。从边框的外边缘开始计算/裁剪。 |
padding-box | 从内边距的外边缘(即边框的内边缘)开始计算/裁剪。 |
content-box | 从内容区的边缘开始计算/裁剪。 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <style> .box-model-mask { width: 250px; height: 150px; padding: 20px; border: 10px dashed #ccc; background-color: #3498db;
-webkit-mask-image: linear-gradient(45deg, black, transparent); mask-image: linear-gradient(45deg, black, transparent);
-webkit-mask-origin: padding-box; mask-origin: padding-box; -webkit-mask-clip: content-box; mask-clip: content-box; } </style> <div class="box-model-mask"></div>
|
在示例中,mask-origin: padding-box
让渐变蒙版的左上角从内边距区域开始,而 mask-clip: content-box
则让蒙版的效果只在内容区内生效,不影响内边距和边框。
7.6. 其他实用 UI 属性
7.6.1. resize
属性
允许用户通过拖动来缩放元素的尺寸。
resize
属性需要与 overflow
属性(值为 auto
, hidden
或 scroll
)结合使用才有效。
1 2 3 4 5 6 7 8 9 10 11
| <style> textarea.resizable { resize: both; overflow: auto; border: 1px solid #ccc; padding: 5px; width: 300px; height: 100px; } </style> <textarea class="resizable">你可以拖动右下角来调整我的大小。</textarea>
|
7.6.2. cursor
属性:改变鼠标指针
cursor
属性用于定义当鼠标指针悬停在元素上时所显示的图标样式。为可交互元素设置正确的鼠标指针,是提升用户体验、提供明确视觉线索的关键。在浏览网页的过程中,当我们将鼠标移动到一些元素上时,鼠标的样式会发生相应的改变,例如当鼠标指向文本时,鼠标的样式会变成类似大写字母I
的样子;当鼠标指向链接时,鼠标会变成一个小手的形状等。
除了这些默认的变化外,您还可以通过 CSS 中的 cursor 属性来改变网页中鼠标(光标)的样式,下表中列举了 cursor 属性的可选值:
属性值 | 示意图 | 描述 |
---|
auto | | 默认值,由浏览器根据当前上下文确定要显示的光标样式 |
default |  | 默认光标,不考虑上下文,通常是一个箭头 |
none | | 不显示光标 |
initial | | 将此属性设置为其默认值 |
inherit | | 从父元素基础 cursor 属性的值 |
context-menu |  | 表示上下文菜单可用 |
help |  | 表示有帮助 |
pointer |  | 表示一个链接 |
progress |  | 进度指示器,表示程序正在执行一些处理,但是您仍然可以在该界面进行一些操作(与 wait 不同) |
wait |  | 表示程序繁忙,您应该等待程序指向完成 |
cell |  | 表示可以选择一个单元格(或一组单元格) |
crosshair |  | 一个简单的十字准线 |
text |  | 表示可以选择的文本 |
vertical-text |  | 表示可以选择的垂直文本 |
alias |  | 表示要创建别名或快捷方式 |
copy |  | 表示可以复制某些内容 |
move |  | 表示可以移动鼠标下方的对象 |
no-drop |  | 表示所拖动的项目不能放置在当前位置 |
not-allowed |  | 表示无法完成某事 |
all-scroll |  | 表示对象可以沿任何方向滚动(平移) |
col-resize |  | 表示可以水平调整列的大小 |
row-resize |  | 表示可以垂直调整行的大小 |
n-resize |  | 表示对象的边缘可以向上(向北)移动 |
e-resize |  | 表示对象的边缘可以向右(向东)移动 |
s-resize |  | 表示对象的边缘可以向下(向南)移动 |
w-resize |  | 表示对象的边缘可以向左(向西)移动 |
ne-resize |  | 表示对象的边缘可以向上和向右(北/东)移动 |
nw-resize |  | 表示对象的边缘可以向上和向左(北/西)移动 |
se-resize |  | 表示对象的边缘可以向下和向右(向南/向东)移动 |
sw-resize |  | 表示对象的边缘可以向下和向左(南/西)移动 |
ew-resize |  | 表示可以双向调整对象大小的光标 |
ns-resize |  | |
nesw-resize |  | |
nwse-resize |  | |
zoom-in |  | 表示可以放大某些内容 |
zoom-out |  | 表示可以缩小某些内容 |
grab |  | 表示可以抓取(拖动)某些东西 |
grabbing |  | 表示已经抓取到某些东西 |
url(“”) | | 自定义光标的样式,括号中的内容为光标图像的源文件路径 |
自定义光标样式
除了可以使用上表中介绍的光标样式外,您也可以使用图像文件来自定义光标的样式,如下所示:
1 2
| cursor: url("custom.gif"), url("custom.cur"), default;
|
提示:.cur 格式是光标文件的标准格式,您可以使用一些在线工具(例如 https://convertio.co/zh/cur-converter/)将 .jpg、.gif 等格式的图像文件转换为 .cur 格式。
实战: 为不同功能的元素设置对应的鼠标指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <style> .cursor-demo-area { display: flex; flex-wrap: wrap; gap: 15px; font-family: sans-serif; } .cursor-box { width: 120px; height: 80px; border: 1px solid #ccc; border-radius: 5px; display: grid; place-items: center; background: #f9f9f9; }
.c-pointer { cursor: pointer; background: #e3f2fd; } .c-help { cursor: help; } .c-move { cursor: move; } .c-not-allowed { cursor: not-allowed; color: #999; background: #eee; } .c-text { cursor: text; } .c-wait { cursor: wait; } </style> <div class="cursor-demo-area"> <div class="cursor-box c-pointer">pointer</div> <div class="cursor-box c-help">help</div> <div class="cursor-box c-move">move</div> <div class="cursor-box c-not-allowed">not-allowed</div> <div class="cursor-box c-text">text</div> <div class="cursor-box c-wait">wait</div> </div>
|
7.7. 本章核心速查总结与实战
分类 | 关键项 | 核心描述 |
---|
显隐 | visibility: hidden | 隐藏元素,但保留其布局空间。 |
| display: none | 隐藏元素,并移除其布局空间。 |
透明度 | opacity: 0.5 | 整个元素(包括子元素)都变半透明。 |
| background: rgba() | (推荐) 仅背景半透明。 |
阴影 | box-shadow | 为元素的矩形盒子添加阴影。 |
| filter: drop-shadow() | 为元素内容的实际轮廓添加阴影。 |
渐变 | linear-gradient() | 线性渐变。 |
| radial-gradient() | 径向渐变。 |
滤镜 | filter | blur() , grayscale() 等,实现 Photoshop 级特效。 |
综合实战:创建“毛玻璃”效果卡片
“毛玻璃” (Glassmorphism) 是现代 UI 设计中非常流行的效果,它模拟了透过磨砂玻璃看背景的观感。
核心属性: backdrop-filter
backdrop-filter
是一个特殊的属性,它不对元素本身应用滤镜,而是对其背后区域的内容应用滤镜。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>测试</title> <style> .glass-container { display: grid; place-items: center; margin: 40px auto; height: 400px; border-radius: 10px; background-image: url(https://picsum.photos/seed/glass/600/400); background-size: cover; }
.glass-card { width: 300px; height: 200px; background-color: rgba(255, 255, 255, 0.2); backdrop-filter: blur(10px); border-radius: 15px; border: 1px solid rgba(255, 255, 255, 0.3); box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
color: white; display: grid; place-items: center; font-size: 24px; text-shadow: 1px 1px 5px black; } </style> </head>
<body> <div class="glass-container"> <div class="glass-card"> Glassmorphism </div> </div> </body>
</html>
|