779 字
4 分钟
CSS实现旋转渐变边框动效按钮
今天做一个花哨的动效,这种动效经常会在一些产品或个人网站上见到。它的特点是边框带有渐变旋转的效果。虽然制作起来不算难,但需要使用一些 CSS 属性,这些属性在平常的开发中并不常用,但非常有效。下面我将一步一步地解释如何制作这个动效。
准备一个按钮
<button>
<span>我是个按钮</span>
</button>
button {
position: relative;
padding: 20px 40px;
border: 0;
border-radius: 999px;
font-size: 24px;
color: #fff;
--bg: radial-gradient(40% 50% at center 100%, hsl(270 0% 72% / 0.05), transparent), radial-gradient(
80% 100% at center 120%,
hsl(260 0% 70% / 0.1),
transparent
), hsl(260 0% 12%);
background: radial-gradient(40% 50% at center 100%, hsl(270 0% 72% / 0.05), transparent), radial-gradient(
80% 100% at center 120%,
hsl(260 0% 70% / 0.1),
transparent
), hsl(260 0% 12%);
overflow: hidden;
}
渐变效果
我把上层遮罩去掉,应该很多人都看得出实现原理了。
其实,就是一个锥形渐变加上旋转动画。CSS 锥形渐变(CSS conic gradient)是一种用于创建圆锥形渐变效果的 CSS 背景样式。它允许你在元素的背景上创建一个从中心点向外辐射的渐变效果,类似于放射性波纹或圆锥。
使用 CSS 锥形渐变,你可以定义一个或多个颜色断点,并指定它们在渐变中所占的位置。这些颜色断点将按照一定的角度从中心点开始辐射状分布,形成一个圆锥形的渐变效果。
一个简单的示例:
所以,要表示上面的部分锥形,可以这样写:
background: conic-gradient(from 0deg, transparent, hsl(0deg, 100%, 50%) 60deg, transparent 61deg);
from 0deg
:这是渐变的起始角度,通过改变这个值可以不同的位置偏移。hsl(0deg, 100%, 50%)
:这里使用 HSL 表示色值,因为可以通过色相(H)角度不同改变颜色值。
旋转动画
上面已经提到通过改变角度实现位置偏移和颜色,所以要给角度先定义一个变量。自定义变量采用的是@property
。为什么不用形如--*
定义呢?因为--*
是定义在 CSS 选择器里面,选择器本身及其嵌套选择器都可以使用和改变,但是@keyframes
动画规则并不在任何嵌套选择器内,所以更改值并不会生效。
@property --rotation {
syntax: '<angle>';
inherits: true;
initial-value: 0deg;
}
然后,用变量替代角度值并在@keyframes
内更改。
button::before {
content: '';
position: absolute;
inset: 0;
background: conic-gradient(
from var(--rotation),
transparent,
hsl(var(--rotation), 100%, 50%) 60deg,
transparent 61deg
);
animation: spin 2s infinite linear;
}
@keyframes spin {
0% {
--rotation: 0deg;
}
100% {
--rotation: 360deg;
}
}
在上面代码中用到了inset
属性,inset 为简写属性,对应于top
、right
、bottom
和 left
属性,inset: 0
相当于left: 0; right: 0; top: 0; bottom: 0;
。
显示边框
上面的效果已经基本成型了,要是它显示成边框的效果,还要把中间部分盖住。
button::after {
content: '';
position: absolute;
inset: 3px;
border-radius: 999px;
background: var(--bg);
}
文字显示
上面的多次使用了position: absolute;
,会改变层级导致文字被遮挡,所以还需要提升文字层级。
span {
position: relative;
z-index: 2;
}