Creating an Animated 3D Bouncing Ball with CSS3

In this tutorial we’ll create an animated 3D bouncing ball using only CSS3 transitions, animations and shadow effects.

Creating an Animated 3D Bouncing Ball with CSS3

Hi guys! Today we are going to see another great example of how to use the power of CSS3. We will start by creating a very cool and realistic 3D ball with pure CSS3 properties, and add a little CSS3 animations for giving the ball a “bouncing” effect.

Please note: the result of this tutorial will only work as intended in browsers that support the respective CSS properties.

The HTML

Let’s start with some very basic HTML:

<div id="ballWrapper">
	<div id="ball"></div>
	<div id="ballShadow"></div>			
</div>	

What we have here are 3 simple DIV elements. “#ballWrapper” is the main DIV which wraps the ball. This DIV will determine the ball’s position and height on the screen. Next, we have the “#ball” element which is the ball markup, and finally there is the “#ballShadow” which holds the ball’s shadow separately from the ball itself.

The CSS

Note that we won’t be using vendor prefixes in the tutorial. You will, of course, find them in the files.

First, we’ll want to set a basic width and height to our ‘#ballWrapper’ DIV. It will help us position it to the center of the screen:

#ballWrapper {
	width: 140px;
	height: 300px;
	position: fixed;
	left: 50%;
	top: 50%;
	margin: -150px 0 0 -70px;
}

Note that I gave the DIV both top and left position properties of ‘50%’, and a negative top and left margin which is calculated to be exactly half of the original height and width of the DIV. That way we can center the ball on the screen.

Next in line, let’s give our ball some styles (grow up, it’s not that funny… :])

#ball {
	width: 140px;
	height: 140px;
	border-radius: 70px;
	background: linear-gradient(top,  rgba(187,187,187,1) 0%,rgba(119,119,119,1) 99%);
	box-shadow: inset 0 -5px 15px rgba(255,255,255,0.4), 
				inset -2px -1px 40px rgba(0,0,0,0.4), 
				0 0 1px #000;	
}

We are giving the ball equal width and height and a ‘border-radius’ property with a value of ’70px’ (which is half of the original width and height we’ve set) so it will be a ball and not an oval shape.


Another thing you’ll notice is the background. I gave the ball’s element a linear background and 3 different box shadow levels so it would get the 3D effect. The first box shadow level is for the dark shadowing at the bottom of the ball (see image). Then, we have the second level that is responsible for the blurry glow – again, at the bottom of the ball. Finally the third level is a hardly noticeable blurry shadow behind the contours of the ball.

If you take a look at the ball you’ll notice that there is another small oval shape on top of the ball that gives it a reflection effect. Here is how I created it:

#ball::after {
	content: "";
	width: 80px; 
	height: 40px; 
	position: absolute;
	left: 30px;
	top: 10px;	
	background: linear-gradient(top,  rgba(232,232,232,1) 0%,rgba(232,232,232,1) 1%,rgba(255,255,255,0) 100%);
	border-radius: 40px / 20px;	
}

I used the CSS pseudo element ::after and gave it a linear gradient with an opacity. In addition, I’ve set the border radius to ’40px / 20px’ so it has an oval shape.

Next, let’s handle the ball’s shadow:

 #ballShadow {
	width: 60px;
	height: 75px;
	position: absolute;
	z-index: 0;
	bottom: 0;
	left: 50%;
	margin-left: -30px;
	background: rgba(20, 20, 20, .1);
	box-shadow: 0px 0 20px 35px rgba(20,20,20,.1);
	border-radius: 30px / 40px;	
}

Again, I used the same properties for centering the shadow, but this time I pinned it to the bottom of ‘#ballWrapper’. I also added a semi-transparent background to it, a fitting box shadow and a border radius.

The bouncing animation

Now let’s take a look at the fun stuff…

I’ll start by adding the animation property to our ball:

#ball {
	animation: jump 1s infinite;
}

All I did was to define the animation’s name (jump), the animation’s duration (1 second) and how many times the animation will happen – in our case we use ‘infinite’ which means that it will run forever.

The animation itself:

@keyframes jump {
	0% {
		top: 0;
	}
	50% {
		top: 140px;
		height: 140px;
	}
	55% {
		top: 160px; 
		height: 120px; 
		border-radius: 70px / 60px;
	}
	65% {
		top: 120px; 
		height: 140px; 
		border-radius: 70px;
	}
	95% {
		top: 0;
	}
	100% {
		top: 0;
	}
}

