0

I have a simple react app with a div containing an SVG ball image. Upon hovering on the image, I want it to rotate and move left simultaneously smoothly. When hover state is false, I want it to rotate and roll back to its initial position.

I'm struggling to combine both effects in CSS.

BallRoll.js

 <div className="ball-holder">
              <img
                src={rollingBall}
                loading="lazy"
                width="223"
                alt="rolling Ball"
                className="ball"
              />
   </div>

I'm a bit lost on the css, can't figure out a proper way to combine everything. ball.css

.ball {
 display: block;
transition: 1s ease-in-out;
}

.ball:hover {
animation: animate2 5s linear; 
}
 @keyframes animate2 {
    0%{
        transform: rotate(0deg);
        left:0;
    }
    50%{
        transform: rotate(360deg);
        left:calc(100% - 50px);
    }
    100%{
        transform: rotate(0deg);
        left:0;
    }

They are not perfect, work fine individually, but not together. Any better suggestions and help?

  • You can add the position like this `transform : translateX(200px) rotate(45deg);`. You don't need `left`. – Kokodoko Aug 12 '22 at 13:53
  • I tried that, it happens so fast and not smooth at all. I can't tell if it actually rotates or not –  Aug 12 '22 at 13:59
  • If you need different timing for the horizontal and rotation animations, I would suggest creating a child div that holds the ball image. Then you rotate the child div slowly. Then you can move the parent div horizontally with a different speed. – Kokodoko Aug 12 '22 at 14:01
  • Is it possible for you to give an example? I've been fiddling around for quite some time but I can't figure out a good way to implement this –  Aug 12 '22 at 14:06
  • I created an example in my answer – Kokodoko Aug 12 '22 at 14:15

2 Answers2

0

Here is a working example.

One thing to note is that if you apply the affect only on hover of the ball, then as soon as the ball moves the hover will end and it will go back to non-hover state, causing just a quick flicker. For that reason I activate the animation when the ball holder is hovered.

.ball {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: linear-gradient(teal, #000);
}

.ball {
  display: block;
  transition: all 2s;
}

.ball-holder:hover .ball {
  transform: translateX(calc(100vw - 80px)) rotate(360deg);
}
<div class="ball-holder">
  <div class="ball"></div>
</div>
H K
  • 1,062
  • 8
  • 10
  • Perfect! Thank you so much, this is the very simple and I understood your code. Thanks a lot. –  Aug 12 '22 at 14:31
0

If you create two separate containers, you can animate them separately

* {
  box-sizing: border-box;
}

body {
  margin: 0; padding:0;
  font-family: system-ui, sans-serif;
  color: black;
  background-color: white;
}

#ball {
  animation: roll 5s linear; 
}

#ball-holder {
  animation: moveLeft 5s linear; 
}
@keyframes moveLeft {
  0%{
      transform: translateX(0px);
  }
  50%{
      transform: translateX(300px);
  }
  100%{
      transform: translateX(0px);
  }
}
@keyframes roll {
  0%{
      transform: rotate(0deg);
  }
  50%{
      transform: rotate(360deg);
  }
  100%{
      transform: rotate(0deg);
  }
}
<div id="ball-holder">
      <img
        id="ball"
        src="https://media.istockphoto.com/photos/soccer-ball-isolated-3d-rendering-picture-id1257575611?k=20&m=1257575611&s=612x612&w=0&h=g530fFJspT42xFGY7HycLvpBKLXpJ2XAkKCRyY-SK80="
        width="200"
        alt="rolling Ball"
        className="ball"
      />
    </div>
Kokodoko
  • 26,167
  • 33
  • 120
  • 197
  • 1
    Thank you so much, this is a very good answer :) but I prefer something shorter where I can control both effects in one go. Thank you tho –  Aug 12 '22 at 14:32
  • no probz! the single line is better :) – Kokodoko Aug 13 '22 at 10:00