如何使用CSS制作渐变动画

48

我想要平滑地移动具有多种颜色的渐变,但问题是动画不够流畅。它只是在每一步改变其位置。

<style>
  .animated {
    width: 300px;
    height: 300px;
    border: 1px solid black;
    animation: gra 5s infinite;
    animation-direction: reverse;
    -webkit-animation: gra 5s infinite;
    -webkit-animation-direction: reverse;
    animation-timing-function: linear;
    -webkit-animation-timing-function: linear;
  }
  
  @keyframes gra {
    0% {
      background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #ff670f), color-stop(21%, #ff670f), color-stop(56%, #ffffff), color-stop(88%, #0eea57));
      background: -webkit-linear-gradient(-45deg, #ff670f 0%, #ff670f 21%, #ffffff 56%, #0eea57 88%);
      background: linear-gradient(135deg, #ff670f 0%, #ff670f 21%, #ffffff 56%, #0eea57 88%);
    }
    50% {
      background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #ff670f), color-stop(10%, #ff670f), color-stop(40%, #ffffff), color-stop(60%, #0eea57));
      background: -webkit-linear-gradient(-45deg, #ff670f 0%, #ff670f 10%, #ffffff 40%, #0eea57 60%);
      background: linear-gradient(135deg, #ff670f 0%, #ff670f 10%, #ffffff 40%, #0eea57 60%);
    }
    100% {
      background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #ff670f), color-stop(5%, #ff670f), color-stop(10%, #ffffff), color-stop(40%, #0eea57));
      background: -webkit-linear-gradient(-45deg, #ff670f 0%, #ff670f 5%, #ffffff 10%, #0eea57 40%);
      background: linear-gradient(135deg, #ff670f 0%, #ff670f 5%, #ffffff 10%, #0eea57 40%);
    }
  }
</style>
<div class="animated">
  <h1>Hello</h1>
</div>

不使用jQuery是否有可能完成?

我的jsfiddle链接是 https://jsfiddle.net/bAUK6


1
好的,我认为你可能想在IE 11上尝试你的演示(不确定IE 10),它可以按照你的预期工作。目前所有其他浏览器都不支持背景动画,但是你可以尝试通过动画background-position来代替,当然这样做不会有整个背景动画的效果。 - King King
这个回答解决了你的问题吗?如何在具有渐变背景的元素上使用CSS3过渡效果 - Mahozad
5个回答

57
请尝试这段代码:

#gradient
{
    height:300px;
    width:300px;
    border:1px solid black;
    font-size:30px;
    background: linear-gradient(130deg, #ff7e00, #ffffff, #5cff00);
    background-size: 200% 200%;

    -webkit-animation: Animation 5s ease infinite;
    -moz-animation: Animation 5s ease infinite;
    animation: Animation 5s ease infinite;
}

@-webkit-keyframes Animation {
    0%{background-position:10% 0%}
    50%{background-position:91% 100%}
    100%{background-position:10% 0%}
}
@-moz-keyframes Animation {
    0%{background-position:10% 0%}
    50%{background-position:91% 100%}
    100%{background-position:10% 0%}
}
@keyframes Animation { 
    0%{background-position:10% 0%}
    50%{background-position:91% 100%}
    100%{background-position:10% 0%}
}
<html>
<div id="gradient">
  Hello
</div>
</html>


完美地完成了工作。 - Chintan Joshi

13

动态实现 Dave 的答案:

:root{
    --overlay-color-1: #ff0000;
    --overlay-color-2: #0000ff;
    --anim-duration: 2s;
}

#gradient {
    opacity: 0.8;
    background: none;
}

#gradient:after,
#gradient:before {
    content: '';
    display: block;
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
}

#gradient:before {
    background: linear-gradient(135deg, var(--overlay-color-2) 0%, var(--overlay-color-1) 100%);
    animation: OpacityAnim var(--anim-duration) ease-in-out 0s infinite alternate;
}

#gradient:after {
    background: linear-gradient(135deg, var(--overlay-color-1) 0%, var(--overlay-color-2) 100%);
    animation: OpacityAnim var(--anim-duration) ease-in-out calc(-1 * var(--anim-duration)) infinite alternate;
}

@keyframes OpacityAnim {
    0%{opacity: 1.0}
    100%{opacity: 0.0}
}
<div id="gradient"></div>


position:fixed; z-index:-1; 添加到 #gradient 中,它将保持在其他元素下方,并可用作背景。我不懂 CSS,但这是对我有效的方法,如果有其他方法,我很乐意听取建议。 - PAEz

12

现在使用CSS变量已经成为一项平凡的任务。

这里是一个基本示例(悬停以查看结果)

@property --a{
  syntax: '<angle>';
  inherits: false;
  initial-value: 90deg;
}
@property --l{
  syntax: '<percentage>';
  inherits: false;
  initial-value: 10%;
}
@property --c{
  syntax: '<color>';
  inherits: false;
  initial-value: red;
}

.box {
  /*  needed for firefox to have a valid output */
  --a:80deg;
  --l:10%;
  --c:red;
  /**/
  cursor:pointer;
  height:200px;
  transition:--a 0.5s 0.1s,--l 0.5s,--c 0.8s;
  background:linear-gradient(var(--a), var(--c) var(--l),blue,var(--c) calc(100% - var(--l)));
}
.box:hover {
  --a:360deg;
  --l:40%;
  --c:green;
}
<div class="box"></div>

更多细节请见:https://dev.to/afif/we-can-finally-animate-css-gradient-kdk


3
请注意,渐变过渡效果目前在Firefox和Safari浏览器上还不能正常工作,这也意味着在iPhone和iPad设备上也无法正常使用。 - M -
2
更具体地说,@property 部分在 Safari 和 Firefox 中不起作用(https://developer.mozilla.org/en-US/docs/Web/CSS/@property)。 - Simon_Weaver
alc 作为变量名真的让人难以理解... 这就像你在试图教授的同时混淆了你的代码。 - undefined

2
这是另一种方式。以下内容包含所有动画阶段的静态渐变,然后将其移动到外部元素内部。这样可以平稳地执行动画(如主题所示),因为此处唯一的动画是元素位置。
请注意,出于性能考虑,渐变元素保持不变。尽管问题是要对渐变进行动画处理,但移动背景实际上可以达到相同的效果,而且性能更佳!

.animated {
    width: 300px;
    height: 300px;
    overflow: hidden;
    position: relative;
    border: 1px solid black;
}
.innerGradient {
    z-index: -1;
    width: 300%;
    height: 300%;
    position: absolute;
    animation: gra 5s infinite;
    -webkit-animation: gra 5s infinite;
    background: linear-gradient(135deg, #ff670f 0%, #ff670f 20%, #ffffff 50%, #0eea57 80%, #0eea57 100%);
    background: -webkit-linear-gradient(135deg, #ff670f 0%, #ff670f 20%, #ffffff 50%, #0eea57 80%, #0eea57 100%);
}
@keyframes gra {
    0% { left: -200%; top: -200%; }
    50% { left: 0%; top: 0%; }
    100% { left: -200%; top: -200%; }
}
<div class="animated">
    <h1>Hello</h1>
    <div class="innerGradient"></div>
</div>


0

这样怎么样:

将body的margin和padding设置为0。将html规则设置为100%高度(可能需要更高)。

将body设置为渐变的结束状态。

创建一个空的div,其背景是渐变的起始状态。给空的div 100%的高度。

给body和空的div都设置background-attachment: fixed;

为你的body内容创建一个包装器。

将空的div设置为position: fixed; 将包装器设置为position: relative; 给两者都设置z-index,其中包装器更高。

创建一个动画,将空的div的不透明度从1变为0,持续所需时间。在div规则中添加animation-fill-mode: forwards;,使动画停留在结束位置。

虽然不如真正的动态渐变效果那么吸引人,但我认为这是只用CSS和关键帧最简单的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接