Search code examples
csssvgcss-animationscss-shapes

Filling water animation


I am trying to get a wipe up animation to make a circle look like it's filling with water. I've run into two errors, and haven't been able to even tackle the 3rd one:

  1. It fills up the wrong way
  2. It resets to empty (black) after it has filled *
  3. For now, I am using the <img> tags, but I would like to move this effect to body { background-image: } and need some direction on how to do this.

What I have tried so far:

#banner {
  width: 300px;
  height: 300px;
  position: relative;
}
#banner div {
  position: absolute;
}
#banner div:nth-child(2) {
  -webkit-animation: wipe 6s;
  -webkit-animation-delay: 0s;
  -webkit-animation-direction: up;
  -webkit-mask-size: 300px 3000px;
  -webkit-mask-position: 300px 300px;
  -webkit-mask-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.00, rgba(0, 0, 0, 1)), color-stop(0.25, rgba(0, 0, 0, 1)), color-stop(0.27, rgba(0, 0, 0, 0)), color-stop(0.80, rgba(0, 0, 0, 0)), color-stop(1.00, rgba(0, 0, 0, 0)));
}
@-webkit-keyframes wipe {
  0% {
    -webkit-mask-position: 0 0;
  }
  100% {
    -webkit-mask-position: 300px 300px;
  }
}
<div id="banner">
  <div>
    <img src="http://i.imgur.com/vklf6kK.png" />
  </div>
  <div>
    <img src="http://i.imgur.com/uszeRpk.png" />
  </div>
</div>


Giving it a default mask position as @anpsmn suggested, doesn't reset it to black anymore.


Solution

  • This can be achieved with a single div and a ::before pseudo element:

    • The #banner is given border-radius: 50% to create a circle and overflow: hidden to clip its children inside it

    • The ::before pseudo element is animated to 100% height and the animation is paused at 100% using the forwards value. It begins at the bottom with the use of bottom: 0

    • The background images would be applied in place of the black and blue backgrounds on #banner and #banner::before

    Compatibility: IE10+ and all modern browsers. The -webkit- prefixed property is most likely no longer necessary for your keyframe animations. Check the browser compatibility chart over here on caniuse.com

    Working Example

    I have added the cubic-bezier(.2,.6,.8,.4) which is explained in @ChrisSpittles answer. It provides a neat effect!

    #banner {
      width: 300px;
      height: 300px;
      position: relative;
      background: #000;
      border-radius: 50%;
      overflow: hidden;
    }
    #banner::before {
      content: '';
      position: absolute;
      background: #04ACFF;
      width: 100%;
      bottom: 0;
      animation: wipe 5s cubic-bezier(.2,.6,.8,.4) forwards;
    }
    @keyframes wipe {
      0% {
        height: 0;
      }
      100% {
        height: 100%;
      }
    }
    <div id="banner">
    
    </div>