你有没有遇到过这种情况:在 CSS 里给同一个卡片调了十几遍 background 和 border-radius,最后出来的页面还是像没做完的半成品?我刚开始做前端开发那会儿就是这样,背景颜色一顿叠,圆角在 10px 和 50% 之间反复横跳,结果页面虽然能用,但怎么看怎么塑料。后来我才想明白,背景和圆角这两个属性不是拿来“填色”的,而是用来控制视觉层次的。背景能叠加多层渐变和图案,圆角能组合出扇形、水滴、花瓣这类跟“圆角矩形”八竿子打不着的形状,二者配合起来,才是页面颜值飙升的真正底牌。
这篇我把 background 和 border-radius 的进阶用法完整梳理了一遍,从渐变背景到多重背景,从椭圆圆角到切角卡片,再到实战案例和性能坑,适合已经写过基础 CSS、但想把页面做出质感的开发者。不用你有多深的功底,跟着思路走,每一步都能落地。
1. 背景属性的底层逻辑:子属性这么多,先弄懂它们在干什么
很多前端写了几年 background: #fff url(...) no-repeat center,本质上还是“会背不会讲”。背景属性其实是一组子属性的集合,搞懂每个子属性负责什么,后面玩渐变和多重背景时就不会懵。
1.1 background 子属性全景与简写顺序
先列个全景表,把 background 家族的子属性一次看清:
| 子属性 | 作用 | 默认值 |
|---|---|---|
background-color |
背景色,只能有一层 | transparent |
background-image |
背景图或渐变,可叠多层 | none |
background-position |
背景图的起点位置 | 0% 0% |
background-size |
背景图的尺寸 | auto |
background-repeat |
是否平铺 | repeat |
background-origin |
定位参考框:border-box / padding-box / content-box |
padding-box |
background-clip |
绘制范围:border-box / padding-box / content-box / text |
border-box |
background-attachment |
背景是否随滚动 | scroll |
简写的时候,顺序要求并不像 margin 那样严格,但有一个必须记住的规则:position 和 size 要用斜杠 / 分隔,且 size 必须跟在 position 后面。比如 background: url(banner.jpg) center / cover no-repeat,写成 no-repeat center cover 就完全不对。
这里特别容易翻车的是 background-origin 和 background-clip 的简写关系。它俩在简写里如果同时出现两个值,第一个是 origin,第二个是 clip;如果只出现一个值,则两者都被设置成这个值。官方语义里 origin 默认是 padding-box,clip 默认是 border-box,这个错位曾经坑过不少同事。
1.2 background-position 的百分比计算,别再凭感觉写
background-position 用像素、left/right/top/bottom 这些关键字大家都会,但一到百分比就容易懵:为什么 50% 50% 能居中,而 50px 50px 看起来并没有居中?
关键区别在于:百分比是拿“容器尺寸减去背景图尺寸后的剩余空间”乘以百分比来算偏移的。公式是这样的:
code复制偏移量 =(容器尺寸 - 背景图尺寸)× 百分比
举个例子,容器宽 400px,背景图宽 200px:
background-position: 50%→(400 - 200) × 0.5 = 100px,图片从左边偏移 100px,刚好居中。background-position: 100px→ 图片左边缘离容器左边缘固定 100px,但因为图宽 200px,右边缘到容器右边缘也是 100px,看起来也居中。- 但容器改成 410px 再看:
50%会偏移105px,而100px还是死板的100px,差异就冒出来了。
所以如果你想做“背景图随容器宽度变化而保持某种相对位置”的效果,用百分比;想要绝对偏移,再用像素。这个规律同样适用于 background-origin 改变参考框后的计算,搞清楚一次,省得以后每个项目都现场试。
1.3 多重背景的叠加顺序:前面的在顶层
background 支持用逗号分隔多个背景层,比如:
css复制background:
linear-gradient(135deg, rgba(106,92,255,0.8), rgba(162,75,207,0.6)),
url('texture.png'),
#f5f4ff;
规则是:越靠前的层,层级越高,显示在最上面。background-color 只能有一个,永远放在最后一层。
理解这个顺序就能玩出花样了:比如底层放一张噪点纹理图,上面叠一层带透明度的渐变,视觉上纹理透过渐变透出来,相当于给页面加了一层“纸质感”。如果顺序写反了,纹理盖在渐变上面,效果会完全变味。
还有个细节:如果 background-repeat 是 no-repeat,但背景图尺寸小于容器,多出来的区域会显示下一层的背景。所以你在调试多重背景时,经常要同时配合 background-size 来控制每一层的覆盖范围,而不是单纯靠叠层数。
1.4 background-attachment 滚动效果里的暗坑
background-attachment 有三个值:scroll(默认,背景随元素滚动)、fixed(背景相对视口固定)、local(背景随元素内容一起滚动)。
fixed 在 PC 端做“视差背景”很漂亮,但在移动端浏览器上兼容性一直不太妙,不少安卓浏览器会直接把它降级成 scroll,iOS Safari 在配合 overflow 容器时也容易抽风。如果你需要同时兼容移动端,建议直接用两个图层 + transform 来做视差,而不是依赖 background-attachment: fixed。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 渐变背景:能给页面“打光”的三种渐变
很多人对渐变的认知停留在 linear-gradient(90deg, red, blue) 这种入门写法,但渐变其实是 CSS 里表现力最强的“绘图工具”。它不占额外 DOM、可叠加、可做纹理、可裁切到文字上,是高级感页面的主力。
2.1 linear-gradient 的角度与位置节点
线性渐变的语法是:
css复制background: linear-gradient(角度或方向, 颜色 位置, 颜色 位置, ...);
角度很容易记混,这里给个锚点:
0deg方向是从下往上(颜色从底部渐变到顶部)90deg方向是从左往右180deg方向是从上往下to top等价于0deg,to right等价于90deg
实际开发中我更喜欢写 to bottom right 这类方向关键字,语义清楚,不用脑子里转一圈角度。
颜色后面的位置节点也很关键。默认情况下,两个颜色会均匀分布在渐变轴上,但你可以手动指定:
css复制background: linear-gradient(
to right,
#6a5cff 0%,
#a24bcf 30%,
#ff6a88 70%,
#ffd166 100%
);
这样把渐变节奏控制到自己想要的位置,画面会更有层次。调试时最有效的方式是直接开浏览器 DevTools 的渐变编辑器,它支持在代码面板上拖动渐变柄,比盲写快太多。
2.2 radial-gradient 的光斑与打光效果
radial-gradient 适合做圆形渐变,常用在按钮光斑、页面氛围光和卡片高光上。语法:
css复制background: radial-gradient(
circle at 30% 30%,
rgba(255,255,255,0.8) 0%,
rgba(255,255,255,0) 40%
);
这里的 circle at 30% 30% 表示圆心在容器横向 30%、纵向 30% 的位置。size 关键字里我个人最常用 closest-side 和 farthest-corner:
closest-side:以离圆心最近的边为半径,渐变结束得快,光斑更紧凑。farthest-corner:以离圆心最远的角为半径,渐变铺得更开,适合做大面积氛围光。
给卡片叠一层从上往下的柔和光,就能把“平铺贴图”的廉价感压下去:
css复制.card {
background:
radial-gradient(circle at 20% 0%, rgba(255,255,255,0.35), transparent 45%),
linear-gradient(180deg, #4b3f72, #221e3d);
}
2.3 conic-gradient 画饼图和表盘
conic-gradient 是锥形渐变,颜色绕着圆心走一圈,最常见的用途是画饼图、仪表盘、彩色圆环。比如一个 50% 占比的进度饼:
css复制.conic-progress {
width: 160px;
height: 160px;
border-radius: 50%;
background: conic-gradient(#6a5cff 0deg 180deg, #e5e7ef 180deg 360deg);
}
如果配合 mask 裁出一个圆环,就能做纯 CSS 的进度环,连 SVG 都不用引。这类写法在可视化大屏里极其常见,配合背景面板和圆角,基本就是大屏组件的标配。
2.4 repeating 渐变做纹理
repeating-linear-gradient 和 repeating-radial-gradient 能直接画出条纹、棋盘格、斜纹等纹理,不需要背景图资源。比如网格背景:
css复制background:
repeating-linear-gradient(
0deg,
#f0f0f5 0px,
#f0f0f5 1px,
transparent 1px,
transparent 24px
),
repeating-linear-gradient(
90deg,
#f0f0f5 0px,
#f0f0f5 1px,
transparent 1px,
transparent 24px
);
很多网站的代码块、笔记本风格背景就是这么画的。要注意重复渐变在小尺寸元素上性能没有压力,但如果在非常宽大的画布上频繁 repaint,开销还是有的,后面性能部分会细说。
3. 圆角进阶:border-radius 不只是四个数值
我见过不少前端把 border-radius 当成“四个角统一定值”的工具,实际上它的完整写法能控制四个角各自的水平半径和垂直半径,组合起来能画出各种非矩形形状。这块吃透了,很多组件效果可以完全脱离切图。
3.1 四值语义与斜杠椭圆写法的推导
border-radius 支持 1 到 4 个值,顺时针从左上角开始:
| 值个数 | 语义 |
|---|---|
| 1 个 | 四角相同 |
| 2 个 | 第一个:左上/右下;第二个:右上/左下 |
| 3 个 | 第一个:左上;第二个:右上/左下;第三个:右下 |
| 4 个 | 左上、右上、右下、左下 |
真正容易忽略的是斜杠写法:
css复制border-radius: 50% / 20%;
斜杠前面是水平半径,斜杠后面是垂直半径。这种写法可以让角呈现明显的椭圆弧——比如你要做一个扁平但带一点弧度的卡片,20px / 8px 会比均匀的 10px 更有“现代感”。
百分比值也很重要:border-radius: 50% 在宽高不等的元素上会自动形成椭圆,这正是圆形头像、饼图容器能“碰巧”变成正圆或椭圆的原理。
3.2 圆角与外边框、背景裁切的关系
border-radius 的曲线是作用在 border-box 外边缘上的。如果你给元素加了较粗的边框,内边缘的圆角会按“外半径减去边框宽度”自动压缩。边框越粗,内边缘越接近直角,这是很多人调了半天觉得“内边不圆”的原因。
更隐蔽的问题是:子元素背景溢出圆角。给一个父容器设置 border-radius: 12px,但子元素背景色如果伸出来了,视觉上就会漏一个直角。解决方案是给父容器加 overflow: hidden;,但要注意它会把所有子元素的内容都裁掉,包括可能溢出的下拉菜单、气泡、阴影,所以不要无脑加。
如果你只是想让父容器的背景被圆角裁剪,但不想让阴影被裁掉,可以改用 background-clip: padding-box,这样背景会被裁到圆角范围内,而 box-shadow 可以正常绘制出去。
3.3 用圆角组合生成异形卡片
利用四个角半径不同的特性,能生成很多看起来“不像圆角”的形状:
css复制.petal {
width: 120px;
height: 120px;
background: #6a5cff;
border-radius: 50% 50% 0 50%;
}
这个是水滴/花瓣形,border-radius: 50% 50% 0 50% 让左上、右上、右下三个角都是半圆,左下角是直角,组合起来就是一个斜切水滴。再比如扇形:
css复制.fan {
width: 120px;
height: 120px;
background: #ff6a88;
border-radius: 100% 0 0 0;
}
把 100% 用在左上角,配合纯色背景,就是一个四分之一圆。这类形状用在装饰性角标、悬浮球、加载动画上都挺出效果。
3.4 切角(倒角)的两种实现思路对比
工业设计里的“倒角”分两种:斜切(chamfer)和圆弧(fillet)。CSS 里 border-radius 做的是圆弧倒角,想做“一刀切”的斜角卡片,有两个思路。
第一种是用 linear-gradient 配合透明色来接:
css复制.cut-corner {
background:
linear-gradient(135deg, transparent 10px, #6a5cff 0) top left,
linear-gradient(-135deg, transparent 10px, #6a5cff 0) top right,
linear-gradient(45deg, transparent 10px, #6a5cff 0) bottom left,
linear-gradient(-45deg, transparent 10px, #6a5cff 0) bottom right;
background-size: 50% 50%;
background-repeat: no-repeat;
}
四个渐变各占四分之一区域,每个角切掉 10px。这种方案的问题是内部内容要自己留足安全间距,且背景比较复杂时不好用。
第二种更省心:直接用 clip-path: polygon()。比如:
css复制clip-path: polygon(16px 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 0 100%, 0 16px);
clip-path 会把整个元素都裁掉,包括子元素,所以它更适合做纯装饰卡片;linear-gradient 方案则只影响背景层,内容不会被裁剪。真正做切角组件时,按“要不要保留阴影”“内容会不会溢出”这两个条件来选方案就够了。
4. 实战:把背景和圆角用在高颜值组件上
理论讲完,上点能直接抄的代码。下面几个组件都是我这几年在后台管理系统、官网和营销页里反复用过的,不需要 UI 库,原生 CSS 就能搭。
4.1 渐变发光按钮
一个高级感按钮的底层逻辑无非三件事:渐变背景、恰到好处的圆角、微妙的悬浮反馈。
css复制.btn-glow {
padding: 12px 28px;
border: none;
border-radius: 12px;
color: #fff;
background: linear-gradient(135deg, #6a5cff, #a24bcf);
box-shadow: 0 8px 24px rgba(106, 92, 255, 0.35);
cursor: pointer;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.btn-glow:hover {
transform: translateY(-2px);
box-shadow: 0 12px 32px rgba(106, 92, 255, 0.5);
}
圆角 12px 在大多数按钮上都合适,不会太圆显得卡通,也不会太方显得生硬。box-shadow 的颜色一定要跟渐变的主色同色系,整体才会“发光”而不是“浮灰”。
4.2 渐变边框按钮
渐变边框最简单的实现是“外层渐变 + 内层纯色”两层嵌套:
css复制.wrap {
padding: 2px;
border-radius: 12px;
background: linear-gradient(135deg, #ff6a6a, #ffb347);
}
.btn-inner {
padding: 10px 26px;
border-radius: 10px;
background: #fff;
color: #ff6a6a;
}
内层圆角要比外层小 2px,不然边框粗细不均。更进阶的写法是不加嵌套,用一个 background-clip 双背景技巧:
css复制.btn-border {
padding: 10px 26px;
border: 2px solid transparent;
border-radius: 12px;
background:
linear-gradient(#fff, #fff) padding-box,
linear-gradient(135deg, #ff6a6a, #ffb347) border-box;
color: #ff6a6a;
}
这里的核心原理是两层渐变分别被裁切到 padding-box 和 border-box,透明边框区域露出第二层渐变,视觉效果就是边框本身带渐变。这个写法比嵌套多一层,但结构干净,推荐学一下。
4.3 涟漪扩散动画
想给页面加一点“国产 App 内味”的交互反馈,可以在圆形元素上叠加扩散圆环,纯 CSS 就能实现:
css复制.dot {
position: relative;
width: 24px;
height: 24px;
border-radius: 50%;
background: #6a5cff;
}
.dot::before {
content: '';
position: absolute;
inset: 0;
border-radius: 50%;
border: 2px solid rgba(106, 92, 255, 0.6);
animation: ripple 2s ease-out infinite;
}
@keyframes ripple {
0% {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(2.4);
opacity: 0;
}
}
注意 ::before 需要 position: absolute 和 inset: 0,动画里只动 transform 和 opacity,这样能走到合成器线程,不会触发重排,性能没问题。如果想把扩散圆环固定在右下角或任意位置,改 inset 的偏移值就行。
4.4 渐变字体与胶囊徽章
渐变字是排版里提升质感的杀手锏:
css复制.gradient-text {
background: linear-gradient(90deg, #6a5cff, #ff6a88);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
配套的胶囊标签:
css复制.badge {
display: inline-block;
padding: 4px 14px;
border-radius: 999px;
background: rgba(106, 92, 255, 0.12);
color: #6a5cff;
font-size: 13px;
}
border-radius: 999px 是一个经典写法,只要圆角值足够大就会自动形成胶囊形,不用去算高度的一半。这两个组件拼起来,就是很多博客站和运营后台里最常见的“文章标签 + 标题”组合。
5. 性能与兼容:这些坑我已经帮你踩过了
颜值上去了,性能也得扛住。背景和圆角看起来不起眼,但在低端机和大列表页面上,一不小心就会成为掉帧元凶。
5.1 会导致页面掉帧的属性组合
linear-gradient 本身不会额外增加 DOM 节点,绘制成本是可控的,真正容易翻车的是“大面积渐变 + 大圆角 + 大阴影 + 频繁动画”的组合。以 box-shadow 为例,它的模糊半径计算量很大,如果阴影同时用在几十个列表项上,每次滚动都会触发大量的重绘。
我的习惯是:动画元素能不用 box-shadow 就不用,优先用 filter: drop-shadow() 或者干脆用渐变模拟阴影。比如给按钮做悬浮效果,可以用一个半透明渐变层盖在底部,视觉上有“阴影感”,但绘制成本比 box-shadow 低一截。
还有一点,background-attachment: fixed 在页面滚动时会反复重绘背景图层,非常耗性能,尤其在内容特别高的页面上,肉眼可见的卡顿。移动端遇到这种情况我一般直接放弃该属性,改用固定定位的辅助层。
5.2 background-clip: text 和渐变的前缀问题
background-clip: text 在现代浏览器里已经不需要 -webkit- 前缀,但 Safari 版本一旧就识别不了 background-clip: text,必须写 -webkit-background-clip: text。问题在于:如果浏览器不支持该属性,color: transparent 会让文字完全消失,读者只看到一片空白。
稳妥做法是先给文字一个正常颜色,再用 @supports 特性检测包裹:
css复制.gradient-text {
background: linear-gradient(90deg, #6a5cff, #ff6a88);
color: #6a5cff;
}
@supports (background-clip: text) or (-webkit-background-clip: text) {
.gradient-text {
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
}
这样即使浏览器不支持渐变字,也能显示一个同色系的纯色文字,至少内容不会被吞掉。
5.3 移动端适配与速查表
移动端最容易踩的坑是:圆角按钮的 overflow: hidden 在低版本 WebView 上裁切线不够平滑,边缘会出现像素锯齿。解决方法是给按钮加一层 transform: translateZ(0) 强制开启 GPU 层,或者避免在按钮上同时叠加渐变和阴影。
另外,根容器设 border-radius 后,在 iOS 上并不总能正确裁剪内部溢出的子元素,需要同时给根容器设置 overflow: hidden 和 isolation: isolate,稳定性高很多。
我整理了一张常用属性的兼容与注意速查表:
| 属性/写法 | 兼容性注意 | 备注 |
|---|---|---|
linear-gradient |
现代浏览器全部支持 | 无需前缀 |
conic-gradient |
Safari 12.1+、Chrome 69+ | 可视化大屏可用 |
background-clip: text |
Safari 老版本需要 -webkit- |
必须做降级处理 |
border-radius: 50% |
都支持 | 做圆形头像会自适应 |
background-attachment: fixed |
移动端兼容性差 | 谨慎使用 |
repeating-* 渐变 |
现代浏览器都支持 | 注意大面积重复的性能 |
说实话,背景和圆角是最容易被新手“看轻”的两个 CSS 属性,总觉得它们不就是填色和加弧线吗?但你看下来应该能感受到:背景可以叠层、可以渐变、可以裁剪到文字里;圆角可以通过横纵半径和四值组合生成各种异形;两者再配合阴影和动画,页面质感根本不需要依赖图片素材。
我自己的体会是,接触这些属性不要只背语法,要把它想成“在画布上铺图层”的过程:先决定背景叠几层,每层是什么渐变/纹理,再决定形状怎么裁、圆角怎么组合,最后用阴影和动画做提亮。等你脑子里有了这套流程,设计稿再复杂也不慌了。
