CSS——边框线条动画效果
上次我们实现了边框的线条缩放效果,今天我们来用三种方式完成边框的线条旋转动态效果。
方法一:使用伪元素
这是最普遍、最常用的方法,我们需要为边框所在的元素添加伪元素,然后旋转这个伪元素即可。本节将讲解以下视频的实现过程。
伪元素边框旋转动画效果
<body>
<main class="main">
<a href="javascript:;" class="button" style="--border-color:hsl(318, 100%, 57%); --delay-coef:0"><span
class="button-text">button</span></a>
<a href="javascript:;" class="button" style="--border-color:hsl(192, 100%, 50%); --delay-coef:1"><span
class="button-text">button</span></a>
<a href="javascript:;" class="button" style="--border-color:hsl(120, 86%, 53%); --delay-coef:2"><span
class="button-text">button</span></a>
</main>
</body>
首先准备好三个按钮,这里为每个按钮添加了行内样式(使用了自定义属性变量):style="--border-color:hsl(318, 100%, 57%); --delay-coef:0"
,这里--border-color:hsl(318, 100%, 57%);
是为了方便设置按钮的颜色,--delay-coef:0
是为了设置三个按钮的动画不同步的系数。当然大家也可以选择使用选择器为不同样式的按钮添加这些样式。
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
/* 定义一些颜色,其中 所谓的 --border-color 只是占位,便于知晓这个自定义属性变量 */
--border-color: hsl(295, 100%, 63%);
/* 定义按钮内文本的颜色 */
--font-color: hsl(0, 0%, 100%);
/* --button-bgc 按钮背景色 */
--button-bgc: hsl(0, 0%, 0%);
/* 设置 body 的背景颜色 */
--body-bgc: hsl(230, 50%, 15%);
min-height: 100vh;
/* 接上回说到,为了实现水平和垂直方向上的居中 */
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: var(--body-bgc);
}
.button {
display: flex;
justify-content: center;
align-items: center;
text-decoration: none;
padding: 0.8em 1em;
background-color: var(--button-bgc);
}
/* 为元素添加上边距 */
.button+.button {
margin-top: 10rem;
}
/* 内部文字 */
.button-text {
font-size: 2rem;
letter-spacing: .1em;
text-transform: uppercase;
color: var(--font-color);
opacity: 0.6;
}
这里设置了一些基础的样式,主要是使用了 flex布局
进行了水平和竖直方向的对齐
。然后使用相邻兄弟选择器对除了第一个按钮以外的的按钮添加上边距。
接下来,进行伪元素的创建和使用。
.button::before {
content: '';
position: absolute;
height: 80%;
width: 150%;
background-color: var(--border-color);
animation: animate 3s linear infinite;
}
@keyframes animate {
0% {
transform: rotate(calc(30deg * var(--delay-coef)))
}
100% {
transform: rotate(calc(360deg + 30deg * var(--delay-coef)))
}
}
!!!
这里需要注意的点是:在设置关键帧时,这里我为了实现三个伪元素的旋转非同步的效果,在设置关键帧的时候采用了非0的初始旋转角度,有的小伙伴就会问了:”那你直接设置animation-delay: calc( var(--delay-coef) * 0.3s)
的样式不就可以了吗,但是这样会导致在页面刚刚加载完成时,动画效果的卡顿。
基础知识扎实的小伙伴可能也想到了另一个办法:将animation-delay设置为负值
,这样是可以的,负值的animation-delay
会导致动画提前开始,这样当然可行,只是我不喜欢设置为负值(大家可以根据自己喜欢的来)。
这里伪元素的宽高没有很严格的限制,只需要保证其是一个比按钮宽但在旋转时又不完全覆盖整个按钮的长条性。就可以这里我们得到了如下的效果:
可以看到,这里的伪元素不仅把文字盖住了,而且还超出了按钮的区域。接下来我们逐一解决。
首先为按钮添加 overflow: hidden
属性,这样,就不会超出范围了,那如何使其看起来像一个边框呢?关键点来了:再添加一个伪元素将除了“边框”的剩余区域都遮住
。
.button{
overflow: hidden;
}
.button::after{
content: "";
position: absolute;
background-color: var(--button-bgc);
inset: 4px;
}
这里使用了 inset属性
对内容区域进行了裁剪(参见inset属性),到这里,可能有的小伙伴会发现并没有像目标效果一样,而是出现了像如下的全屏混乱效果(眼见的小伙伴可能在上一步就发现了这个问题):
这是因为,我们在设置伪元素时,要为其父元素添加相对定位(一般没有其他需求时是这样),不然伪元素就会寻找其最近的设置祖先定位元素。
.button{
position:relative;
}
进行如以上补充后如图:
这里的边框效果看似就完成了,但是我们发现,原来的文字效果被覆盖住了。这里就需要用到层叠上下文的内容了,可以参考 深入理解CSS中的层叠上下文和层叠顺序。这里我们通过设置不同的z-index
来改变这一现状。
.button-text{
position: relative;
z-index: 1;
}
接下来我们进行鼠标悬浮时的效果。
.button{
transition: 0.5s;
}
.button:hover {
background-color: var(--border-color);
box-shadow: 0 0 30px var(--border-color),
0 0 50px var(--border-color);
}
.button:hover::after {
background-color: var(--border-color);
}
.button:hover>.button-text {
opacity: 1;
transition: 0.5s;
}
这里就实现了目标的效果。
方法二:使用clip-path
上一次实现边框的伸缩动画时,就使用了这个属性。我们通过关键帧改变其属性值就可以实现类似的效果。这里虽然也是使用了伪元素,但是旋转的并不是伪元素本身,所有我把它单独分出来了。这里不过多解释。
clip-path边框线条旋转
源代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>clip-path边框线条旋转</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: hsl(230, 50%, 15%);
}
.container {
display: flex;
justify-content: center;
align-items: center;
}
.content {
position: relative;
width: 300px;
height: 150px;
font-size: 1.5rem;
padding: 1em;
background-color: hsl(179, 43%, 79%);
}
.content::after,
.content::before {
content: "";
position: absolute;
box-sizing: border-box;
width: 100%;
height: 100%;
left: 0;
top: 0;
border: 5px;
clip-path: inset(0 0 0 0);
border: 5px solid hsl(192, 100%, 50%);
animation: animate 3s linear infinite;
}
.content::after {
animation-delay: -1.5s;
}
@keyframes animate {
0%,
100% {
clip-path: inset(0 98% 0 0);
}
25% {
clip-path: inset(0 0 98% 0);
}
50% {
clip-path: inset(0 0 0 98%);
}
75% {
clip-path: inset(98% 0 0 0);
}
}
</style>
</head>
<body>
<div class="container">
<p class="content">这是一段文字,下面要使用 clip-path 属性来实现边框的旋转动画</p>
</div>
</body>
</html>
方法三:使用filter属性
接下来使用 filter属性
实现渐变的边框线条旋转。
filter实现边框渐变线条旋转
我们可以直接地通过border-image属性
来设置边框,但是我们并不去转动它,而是通过filter属性
为其增加一个滤镜,然后变化这个滤镜即可。hue
是色相,0至360deg代表了从红(0deg)到绿(120deg)到蓝(240deg)再回到红的色相变化。我们通过关键帧来实现这样的变化。
.content {
border: 5px solid;
border-image: linear-gradient(45deg, hsl(358, 95%, 77%), hsl(43, 95%, 77%), hsl(59, 98%, 95%), hsl(191, 92%, 79%), hsl(197, 95%, 52%), hsl(244, 84%, 76%), hsl(43, 95%, 77%)) 1;
}
@keyframes animate {
0% {
filter: hue-rotate(0deg);
}
100% {
filter: hue-rotate(360deg);
}
}
因为这个动画是给整个容器添加的,所以这个容器内的所有颜色(除了 #fff 、#000 以及 transparent)都会受到影响。因此我们可以同时实现背景或文字等的同时渐变。我们这里展示文字渐变——添加以下属性:
.content {
background: linear-gradient(45deg, #ffadad, #ffd65a, #fdffb6, #9bf6ff, #10c4ff, #bdb2ff, #ffc626);
background-clip: text;
-webkit-text-fill-color: transparent;
}
效果如下:
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>filter属性实现边框线条旋转</title>
<style>
* {
padding: 0;
margin: 0;
}
body {
height: 100vh;
display: flex;
justify-content: center;
background-color: hsl(230, 50%, 15%);
align-items: center;
}
.content {
width: 300px;
font-size: 1.5rem;
padding: 1em;
background: linear-gradient(45deg, hsl(358, 95%, 77%), hsl(43, 95%, 77%), hsl(59, 98%, 95%), hsl(191, 92%, 79%), hsl(197, 95%, 52%), hsl(244, 84%, 76%), hsl(43, 95%, 77%));
background-clip: text;
-webkit-text-fill-color: transparent;
border: 5px solid;
border-image: linear-gradient(45deg, hsl(358, 95%, 77%), hsl(43, 95%, 77%), hsl(59, 98%, 95%), hsl(191, 92%, 79%), hsl(197, 95%, 52%), hsl(244, 84%, 76%), hsl(43, 95%, 77%)) 1;
animation: animate 3s linear infinite;
}
@keyframes animate {
0% {
filter: hue-rotate(0deg);
}
100% {
filter: hue-rotate(360deg);
}
}
</style>
</head>
<body>
<main class="containter">
<p class="content">这是一段文字,下面要使用 filter 属性来实现边框的旋转动画</p>
</main>
</body>
</html>
结语
创作不易,感谢大家支持和喜欢,如有错误,恳请指出,希望与大家共同进步。