如何平滑地动画渐变背景
How to animate gradient background smoothly
我想实现一种效果,当用户将鼠标悬停在 div 上时,它的背景颜色变成渐变,从一个角平滑地切换到另一个角,重复使用纯粹 CSS .
我想要达到的效果,更具体地说,只要光标保持在上方,背景的较暗部分(不透明度为 0.9 的部分)就会从一个角反复滑动到另一个角元素。
实际发生的是背景从一种状态跳到另一种状态。我哪里错了?我怎样才能使它成为动画、平滑的效果?
这是我的代码:
#test {
width: 200px;
height: 200px;
background-color: rgba(215, 54, 92, 0.7);
}
@keyframes test_hover {
from {
background: -webkit-linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5)); /* For Safari 5.1 to 6.0 */
background: -o-linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5)); /* For Opera 11.1 to 12.0 */
background: -moz-linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5)); /* For Firefox 3.6 to 15 */
background: linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5)); /* Standard syntax (must be last) */
}
to {
background: -webkit-linear-gradient(45deg, rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9)); /* For Safari 5.1 to 6.0 */
background: -o-linear-gradient(45deg, rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9)); /* For Opera 11.1 to 12.0 */
background: -moz-linear-gradient(45deg, rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9)); /* For Firefox 3.6 to 15 */
background: linear-gradient(45deg, rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9)); /* Standard syntax (must be last) */
}
}
#test:hover {
cursor: pointer;
animation-name: test_hover;
animation-duration: 4s;
animation-delay: 1s;
animation-iteration-count: infinite;
}
<div id="test"></div>
这里是JSFiddle
这个问题被认为是 here 的重复问题,但我认为不是。首先,该问题中没有代码,因此难以理解。另外,在回答那个问题时,他使用了过渡,但我不想要过渡,因为它只应用了一次,我希望我的动画在用户悬停在 div 时不断重复。
要使背景动起来,您需要修改背景位置。
为了使过渡平滑,您需要使用不透明度 - 由于您不希望所有元素都淡出,因此您需要为此使用伪元素
#test{
width: 200px;
height: 200px;
position: relative;
background-color: rgba(215,54,92,0.7);
transition: background-color 1s;
}
#test:hover{
background-color: transparent;
}
#test:after {
content: "";
position: absolute;
left: 0px;
top: 0px;
right: 0px;
bottom: 0px;
z-index: -1;
background-image: linear-gradient(45deg,
rgba(215,54,92,0.5),
rgba(215,54,92,0.9),
rgba(215,54,92,0.5),
rgba(215,54,92,0.9),
rgba(215,54,92,0.5)
);
background-size: 800px 800px;
background-position: 0px 0px;
animation: move 2s infinite linear;
opacity: 0;
transition: opacity 1s;
}
#test:hover:after {
opacity: 1;
}
@keyframes move {
from {background-position: 0px 600px;}
to {background-position: -800px 600px;}
}
<div id="test"></div>
正如评论中已经指出的那样,线性渐变不像颜色 (background-color
) 那样是不可转换的或不可动画的,因为它们被视为图像 (background-image
)。过渡效果通常是通过用户代理计算每个中间阶段的值,然后将该值应用于元素来实现的。在图像的情况下,无法计算中间阶段的值,因此无法转换它们。
您需要转换位置(background-position
)来实现效果。这可以通过使用背景包含 linear-gradient
的伪元素并将其在 hover
上的位置设置为动画来完成。渐变应该是双向的(也就是说,它应该从 rgba(215,54,92,0.9)
到 rgba(215,54,92,0.5)
然后到 rgba(215,54,92,0.9)
)因为它需要适应动画的两个阶段及其 background-size
也需要加倍(即 200% 200%
)。然后通过动画从 0% 100%
到 100% 0%
的位置可以实现所需的效果。
#test {
position: relative;
width: 200px;
height: 200px;
background-color: rgba(215, 54, 92, 0.7);
transition: background-color .1s;
}
#test:hover {
background-color: transparent;
cursor: pointer;
}
#test:hover:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
background: linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9));
background-size: 200% 200%;
background-position: 0% 100%;
animation-name: test_hover;
animation-duration: 4s;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-direction: alternate;
}
@keyframes test_hover {
from {
background-position: 0% 100%;
}
to {
background-position: 100% 0%;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="test"></div>
另一种可以使用的稍微不同的方法是添加两个伪元素,每个伪元素都有一个动画渐变阶段,然后设置它们的 opacity
动画,这样在任何时间点只有其中一个会是可见的。这也会产生类似的效果。
#test {
position: absolute;
width: 200px;
height: 200px;
background-color: rgba(215, 54, 92, 0.7);
transition: background-color .1s;
}
#test:before,
#test:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
z-index: 1;
}
#test:before {
background: linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5));
opacity: 0;
}
#test:after {
background: linear-gradient(45deg, rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9));
opacity: 0;
}
@keyframes test_hover {
0%, 100% {
opacity: 0;
}
50% {
opacity: 1;
}
}
#test:hover:before,
#test:hover:after {
cursor: pointer;
animation-name: test_hover;
animation-duration: 4s;
animation-iteration-count: infinite;
animation-fill-mode: backwards;
}
#test:hover:before {
animation-delay: 1s;
}
#test:hover:after {
animation-delay: 3s;
}
#test:hover {
background-color: transparent;
transition: background-color 2s 1s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="test"></div>
如何使用关键帧设置渐变颜色动画:
// Beggin
#demo {
width: 200px;
height: 200px;
position: absolute;
background: linear-gradient(to right, #f06 0%, #60f 100%);
z-index: 2;
}
/* Use a 'Before' element to change the background */
#demo::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(to left, #f06 0%, #60f 100%);
/* Give it an Opacity of 0 and create your animation property: */
opacity: 0;
animation: bg 2800ms ease-in-out 0s infinite alternate-reverse;
z-index: -1;
}
/* Now call the keyframe-function */
@keyframes bg {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
/* Unnecessary styling: */
h3 {
color: #fff;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -130%);
font-family: Helvetica, Arial, sans-serif;
}
<div id="demo"><h3>CWM</h3></div>
我想实现一种效果,当用户将鼠标悬停在 div 上时,它的背景颜色变成渐变,从一个角平滑地切换到另一个角,重复使用纯粹 CSS .
我想要达到的效果,更具体地说,只要光标保持在上方,背景的较暗部分(不透明度为 0.9 的部分)就会从一个角反复滑动到另一个角元素。
实际发生的是背景从一种状态跳到另一种状态。我哪里错了?我怎样才能使它成为动画、平滑的效果?
这是我的代码:
#test {
width: 200px;
height: 200px;
background-color: rgba(215, 54, 92, 0.7);
}
@keyframes test_hover {
from {
background: -webkit-linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5)); /* For Safari 5.1 to 6.0 */
background: -o-linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5)); /* For Opera 11.1 to 12.0 */
background: -moz-linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5)); /* For Firefox 3.6 to 15 */
background: linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5)); /* Standard syntax (must be last) */
}
to {
background: -webkit-linear-gradient(45deg, rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9)); /* For Safari 5.1 to 6.0 */
background: -o-linear-gradient(45deg, rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9)); /* For Opera 11.1 to 12.0 */
background: -moz-linear-gradient(45deg, rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9)); /* For Firefox 3.6 to 15 */
background: linear-gradient(45deg, rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9)); /* Standard syntax (must be last) */
}
}
#test:hover {
cursor: pointer;
animation-name: test_hover;
animation-duration: 4s;
animation-delay: 1s;
animation-iteration-count: infinite;
}
<div id="test"></div>
这里是JSFiddle
这个问题被认为是 here 的重复问题,但我认为不是。首先,该问题中没有代码,因此难以理解。另外,在回答那个问题时,他使用了过渡,但我不想要过渡,因为它只应用了一次,我希望我的动画在用户悬停在 div 时不断重复。
要使背景动起来,您需要修改背景位置。
为了使过渡平滑,您需要使用不透明度 - 由于您不希望所有元素都淡出,因此您需要为此使用伪元素
#test{
width: 200px;
height: 200px;
position: relative;
background-color: rgba(215,54,92,0.7);
transition: background-color 1s;
}
#test:hover{
background-color: transparent;
}
#test:after {
content: "";
position: absolute;
left: 0px;
top: 0px;
right: 0px;
bottom: 0px;
z-index: -1;
background-image: linear-gradient(45deg,
rgba(215,54,92,0.5),
rgba(215,54,92,0.9),
rgba(215,54,92,0.5),
rgba(215,54,92,0.9),
rgba(215,54,92,0.5)
);
background-size: 800px 800px;
background-position: 0px 0px;
animation: move 2s infinite linear;
opacity: 0;
transition: opacity 1s;
}
#test:hover:after {
opacity: 1;
}
@keyframes move {
from {background-position: 0px 600px;}
to {background-position: -800px 600px;}
}
<div id="test"></div>
正如评论中已经指出的那样,线性渐变不像颜色 (background-color
) 那样是不可转换的或不可动画的,因为它们被视为图像 (background-image
)。过渡效果通常是通过用户代理计算每个中间阶段的值,然后将该值应用于元素来实现的。在图像的情况下,无法计算中间阶段的值,因此无法转换它们。
您需要转换位置(background-position
)来实现效果。这可以通过使用背景包含 linear-gradient
的伪元素并将其在 hover
上的位置设置为动画来完成。渐变应该是双向的(也就是说,它应该从 rgba(215,54,92,0.9)
到 rgba(215,54,92,0.5)
然后到 rgba(215,54,92,0.9)
)因为它需要适应动画的两个阶段及其 background-size
也需要加倍(即 200% 200%
)。然后通过动画从 0% 100%
到 100% 0%
的位置可以实现所需的效果。
#test {
position: relative;
width: 200px;
height: 200px;
background-color: rgba(215, 54, 92, 0.7);
transition: background-color .1s;
}
#test:hover {
background-color: transparent;
cursor: pointer;
}
#test:hover:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
background: linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9));
background-size: 200% 200%;
background-position: 0% 100%;
animation-name: test_hover;
animation-duration: 4s;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-direction: alternate;
}
@keyframes test_hover {
from {
background-position: 0% 100%;
}
to {
background-position: 100% 0%;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="test"></div>
另一种可以使用的稍微不同的方法是添加两个伪元素,每个伪元素都有一个动画渐变阶段,然后设置它们的 opacity
动画,这样在任何时间点只有其中一个会是可见的。这也会产生类似的效果。
#test {
position: absolute;
width: 200px;
height: 200px;
background-color: rgba(215, 54, 92, 0.7);
transition: background-color .1s;
}
#test:before,
#test:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
z-index: 1;
}
#test:before {
background: linear-gradient(45deg, rgba(215, 54, 92, 0.9), rgba(215, 54, 92, 0.5));
opacity: 0;
}
#test:after {
background: linear-gradient(45deg, rgba(215, 54, 92, 0.5), rgba(215, 54, 92, 0.9));
opacity: 0;
}
@keyframes test_hover {
0%, 100% {
opacity: 0;
}
50% {
opacity: 1;
}
}
#test:hover:before,
#test:hover:after {
cursor: pointer;
animation-name: test_hover;
animation-duration: 4s;
animation-iteration-count: infinite;
animation-fill-mode: backwards;
}
#test:hover:before {
animation-delay: 1s;
}
#test:hover:after {
animation-delay: 3s;
}
#test:hover {
background-color: transparent;
transition: background-color 2s 1s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="test"></div>
如何使用关键帧设置渐变颜色动画:
// Beggin
#demo {
width: 200px;
height: 200px;
position: absolute;
background: linear-gradient(to right, #f06 0%, #60f 100%);
z-index: 2;
}
/* Use a 'Before' element to change the background */
#demo::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(to left, #f06 0%, #60f 100%);
/* Give it an Opacity of 0 and create your animation property: */
opacity: 0;
animation: bg 2800ms ease-in-out 0s infinite alternate-reverse;
z-index: -1;
}
/* Now call the keyframe-function */
@keyframes bg {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
/* Unnecessary styling: */
h3 {
color: #fff;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -130%);
font-family: Helvetica, Arial, sans-serif;
}
<div id="demo"><h3>CWM</h3></div>