Home > Back-end >  Make a ball bounce with decreasing height of each successive bounce using just CSS and HTML
Make a ball bounce with decreasing height of each successive bounce using just CSS and HTML

Time:05-16

I am trying to make a ball bounce using just HTML and CSS and hopefully not needing Javascript. I was able to make a simple bounce (see #ball), with some horizontal motion. The Bezier curve timing function helps to make it natural. However, I am having trouble making successive bounces decrease in height - see #ball2. I have tried the following (both #ball and #ball2 are shown below), but the bounce for #ball2 does not look natural. (I also tried animating the height of the div that "holds" the ball but it didn't work for some reason.) Also, there is another problem: when I put 100% for the height of the ball's bounce in the keyframes, it measures the height of the ball, not the parent div, and takes 100% of that (so 100% of 100px).
I suspect the main reason why the bounce does not look natural in #ball2 is that I have put the Bezier curve wrongly in the keyframes. I put cubic-bezier(0.5, 1, 0.05, 0.5) for the upward part of the bounce, but don't think this is right. I think cubic-bezier(0.5, 0.05, 1, 0.5) works well for the downward bounce (see #ball), and the animation-direction of "alternate" makes sure the cubic-bezier works well for the reverse direction of the bounce in the case of #ball. (But with #ball there is no change in the height of the bounces.) I have tried "ease-out" timing function for the bounce up in the case of #ball2 but it still did not look right.

html, body {
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

body {
  display: flex;
 flex-direction: column;
  align-items: center;
}

#div1{
 width: 100vw;
 height: 100vh;
 background: gray;
  display: flex;
 flex-direction: column reverse;
align-items: flex-end;
  position: relative;
   animation: slide 3s linear forwards; 
}

#div2{
 width: 100%;
 height: 100%;
 background: gray;
  display: flex;
 flex-direction: column reverse;
 align-items: flex-end;
  position: absolute;
}

@keyframes slide{
  0%{ transform: translate3d(0, 0, 0);}
    10%{ transform: translate3d(-30px, 0, 0);}
    20%{ transform: translate3d(-60px, 0, 0);}
    30%{ transform: translate3d(-90px, 0, 0);}
    40%{ transform: translate3d(-120px, 0, 0);}
    50%{ transform: translate3d(-150px, 0, 0);}
    60%{ transform: translate3d(-180px, 0, 0);}
    70%{ transform: translate3d(-210px, 0, 0);}
    80%{ transform: translate3d(-240px, 0, 0);}
    90%{ transform: translate3d(-270px, 0, 0);}
    100%{ transform: translate3d(-300px, 0, 0);}
}

#ball{
    height: 100px;
    width: 100px;
    border-radius: 50%;
    right: 100px;
    top:200px;
    position: absolute;
    background-color:  pink;
    animation: bounce .5s alternate cubic-bezier(0.5, 0.05, 1, 0.50) 16;
    transform-box: border-box;
    }

@keyframes bounce {
  0%{transform:  translate(0,-200%);}
  100%{transform:  translate(0, 0);}
}

#ball2{
    height: 100px;
    width: 100px;
    border-radius: 50%;
    right: 100px;
    top:200px;
    position: absolute;
    background-color:  pink;
    animation: bounce2 2s,bezier 2s steps(6) ;
}

@keyframes bezier {
 0% {animation-timing-function: cubic-bezier(0.5, 0.05, 1, 0.50);}
 20% {animation-timing-function: cubic-bezier(0.5, 1, 0.05, 0.50);}
40% {animation-timing-function: cubic-bezier(0.5, 0.05, 1, 0.50);}
60% {animation-timing-function: cubic-bezier(0.5, 1, 0.05, 0.50);}
80% {animation-timing-function: cubic-bezier(0.5, 0.05, 1, 0.50);}
100% {animation-timing-function: cubic-bezier(0.5, 1, 0.05, 0.50);}
}

@keyframes bounce2 {
  0%{transform:  translate(0,-300%);} 
  20%{transform:  translate(0, 0);}
  40%{transform:  translate(0,-150%);}
  60%{transform:  translate(0, 0);}
  80% {transform:  translate(0,-75%);}
  100%{transform:  translate(0, 0);} 
}






   
<div id="div1">
   <div id="div2">
      <div id="ball2"></div>
   </div>
</div>

CodePudding user response:

I tried to play with height and width values. I think it can help you.

@keyframes bounce2 {
  0% {
    transform: translate(0, -300%);
    height: 120px;
  }
  12% {
    height: 120px;
  }
  20% {
    transform: translate(0, 0);
    height: 90px;
    width: 110px;
  }
  40% {
    transform: translate(0, -150%);
    height: 110px;
    width: 100px;
  }
  50% {
    height: 110px;
    width: 100px;
  }
  60% {
    transform: translate(0, 0);
    height: 95px;
    width: 105px;
  }
  80% {
    transform: translate(0, -75%);
    height: 95px;
  }
  100% {
    transform: translate(0, 0);
  }
}

CodePudding user response:

Looks like there is no systematic way to achieve this with CSS and HTML and by using Bezier curves like I tried to. Looking at the examples Bouncing ball with CSS keyframes and Creating an Animated 3D Bouncing Ball with CSS3 of bouncing balls, it seems the only way, if one wants to stick to HTML and CSS, is to play around with different values of height and timing until the right sort of bouncing effect is obtained. They have gotten very good results at these sites.

  • Related