Arian Faurtosh Arian Faurtosh - 6 months ago 55
CSS Question

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.

Answer

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>