How to animate gradient background smoothly

后端 未结 3 1360
Happy的楠姐
Happy的楠姐 2021-01-29 15:29

I want to achieve an effect than when the user hovers over a div, it\'s background color turns into a gradient that smoothly switches from one corner to the other, repeatedly, u

3条回答
  •  走了就别回头了
    2021-01-29 15:41

    As already pointed out in comments, linear gradients are not transitionable or animatable unlike colors (background-color) because they are considered as image (background-image). Transitions effects are generally achieved by the UA calculating the value at each intermediate stage and then applying that value to the element. In case of an image, it is not possible to calculate the values at intermediate stages and hence they cannot be transitioned.

    You need to transition the position (background-position) instead to achieve the effect. This can be done by using a pseudo-element whose background contains the linear-gradient and animating its position on hover. The gradient should go both ways (that is, it should go from rgba(215,54,92,0.9) to rgba(215,54,92,0.5) and then to rgba(215,54,92,0.9)) because it needs to accommodate both phases of the animation and its background-size also needs to be double (that is 200% 200%). Then by animating the positon from 0% 100% to 100% 0% the required effect can be achieved.

    #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%;
      }
    }
    
    


    Another slightly different approach that can be used is to add two pseudo-elements with each having one stage of animation's gradient and then animate their opacity such that at any point of time only one of them will be visible. This would also produce a similar effect.

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

提交回复
热议问题