So, basically what I’m doing here is to play with the ‘top’ position property of the ball. Starting from 0, through 160 and back to 0. You’ll notice that in the middle of the animation I’m also playing with the ‘border-radius’ property – that way I handle the “impact” of the ball on the ground.

And now the ball’s shadow; first let’s add the shadow’s relevant animation property:

#ballShadow {
	animation: shrink 1s infinite;
}

I used the same values that I used with the ball, only with a different keyframes animation called shrink which looks as follows:

@-keyframes shrink {
	0% {
		bottom: 0;
		margin-left: -30px;
		width: 60px;
		height: 75px;
		background: rgba(20, 20, 20, .1);
		box-shadow: 0px 0 20px 35px rgba(20,20,20,.1);
		border-radius: 30px / 40px;
	}
	50% {
		bottom: 30px;
		margin-left: -10px;
		width: 20px;
		height: 5px;
		background: rgba(20, 20, 20, .3);
		box-shadow: 0px 0 20px 35px rgba(20,20,20,.3);
		border-radius: 20px / 20px;
	}
	100% {
		bottom: 0;
		margin-left: -30px;
		width: 60px;
		height: 75px;
		background: rgba(20, 20, 20, .1);
		box-shadow: 0px 0 20px 35px rgba(20,20,20,.1);
		border-radius: 30px / 40px;
	}
}

In the shadow’s animation I played with different properties then in the ball’s animation. In order to give it all a realistic effect when it comes to the ball’s distance from the floor, I needed to animate the shadow width, height and opacity. While the ball is close to the floor, the shadow needs to be darker and smaller. When the ball jumps up, the shadow should be lighter and bigger.

Last, but not least, let’s add the “click effect” to the ball which makes it appear as if it moves away from us when we click and hold. To achieve this effect, all we have to use is the ‘:active‘ pseudo-class, add a transition and play with the CSS3 transform ‘scale’ property like this:

#ballWrapper {
	transform: scale(1);
	transition: all 5s linear 0s;
}

#ballWrapper:active {
	transform: scale(0);
}

The transition from a transform value of scale(1) to scale(0) will make it look as if the element is moving away from you.

Tagged with:

Daniel Sternlicht

Daniel Sternlicht is a front-end developer based in Israel who has also a great passion for UX and web design. He specializes in CSS3, HTML5, and JavaScript. In his free time you'll find him exploring new web technologies, developing cool web apps and making his wife happy :)

Stay up to date with the latest web design and development news and relevant updates from Codrops.

Feedback 22

Comments are closed.
  1. Very nice idea and natural moves of the css based bouncing ball. I did something “similar”, with a CSS3 animated ball two years ago. Thx for sharing your idea Daniel and greetings from Berlin, Germany!

  2. Amazing , looks purely natural , Well I suppose the only thing now left to be achieved by CSS3 is a full length Animated movie !!

  3. Very nice. I haven’t tried this, but what about instead of adding all those keyframes in the ‘jump’ animation, start and stop the ball at the top of it’s arc and use an ease-in-out to simulate the physics even more naturally. You could even add a little more swash and stretch as it flies back up. Sorry, I’ve been around too many animators. That’s a good looking ball!

  4. Very cool- I am not sure if I wanted to do it myself how many times I had to edit my mistakes- Thanks for sharing

    • Thanks for the heads up Mardeg, I added both -o and -ms to the CSS file.

  5. Amazing ๐Ÿ™‚ I love this effect so much ๐Ÿ™‚ Maybe, I’ll make some cool effects like this for my future WordPress themes ๐Ÿ™‚

  6. Hi Daniel

    Thanks for posting this informative tutorial, I have recently been reading a number of blog posts about css3 animations, and the effects that can be created. The animation you have created strongly resembles the flash animations of a few years ago. As impressive as the script is the one draw back in my opinion is perhaps the lack of functionality.

    Cathy

  7. superb,man!
    and anyway, is it possible to change the ball with a round logo?if so,can you please be kindly to tell me how to do it?

    Thanks!

  8. The sample is occupying more CPU time, which can be seen from task manager… or i am i missing anything here?