如何实现div内多个径向渐变的顺时针平滑动画?
问题描述
现有HTML结构:
<header class="hero"> <section class="hero-text-container"> <!--Content Here--> </section> <figure class="hero-figure"> <!--Image Here--> </figure> </header>
对应的初始CSS:
.hero { background-image: radial-gradient(ellipse 30% 100% at -4% 5%, #ce0058, transparent), radial-gradient(ellipse 100% 75% at 0% 0%, #cf4520, #460702, transparent), radial-gradient(ellipse 100% 100% at 100% 100%, black, black); display: flex; width: 100%; max-width: 100vw; justify-content: center; align-items: stretch; text-align: justify; flex-wrap: wrap; margin: 0 auto; border-bottom: 2px solid #eee; animation-name: colors-circulating; animation-duration: 5s; animation-timing-function: ease-in-out; animation-iteration-count: 3; }
尝试通过@keyframes直接修改background-image,实现渐变沿左上→右上→右下→左下顺时针平滑移动,但实际效果是生硬切换4个关键帧画面,无平滑过渡。
解决方案:用CSS变量实现平滑动画
核心思路是将渐变的位置参数抽离为CSS变量,通过动画变量数值实现平滑插值——浏览器可对数值类型的CSS变量进行过渡计算,但无法直接对完整的background-image定义插值。
修改后的完整CSS代码:
.hero { /* 定义控制渐变位置的CSS变量,初始值对应原位置 */ --pink-x: -4%; --pink-y: 5%; --brown-x: 0%; --brown-y: 0%; background-image: radial-gradient(ellipse 30% 100% at var(--pink-x) var(--pink-y), #ce0058, transparent), radial-gradient(ellipse 100% 75% at var(--brown-x) var(--brown-y), #cf4520, #460702 60%, transparent), radial-gradient(ellipse 100% 100% at 100% 100%, black, black); display: flex; width: 100%; max-width: 100vw; justify-content: center; align-items: stretch; text-align: justify; flex-wrap: wrap; margin: 0 auto; border-bottom: 2px solid #eee; animation: colors-circulating 5s ease-in-out 3; } @keyframes colors-circulating { 0%, 100% { --pink-x: -4%; --pink-y: 5%; --brown-x: 0%; --brown-y: 0%; } 25% { --pink-x: 96%; --pink-y: 5%; --brown-x: 100%; --brown-y: 0%; } 50% { --pink-x: 96%; --pink-y: 105%; --brown-x: 100%; --brown-y: 100%; } 75% { --pink-x: -4%; --pink-y: 105%; --brown-x: 0%; --brown-y: 100%; } }
原理说明
- 原方案直接修改
background-image属于离散属性动画,浏览器无法在不同的渐变字符串之间计算中间值,只能在关键帧处直接切换,导致生硬效果。 - CSS变量若存储数值(含百分比、像素等单位),浏览器会自动对其进行插值计算,实现平滑过渡动画,最终带动渐变位置连续变化。
额外优化建议
如果需要更细腻的动画节奏,可调整animation-timing-function的值,比如用cubic-bezier(0.4, 0, 0.2, 1)替代默认的ease-in-out;也可增加更多关键帧,细化运动轨迹的细节。
内容的提问来源于stack exchange,提问作者Abdurrahman Tantawi
相关产品推荐
相关产品推荐

