【问题标题】:Animating Linear Gradient using CSS使用 CSS 动画线性渐变
【发布时间】:2014-06-19 21:36:54
【问题描述】:

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

<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

【问题讨论】:

  • 好吧,我想您可能想在 IE 11 上尝试您的演示(不确定 IE 10),它可以按预期工作。目前所有其他浏览器都不支持背景动画,您可以尝试为background-position 设置动画但是当然这不会通过对整个背景进行动画来获得所有效果。

标签: html css css-animations linear-gradients


【解决方案1】:

使用 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;
}
&lt;div class="box"&gt;&lt;/div&gt;

更多详情:https://dev.to/afif/we-can-finally-animate-css-gradient-kdk

【讨论】:

  • 仅供参考,渐变过渡不适用于 Firefox 或 Safari,这意味着它也不适用于 iPhone 和 iPad。
【解决方案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>

【讨论】:

    【解决方案3】:

    Dave's answer的动态实现:

    :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}
    }
    &lt;div id="gradient"&gt;&lt;/div&gt;

    【讨论】:

      【解决方案4】:

      这个怎么样:

      将正文边距和内边距设置为 0。将 html 规则设置为 100% 高度(可能需要高于 100%)。

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

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

      给 body 和空 div 一个 background-attachment: fixed;

      为您的正文内容创建一个包装器。

      将空 div 设置为 position: fixed; 将包装器设置为位置:相对; 给两个 z-index,包装更高。

      创建一个动画,在所需时间内将空 div 的不透明度从 1 更改为 0。添加动画填充模式:转发;到 div 规则,所以动画停留在它结束的地方。

      它不像真正的动画渐变转换那样性感,但我认为它就像你可以通过仅使用 CSS 和关键帧获得的一样简单。

      【讨论】:

        【解决方案5】:

        请试试这个代码:

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

        【讨论】:

        • 完美地完成了这项工作。