CSS @keyframe Animation 移除整个按钮而不仅仅是边框
CSS @keyframe Animation Removing whole button instead of just border
我有一个 CSS 勾勒出按钮边框的关键帧动画。但是,当我尝试在鼠标关闭时反转动画时,它会删除插入框阴影而不是渐变边框。
正如您在下面看到的,我尝试在 mouseLeaveAnimationClass
中再次设置边框和背景。那也不能解决问题。这个问题有没有优雅的解决方案?
var els = document.querySelectorAll('.get-started');
for (var i = 0; i < els.length; i++) {
els[i].addEventListener('mouseleave', function(e) {
e.target.classList.add('mouseleaveAnimationClass');
});
els[i].addEventListener('mouseenter', function(e) {
e.target.classList.remove('mouseleaveAnimationClass');
});
}
body {
background-color: black;
}
#button {
display: flex;
font-size: 2.5rem;
color: white;
align-items: center;
justify-content: center;
width: 250px;
height: 75px;
position: relative;
top: -30%;
left: calc(50% - 125px);
}
.get-started {
--borderWidth: 5px;
position: relative;
border-radius: var(--borderWidth);
background-color: #8551FF;
box-shadow: inset 0 0 0 5px white;
z-index: 1;
}
.get-started:after {
content: '';
position: absolute;
}
.get-started:hover:after {
background: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82);
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 2px;
background-size: 300% 300%;
animation: frame-enter 1s forwards ease-in-out reverse, gradient-animation 4s ease-in-out infinite;
}
.get-started.mouseleaveAnimationClass {
background: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82);
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 2px;
background-size: 300% 300%;
animation: frame-enter 1s forwards ease-in-out;
}
/* motion */
@keyframes gradient-animation {
0% {
background-position: 15% 0%;
}
50% {
background-position: 85% 100%;
}
100% {
background-position: 15% 0%;
}
}
@keyframes frame-enter {
0% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), 5px calc(100% - 5px), 5px 100%, 100% 100%, 100% 0%, 0% 0%);
}
25% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) 100%, 100% 100%, 100% 0%, 0% 0%);
}
50% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, 100% 0%, 0% 0%);
}
75% {
-webkit-clip-path: polygon(0% 100%, 5px 100%, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 0%, 0% 0%);
}
100% {
-webkit-clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
}
<div class="get-started" id="button">Get Started</div>
在您的原始问题中,.get-started.mouseleaveAnimationClass {
规则应用于元素本身,而不应用于 ::after
伪元素,这就是元素被剪裁的原因。但是,这不会解决您的主要问题 - 反向动画。
我已经用一个不是超级 DRY 的解决方案更新了你的代码,你可能可以改进它。
仅在第一次悬停时,.ready
class 被添加到按钮。这会启用 frame-leave
动画,但不会 运行。每当您 :hover
元素时,都会应用 frame-enter
动画,一旦您离开该元素,就会再次调用 frame-leave
。
备注:
frame-enter
和frame-leave
是同一个动画。使用不同的名称可以让我们替换它们。
- 当你在动画中间进入然后离开时,它会从进入动画跳到离开动画。
var els = document.querySelectorAll('.get-started');
for (var i = 0; i < els.length; i++) {
els[i].addEventListener('mouseenter', function(e) {
e.target.classList.add('ready');
}, { once: true });
}
#button {
display: flex;
font-size: 2.5rem;
color: white;
align-items: center;
justify-content: center;
width: 250px;
height: 75px;
position: relative;
top: -30%;
left: calc(50% - 125px);
}
.get-started {
--borderWidth: 5px;
position: relative;
border-radius: var(--borderWidth);
background-color: #8551FF;
box-shadow: inset 0 0 0 5px white;
z-index: 1;
}
.get-started::after {
content: '';
position: absolute;
background: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82);
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 2px;
background-size: 300% 300%;
clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
.get-started.ready::after {
animation: frame-leave 1s forwards ease-in-out, gradient-animation 4s ease-in-out infinite;
}
.get-started.ready:hover::after {
animation: frame-enter 1s forwards ease-in-out reverse, gradient-animation 4s ease-in-out infinite;
}
/* motion */
@keyframes gradient-animation {
0% {
background-position: 15% 0%;
}
50% {
background-position: 85% 100%;
}
100% {
background-position: 15% 0%;
}
}
@keyframes frame-enter {
0% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), 5px calc(100% - 5px), 5px 100%, 100% 100%, 100% 0%, 0% 0%);
}
25% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) 100%, 100% 100%, 100% 0%, 0% 0%);
}
50% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, 100% 0%, 0% 0%);
}
75% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 0%, 0% 0%);
}
100% {
clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
}
@keyframes frame-leave {
0% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), 5px calc(100% - 5px), 5px 100%, 100% 100%, 100% 0%, 0% 0%);
}
25% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) 100%, 100% 100%, 100% 0%, 0% 0%);
}
50% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, 100% 0%, 0% 0%);
}
75% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 0%, 0% 0%);
}
100% {
clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
}
<div class="get-started" id="button">Get Started</div>
我有一个 CSS 勾勒出按钮边框的关键帧动画。但是,当我尝试在鼠标关闭时反转动画时,它会删除插入框阴影而不是渐变边框。
正如您在下面看到的,我尝试在 mouseLeaveAnimationClass
中再次设置边框和背景。那也不能解决问题。这个问题有没有优雅的解决方案?
var els = document.querySelectorAll('.get-started');
for (var i = 0; i < els.length; i++) {
els[i].addEventListener('mouseleave', function(e) {
e.target.classList.add('mouseleaveAnimationClass');
});
els[i].addEventListener('mouseenter', function(e) {
e.target.classList.remove('mouseleaveAnimationClass');
});
}
body {
background-color: black;
}
#button {
display: flex;
font-size: 2.5rem;
color: white;
align-items: center;
justify-content: center;
width: 250px;
height: 75px;
position: relative;
top: -30%;
left: calc(50% - 125px);
}
.get-started {
--borderWidth: 5px;
position: relative;
border-radius: var(--borderWidth);
background-color: #8551FF;
box-shadow: inset 0 0 0 5px white;
z-index: 1;
}
.get-started:after {
content: '';
position: absolute;
}
.get-started:hover:after {
background: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82);
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 2px;
background-size: 300% 300%;
animation: frame-enter 1s forwards ease-in-out reverse, gradient-animation 4s ease-in-out infinite;
}
.get-started.mouseleaveAnimationClass {
background: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82);
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 2px;
background-size: 300% 300%;
animation: frame-enter 1s forwards ease-in-out;
}
/* motion */
@keyframes gradient-animation {
0% {
background-position: 15% 0%;
}
50% {
background-position: 85% 100%;
}
100% {
background-position: 15% 0%;
}
}
@keyframes frame-enter {
0% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), 5px calc(100% - 5px), 5px 100%, 100% 100%, 100% 0%, 0% 0%);
}
25% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) 100%, 100% 100%, 100% 0%, 0% 0%);
}
50% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, 100% 0%, 0% 0%);
}
75% {
-webkit-clip-path: polygon(0% 100%, 5px 100%, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 0%, 0% 0%);
}
100% {
-webkit-clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
}
<div class="get-started" id="button">Get Started</div>
在您的原始问题中,.get-started.mouseleaveAnimationClass {
规则应用于元素本身,而不应用于 ::after
伪元素,这就是元素被剪裁的原因。但是,这不会解决您的主要问题 - 反向动画。
我已经用一个不是超级 DRY 的解决方案更新了你的代码,你可能可以改进它。
仅在第一次悬停时,.ready
class 被添加到按钮。这会启用 frame-leave
动画,但不会 运行。每当您 :hover
元素时,都会应用 frame-enter
动画,一旦您离开该元素,就会再次调用 frame-leave
。
备注:
frame-enter
和frame-leave
是同一个动画。使用不同的名称可以让我们替换它们。- 当你在动画中间进入然后离开时,它会从进入动画跳到离开动画。
var els = document.querySelectorAll('.get-started');
for (var i = 0; i < els.length; i++) {
els[i].addEventListener('mouseenter', function(e) {
e.target.classList.add('ready');
}, { once: true });
}
#button {
display: flex;
font-size: 2.5rem;
color: white;
align-items: center;
justify-content: center;
width: 250px;
height: 75px;
position: relative;
top: -30%;
left: calc(50% - 125px);
}
.get-started {
--borderWidth: 5px;
position: relative;
border-radius: var(--borderWidth);
background-color: #8551FF;
box-shadow: inset 0 0 0 5px white;
z-index: 1;
}
.get-started::after {
content: '';
position: absolute;
background: linear-gradient(60deg, #f79533, #f37055, #ef4e7b, #a166ab, #5073b8, #1098ad, #07b39b, #6fba82);
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 2px;
background-size: 300% 300%;
clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
.get-started.ready::after {
animation: frame-leave 1s forwards ease-in-out, gradient-animation 4s ease-in-out infinite;
}
.get-started.ready:hover::after {
animation: frame-enter 1s forwards ease-in-out reverse, gradient-animation 4s ease-in-out infinite;
}
/* motion */
@keyframes gradient-animation {
0% {
background-position: 15% 0%;
}
50% {
background-position: 85% 100%;
}
100% {
background-position: 15% 0%;
}
}
@keyframes frame-enter {
0% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), 5px calc(100% - 5px), 5px 100%, 100% 100%, 100% 0%, 0% 0%);
}
25% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) 100%, 100% 100%, 100% 0%, 0% 0%);
}
50% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, 100% 0%, 0% 0%);
}
75% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 0%, 0% 0%);
}
100% {
clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
}
@keyframes frame-leave {
0% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), 5px calc(100% - 5px), 5px 100%, 100% 100%, 100% 0%, 0% 0%);
}
25% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) 100%, 100% 100%, 100% 0%, 0% 0%);
}
50% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, calc(100% - 5px) 5px, 100% 0%, 0% 0%);
}
75% {
clip-path: polygon(0% 100%, 5px 100%, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 5px, 5px 0%, 0% 0%);
}
100% {
clip-path: polygon(0% 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 5px 100%, 0% 100%);
}
}
<div class="get-started" id="button">Get Started</div>