在日常前端开发中,我们经常会遇到一些看起来很简单,但处理起来又有点麻烦的问题:

图标太小,不容易点击
图片尺寸不统一,导致布局错乱
SVG 颜色不好控制
页面滚动到锚点后被顶部导航遮挡
想实现毛玻璃效果,却发现元素本身也被模糊了
想给不规则 PNG 添加阴影,却只能得到矩形阴影
很多时候,这些问题并不需要引入 JavaScript,也不需要额外的库,只需要几个容易被忽略的 CSS 属性就能轻松解决。

下面整理了 17 个项目中非常实用的 CSS 技巧,建议收藏备用。

一、最值得掌握的几个 CSS 技巧
1. 增大元素的点击热区
在移动端页面或工具栏中,图标的视觉尺寸可能只有 16px 或 24px,如果直接点击图标,操作体验往往不太好。

最直接的方法是增加元素宽高,但这样容易影响布局。更推荐使用伪元素扩大点击区域。

.like-button {
position: relative;
}

.like-button::before {
content: "";
position: absolute;
inset: -12px;
border-radius: 50%;
}
伪元素会把按钮四周的点击区域分别扩大 12px,而不会影响页面布局。

注意:伪元素必须属于可点击元素,点击事件会正常传递给 .like-button。

示例:

https://code.juejin.cn/pen/7308632485130240050

另一种简单写法:

.like-button {
padding: 12px;
margin: -12px;
}
不过负 margin 可能影响布局、滚动区域以及点击关系,使用前建议充分测试。

React Native 中可以直接使用:

<Pressable
hitSlop={{
top: 12,
right: 12,
bottom: 12,
left: 12,
}}
>
<Icon />
</Pressable>
2. 使用 :has() 根据子元素控制父元素
过去,CSS 很难根据子元素的状态修改父元素样式,通常需要 JavaScript。

现在可以直接使用 :has():

.form-item:has(input:focus) {
border-color: #1677ff;
}
更多场景:

根据错误信息修改样式:

.form-item:has(.error-message) {
border-color: red;
}
根据复选框状态修改父元素:

.option:has(input:checked) {
background: #e6f4ff;
border-color: #1677ff;
}
判断是否包含图片:

.card:has(img) {
padding-top: 0;
}
和相邻选择器结合:

label:has(+ input:required)::after {
content: "*";
color: red;
}
3. 使用 currentColor 让 SVG 自动继承文字颜色
currentColor 表示当前元素的 color 属性值。

.button {
color: #666;
}

.button:hover {
color: #1677ff;
}

.button svg {
fill: currentColor;
}
<button class="button">
<svg viewBox="0 0 24 24">
<path d="..." />
</svg>
收藏
</button>
鼠标悬停时,文字和 SVG 会一起变色,无需单独修改 SVG 颜色。

对于描边图标:

svg {
stroke: currentColor;
}
4. 使用 drop-shadow() 给透明 PNG 添加自然阴影
很多人不知道:

box-shadow

filter: drop-shadow()
完全不是同一种阴影。

普通阴影:

.logo {
box-shadow: 0 8px 20px rgb(0 0 0 / 20%);
}
透明 PNG:

.logo {
filter: drop-shadow(0 8px 12px rgb(0 0 0 / 25%));
}
区别:

/* 根据矩形盒模型生成阴影 */
box-shadow: 0 8px 20px rgb(0 0 0 / 20%);

/* 根据图片真实轮廓生成阴影 */
filter: drop-shadow(0 8px 20px rgb(0 0 0 / 20%));
适用于:

SVG
Logo
商品抠图
透明 PNG
5. 使用 scroll-margin-top 避免锚点被导航栏遮挡
很多文档站都会遇到这个问题。

.header {
position: fixed;
top: 0;
height: 64px;
}
点击锚点:

<a href="#install">安装方式</a>

<section id="install" class="article-section">
</section>
解决办法:

.article-section {
scroll-margin-top: 80px;
}
整个页面统一偏移也可以:

html {
scroll-padding-top: 80px;
}
区别:

scroll-margin-top:作用于目标元素
scroll-padding-top:作用于滚动容器
二、图片与布局
6. 使用 object-fit 控制图片裁剪
图片尺寸不一致时,直接指定宽高容易被拉伸。

img {
width: 300px;
height: 200px;
object-fit: cover;
}
常见值:

cover:填满容器,超出部分裁剪
contain:完整显示,可能留白
控制裁剪位置:

