用 background-size 缩放+background-position 锚定实现左上角蔓延效果:起始设 background-size: 0% 0%、background-position: top left、background-origin: border-box,悬停时仅过渡 background-size 至 100% 100%。

用 background-size + background-position 控制悬停渐变起点
纯 CSS 实现“从左上角蔓延出背景色”,关键不是动画本身,而是把背景当作可定位、可缩放的图层来操作。默认 background 是铺满整个元素的,必须先把它“缩小”并“锚定”在角落,再通过过渡让它放大覆盖全区域。
- 起始状态设
background-size: 0% 0%,background-position: top left(注意:不能写成0 0,部分浏览器对百分比定位兼容性更稳) - 悬停时设
background-size: 100% 100%,位置保持不变,视觉上就是从左上角“撑开” - 必须加
background-origin: border-box,否则圆角或 padding 会干扰定位基准 - 过渡只写
background-size,别加background-position,否则 Safari 可能抖动
为什么 :hover 里用 linear-gradient 不行
很多人试过直接在 background 里写 linear-gradient(to bottom right, #fff, #fff) 并过渡 background-position,结果发现颜色是“滑动”过去,不是“蔓延”出来——因为渐变本质是纹理平铺,不是单个可缩放图层。
-
linear-gradient的起点/终点是方向描述,不是坐标锚点,无法绑定到物理角落 - 哪怕配合
background-position: 0 0过渡,也只是把整条渐变条在元素内平移,不是从零开始生长 - 真正要“蔓延”,必须依赖
background-size的缩放行为,这是唯一被所有现代浏览器一致支持的“生长式”背景控制方式
兼容性与性能注意点
这个方案在 Chrome/Firefox/Safari/Edge 102+ 都没问题,但老 Edge(≤18)不支持 background-size 百分比过渡,会直接跳变。如果必须兼容,得降级为 transform: scale() 遮罩层,但那是另一套实现。
- 别用
em或rem做background-size单位,只接受%、px或cover/contain;百分比最可控 - 过渡时间别设太长(如 >0.4s),
background-size动画在低端 Android 上可能掉帧 - 如果元素有
border-radius,确保overflow: hidden,否则蔓延过程可能露出直角边缘
一个能直接抄的最小可用示例
button {
background: #007bff;
color: white;
position: relative;
overflow: hidden;
}
button::before {
content: '';
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background: #fff;
background-size: 0% 0%;
background-position: top left;
background-origin: border-box;
transition: background-size 0.3s ease;
z-index: -1;
}
button:hover::before {
background-size: 100% 100%;
}
注意:这里用 ::before 伪元素承载背景,是为了不影响文字层和原有 background;如果你的按钮原本没背景,可以直接作用于元素自身,把 background 拆成 background-color 和 background-image 来分别控制。
立即学习“前端免费学习笔记(深入)”;
真正麻烦的是多角定位——比如“从右下角蔓延”,得把 background-position 改成 bottom right,同时确保 background-origin 仍是 border-box,否则在有 padding 的容器里会偏移。这点很容易被忽略,一试就错。










