在日常前端开发中,我们经常会遇到一些看起来很简单,但处理起来又有点麻烦的问题:
- 图标太小,不容易点击
- 图片尺寸不统一,导致布局错乱
- SVG 颜色不好控制
- 页面滚动到锚点后被顶部导航遮挡
- 想实现毛玻璃效果,却发现元素本身也被模糊了
- 想给不规则 PNG 添加阴影,却只能得到矩形阴影
很多时候,这些问题并不需要引入 JavaScript,也不需要额外的库,只需要几个容易被忽略的 CSS 属性就能轻松解决。
下面整理了 17 个项目中非常实用的 CSS 技巧,建议收藏备用。
一、最值得掌握的几个 CSS 技巧
1. 增大元素的点击热区
在移动端页面或工具栏中,图标的视觉尺寸可能只有 16px 或 24px,如果直接点击图标,操作体验往往不太好。
最直接的方法是增加元素宽高,但这样容易影响布局。更推荐使用伪元素扩大点击区域。
css
.like-button {
position: relative;
}
.like-button::before {
content: "";
position: absolute;
inset: -12px;
border-radius: 50%;
}
伪元素会把按钮四周的点击区域分别扩大 12px,而不会影响页面布局。
注意:伪元素必须属于可点击元素,点击事件会正常传递给
.like-button。
示例:
https://code.juejin.cn/pen/7308632485130240050
另一种简单写法:
css
.like-button {
padding: 12px;
margin: -12px;
}
不过负 margin 可能影响布局、滚动区域以及点击关系,使用前建议充分测试。
React Native 中可以直接使用:
jsx
<Pressable
hitSlop={{
top: 12,
right: 12,
bottom: 12,
left: 12,
}}
>
<Icon />
</Pressable>
2. 使用 :has() 根据子元素控制父元素
过去,CSS 很难根据子元素的状态修改父元素样式,通常需要 JavaScript。
现在可以直接使用 :has():
css
.form-item:has(input:focus) {
border-color: #1677ff;
}
更多场景:
根据错误信息修改样式:
css
.form-item:has(.error-message) {
border-color: red;
}
根据复选框状态修改父元素:
css
.option:has(input:checked) {
background: #e6f4ff;
border-color: #1677ff;
}
判断是否包含图片:
css
.card:has(img) {
padding-top: 0;
}
和相邻选择器结合:
css
label:has(+ input:required)::after {
content: "*";
color: red;
}
3. 使用 currentColor 让 SVG 自动继承文字颜色
currentColor 表示当前元素的 color 属性值。
css
.button {
color: #666;
}
.button:hover {
color: #1677ff;
}
.button svg {
fill: currentColor;
}
html
<button class="button">
<svg viewBox="0 0 24 24">
<path d="..." />
</svg>
收藏
</button>
鼠标悬停时,文字和 SVG 会一起变色,无需单独修改 SVG 颜色。
对于描边图标:
css
svg {
stroke: currentColor;
}
4. 使用 drop-shadow() 给透明 PNG 添加自然阴影
很多人不知道:
css
box-shadow
和
css
filter: drop-shadow()
完全不是同一种阴影。
普通阴影:
css
.logo {
box-shadow: 0 8px 20px rgb(0 0 0 / 20%);
}
透明 PNG:
css
.logo {
filter: drop-shadow(0 8px 12px rgb(0 0 0 / 25%));
}
区别:
css
/* 根据矩形盒模型生成阴影 */
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 避免锚点被导航栏遮挡
很多文档站都会遇到这个问题。
css
.header {
position: fixed;
top: 0;
height: 64px;
}
点击锚点:
html
<a href="#install">安装方式</a>
<section id="install" class="article-section">
</section>
解决办法:
css
.article-section {
scroll-margin-top: 80px;
}
整个页面统一偏移也可以:
css
html {
scroll-padding-top: 80px;
}
区别:
scroll-margin-top:作用于目标元素scroll-padding-top:作用于滚动容器
二、图片与布局
6. 使用 object-fit 控制图片裁剪
图片尺寸不一致时,直接指定宽高容易被拉伸。
css
img {
width: 300px;
height: 200px;
object-fit: cover;
}
常见值:
cover:填满容器,超出部分裁剪contain:完整显示,可能留白
控制裁剪位置:
css
img {
object-fit: cover;
object-position: center top;
}
7. 使用 aspect-ratio 保持宽高比
以前需要:
css
padding-top: 56.25%;
现在:
css
.video {
aspect-ratio: 16 / 9;
}
简单很多。
8. 使用 clamp() 实现响应式尺寸
css
.title {
font-size: clamp(24px, 5vw, 64px);
}
还可以用于:
css
.section {
padding-inline: clamp(16px, 5vw, 80px);
}
css
.card {
width: clamp(280px, 50vw, 600px);
}
相比大量媒体查询更加简洁。
9. clip-path 和 mask 有什么区别?
clip-path 更适合几何裁剪:
css
.avatar {
clip-path: circle(50%);
}
三角形:
css
.triangle {
clip-path: polygon(50% 0,100% 100%,0 100%);
}
六边形:
css
.hexagon {
clip-path: polygon(
25% 0,
75% 0,
100% 50%,
75% 100%,
25% 100%,
0 50%
);
}
mask 更适合图片、透明度和渐变裁剪:
css
.icon {
background: currentColor;
mask: url(icon.svg) center/contain no-repeat;
-webkit-mask: url(icon.svg) center/contain no-repeat;
}
渐隐:
css
.content {
mask-image: linear-gradient(
to bottom,
black 70%,
transparent
);
}
简单理解:
clip-path:裁几何图形mask:裁图片和透明效果
10. 使用 column-count 实现多栏布局
css
.article {
column-count: 2;
}
列间距:
css
.article {
column-count: 2;
column-gap: 32px;
}
更推荐:
css
.article {
column-width: 320px;
column-gap: 32px;
}
浏览器会自动决定列数,更适合响应式布局。
三、视觉效果
11. 使用 backdrop-filter 实现真正的毛玻璃
很多人会误写成:
css
filter: blur(12px);
结果整个元素包括文字都模糊了。
正确写法:
css
.glass {
background: rgb(255 255 255 / 60%);
backdrop-filter: blur(12px);
}
注意:
backdrop-filter 模糊的是元素后面的内容,而不是元素本身,因此通常需要半透明背景。
12. 一行 CSS,把 SVG 或 PNG 图标变成黑色或白色
变黑:
css
img {
filter: brightness(0);
}
变白:
css
img {
filter: brightness(0) invert(1);
}
适用于:
- SVG
- Logo
- 单色图标
- 深色模式切换
不适用于照片或复杂渐变图片。
13. 使用 mix-blend-mode 实现混合效果
css
.hero-title {
color: white;
mix-blend-mode: difference;
}
文字会根据背景自动产生反差。
常见模式:
css
mix-blend-mode: multiply;
mix-blend-mode: screen;
mix-blend-mode: overlay;
mix-blend-mode: difference;
mix-blend-mode: exclusion;
复杂页面建议:
css
.container {
isolation: isolate;
}
四、交互体验优化
14. 使用 pointer-events 实现事件穿透
css
.overlay {
pointer-events: none;
}
让元素显示,但不接收点击事件。
如果部分子元素仍需要点击:
css
.overlay {
pointer-events: none;
}
.overlay button {
pointer-events: auto;
}
15. 使用 user-select 控制文本是否可选
禁止选中文字:
css
.button {
user-select: none;
}
拖拽区域:
css
.drag {
user-select: none;
cursor: grab;
}
一键复制:
css
.copy {
user-select: all;
}
16. 使用 caret-color 修改输入框光标颜色
css
input,
textarea {
caret-color: red;
}
隐藏光标:
css
.preview {
caret-color: transparent;
}
17. letter-spacing 和 word-spacing 有什么区别?
英文单词之间:
css
p {
word-spacing: .25rem;
}
字符之间:
css
.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 提供的原生能力。