渐变描边:让渐变沿着圆角流动
三部曲讲的是角本身;这一页讲边——而它最难的地方,恰恰还是圆角。原生 border 只接受纯色,想给边框上渐变,第一直觉是 border-image:它确实能把渐变铺到边框上,却完全无视 border-radius,四角立刻变回直角。于是整套「渐变描边」技巧,本质都是在回答同一个问题:怎样让一道渐变,严丝合缝地贴着圆角走?
1 · 问题:渐变与圆角为何相互冲突
border-color 只能是纯色,渐变无从谈起。退而求其次用 border-image: linear-gradient(...),渐变是上去了,但 border-image 把边框区域当成一张九宫格图片来贴,不参与圆角裁剪——所以无论
border-radius 设多大,描边的四角都是直角。右边的 background-clip 双层法则用 border-box 层承载渐变、padding-box 层盖住内芯,渐变只在边框环露出,且天然跟随圆角。拖滑块对比。
border-image 不是不能用,而是它与 border-radius 互斥。规范里 border-image 一旦生效就替换掉常规边框的绘制,圆角裁剪只作用于「常规边框 + 背景」这条路径,管不到贴上去的图。所以只要你既要渐变、又要圆角,就得换思路——把渐变放进背景或遮罩,让它走那条会被圆角裁剪的绘制路径。
2 · 两种贴着圆角的静态做法
两种主流写法都能让渐变严格跟随 border-radius。背景双层法:把 border 设成透明,背景叠两层——padding-box 那层是纯色内芯、border-box 那层是渐变,渐变只在透明边框处露出。遮罩法:用一个 ::before 铺满渐变,再用两层 mask 做
exclude,只留下边框环。遮罩法更通用(任意渐变、任意形状都对),双层法更简短。切换方案与渐变类型,看右侧 CSS。
遮罩法的核心是 mask-composite: exclude。两层 mask:一层裁到 content-box(内芯区域)、一层覆盖整盒;exclude 取「整盒 减去 内芯」= 一圈边框环,渲染就被这个环裁出来。Safari 仍需配 -webkit-mask-composite: xor 与 -webkit-mask 前缀(本页已写)。双层法则不需要任何前缀,但只适合「内芯纯色」的场景——内芯要透出底下内容时,用遮罩法。
3 · 让描边转起来:@property + conic-gradient
若浏览器不支持 @property,conic 会停在起始角不旋转——见本页末的降级方案。
把双层法里的渐变换成
,再让 --angle 从 0deg 转到 360deg,描边就沿圆角流动。关键在 @property:裸自定义属性是字符串,动画引擎不知道怎么补间;用 @property 把 --angle
注册成 <angle> 类型后,它才能像普通角度值一样被 @keyframes 平滑插值。拖滑块改转速,或暂停。
为什么不能直接动画一个普通 --angle?未注册的自定义属性,其值在 CSS 看来只是一段不透明文本,@keyframes 无法在两段文本之间「取中间值」,于是动画会在 0deg 与 360deg 之间瞬间跳变(甚至完全不动)。@property
的 syntax: "<angle>" 给了它类型,浏览器据此知道如何插值——这正是 @property 让「动画任意属性」成为可能的根本。prefers-reduced-motion 下本页已自动停转。
4 · 降级:旋转一张超大渐变
@property 较新,不支持时 conic 停在起始角。@property 出现之前,旋转渐变靠的是另一招,且处处可用:外层 overflow: hidden + border-radius 裁出圆角,内部塞一张远大于盒子的渐变层(这里 260%),用
transform: rotate 整张转;再叠一层内芯盖住中间,只留下一圈边框。转的是元素而非渐变的角度,因此不需要可动画的自定义属性。
**降级方案的代价:多两层 DOM、且渐变层必须做得足够大。**盒子是长方形时,旋转中的方形渐变层要能在任意角度都盖满四角,边长得取到对角线以上(本页用 260% 留足余量)。它胜在兼容性——不依赖 @property / conic-gradient 的可动画性,只用最古老的
transform: rotate 与 overflow: hidden 圆角裁剪,这本身正是border-radius那页讲过的能力。
5 · 回到主线
从切图、到border-radius、再到corner-shape,三部曲让「角」一步步从图片资产变成声明式样式。这页则是「边」的同一个故事:渐变描边的全部工程,都是为了让一道颜色沿着那条圆角轮廓流动——角与边,最终都收束到同一条圆角曲线上。