img {
object-fit: cover;
object-position: center top;
}
7. 使用 aspect-ratio 保持宽高比
以前需要:

padding-top: 56.25%;
现在:

.video {
aspect-ratio: 16 / 9;
}
简单很多。

8. 使用 clamp() 实现响应式尺寸
.title {
font-size: clamp(24px, 5vw, 64px);
}
还可以用于:

.section {
padding-inline: clamp(16px, 5vw, 80px);
}
.card {
width: clamp(280px, 50vw, 600px);
}
相比大量媒体查询更加简洁。

9. clip-path 和 mask 有什么区别?
clip-path 更适合几何裁剪:

.avatar {
clip-path: circle(50%);
}
三角形:

.triangle {
clip-path: polygon(50% 0,100% 100%,0 100%);
}
六边形:

.hexagon {
clip-path: polygon(
25% 0,
75% 0,
100% 50%,
75% 100%,
25% 100%,
0 50%
);
}
mask 更适合图片、透明度和渐变裁剪:

.icon {
background: currentColor;
mask: url(icon.svg) center/contain no-repeat;
-webkit-mask: url(icon.svg) center/contain no-repeat;
}
渐隐:

.content {
mask-image: linear-gradient(
to bottom,
black 70%,
transparent
);
}
简单理解:

clip-path:裁几何图形
mask:裁图片和透明效果
10. 使用 column-count 实现多栏布局
.article {
column-count: 2;
}
列间距:

.article {
column-count: 2;
column-gap: 32px;
}
更推荐:

.article {
column-width: 320px;
column-gap: 32px;
}
浏览器会自动决定列数,更适合响应式布局。

三、视觉效果
11. 使用 backdrop-filter 实现真正的毛玻璃
很多人会误写成:

filter: blur(12px);
结果整个元素包括文字都模糊了。

正确写法:

.glass {
background: rgb(255 255 255 / 60%);
backdrop-filter: blur(12px);
}
注意:

backdrop-filter 模糊的是元素后面的内容,而不是元素本身,因此通常需要半透明背景。

12. 一行 CSS,把 SVG 或 PNG 图标变成黑色或白色
变黑:

img {
filter: brightness(0);
}
变白:

img {
filter: brightness(0) invert(1);
}
适用于:

SVG
Logo
单色图标
深色模式切换
不适用于照片或复杂渐变图片。

13. 使用 mix-blend-mode 实现混合效果
.hero-title {
color: white;
mix-blend-mode: difference;
}
文字会根据背景自动产生反差。

常见模式:

mix-blend-mode: multiply;
mix-blend-mode: screen;
mix-blend-mode: overlay;
mix-blend-mode: difference;
mix-blend-mode: exclusion;
复杂页面建议:

.container {
isolation: isolate;
}
四、交互体验优化
14. 使用 pointer-events 实现事件穿透
.overlay {
pointer-events: none;
}
让元素显示,但不接收点击事件。

如果部分子元素仍需要点击:

.overlay {
pointer-events: none;
}

.overlay button {
pointer-events: auto;
}
15. 使用 user-select 控制文本是否可选
禁止选中文字:

.button {
user-select: none;
}
拖拽区域:

.drag {
user-select: none;
cursor: grab;
}
一键复制:

.copy {
user-select: all;
}
16. 使用 caret-color 修改输入框光标颜色
input,
textarea {
caret-color: red;
}
隐藏光标:

.preview {
caret-color: transparent;
}
17. letter-spacing 和 word-spacing 有什么区别?
英文单词之间:

p {
word-spacing: .25rem;
}
字符之间:

.title {
letter-spacing: .08em;
}
其中:

letter-spacing 控制字符距离
word-spacing 控制单词距离(主要针对英文)
总结
上面的这些技巧,大多数都只有一两行 CSS,却能解决很多项目中的真实问题。

相比记住所有 CSS 属性,更重要的是知道:

遇到按钮不好点,想到 伪元素扩大热区
遇到父元素状态联动,想到 :has()
遇到 SVG 配色,想到 currentColor
遇到透明图片阴影,想到 drop-shadow()
遇到锚点偏移,想到 scroll-margin-top
遇到图片裁剪,想到 object-fit
遇到响应式尺寸,想到 clamp()
当这些技巧真正进入你的「CSS 工具箱」,以后遇到类似需求时,就不需要第一时间想到 JavaScript 或各种 Hack,而是优先尝试 CSS 提供的原生能力。