如何平滑地为渐变背景设置动画

时间:2015-11-25 14:00:50

标签: html css css3 linear-gradients

我希望实现一种效果,而不是当用户将鼠标悬停在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时不断重复。

3 个答案:

答案 0 :(得分:5)

正如评论中已经指出的那样,线性渐变不像颜色(background-color)那样是可转换的或动画的,因为它们被视为图像(background-image)。过渡效应通常通过UA计算每个中间阶段的值然后将该值应用于元素来实现。如果是图像,则无法计算中间阶段的值,因此无法进行转换。

您需要转换位置(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%的位置,可以实现所需的效果。

&#13;
&#13;
#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%;
  }
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="test"></div>
&#13;
&#13;
&#13;

可以使用的另一种稍微不同的方法是添加两个伪元素,每个伪元素具有一个动画阶段的渐变,然后为它们opacity设置动画,使得在任何时间点只有其中一个将是可见的。这也会产生类似的效果。

&#13;
&#13;
#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;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="test"></div>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

要为背景设置动画,您需要修改背景位置。

要使转换顺利进行,您需要使用不透明度 - 并且由于您不希望所有元素都褪色,因此您需要为此使用伪元素

&#13;
&#13;
#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;}
}
&#13;
<div id="test"></div>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

如何使用关键帧设置渐变颜色的动画:

// 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>