{"id":673,"date":"2013-01-29T12:22:32","date_gmt":"2013-01-29T18:22:32","guid":{"rendered":"http:\/\/cssnewbie.com\/?p=673"},"modified":"2013-01-29T12:22:32","modified_gmt":"2013-01-29T18:22:32","slug":"pure-css-bouncing-ball","status":"publish","type":"post","link":"https:\/\/cssdeck.com\/blog\/pure-css-bouncing-ball\/","title":{"rendered":"A Pure CSS Bouncing Ball"},"content":{"rendered":"<p><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/cssdeck.com\/blog\/wp-content\/uploads\/2013\/01\/css-bouncing-ball-2.png\" alt=\"css-bouncing-ball-2\" width=\"550\" height=\"315\" class=\"alignnone size-full wp-image-677\" \/><\/p>\n<p>Today we\u2019re going to create a ball that bounces infinitely around its container.<\/p>\n<p>I\u2019ll admit it: the idea for this tutorial was based on two things: first, those corny bouncing ball\/logo\/whatever screensaver animations that are so popular on modern televisions, DVD players, or just about anything else that has &#8212; or outputs to &#8212; a screen. Second, a brief but passionate love affair I had with <a href=\"http:\/\/en.wikipedia.org\/wiki\/Jezzball\" target=\"_blank\" rel=\"noopener noreferrer\">Jezzball<\/a> in 2001.<\/p>\n<p>So if bouncing balls are so old-school, what\u2019s the big whoop? We\u2019ll do ours entirely with CSS.<!--more--><\/p>\n<h3>The HTML<\/h3>\n<p>The HTML we need is pretty minimal: we need an element to be the ball, and we need a container for it to bounce around in. I\u2019m keeping things short and sweet here:<\/p>\n<pre lang=\"html\">\n<div class=\"box\"><b><\/b><\/div>\n<\/pre>\n<p>Like in my <a href=\"http:\/\/cssnewbie.com\/making-a-sphere-in-css\/\" title=\"Making a Sphere in CSS\">sphere tutorial<\/a>, I\u2019m using the good ol&#8217; &lt;b&gt; tag for the ball.<\/p>\n<h3>The Box CSS<\/h3>\n<p>There are three things we need to do here: style the box, style the ball, and animate the ball within the box. We\u2019ll take them in that order.<\/p>\n<p>First up, we\u2019ll give our container some visual interest.<\/p>\n<pre lang=\"css\">\n.box {\n  background-color: #61ab20;\n  margin: 0 auto;\n  width: 500px;\n  height: 300px;\n  position: relative;\n  box-shadow: inset 0 0 3px #000;\n  border-radius: 5px;\n  border: 1px solid #111;\n  overflow: hidden;\n}<\/pre>\n<p>Some of these styles are arbitrary: you can give it any background-color, margin, box-shadow, border, and border-radius you wish. The rest are more important. Our box needs a defined width and height. You can define that in whatever units you want, but it\u2019d be a good idea to define the ball using the same units. And the relative position is critical, because that\u2019s what will <a href=\"http:\/\/cssnewbie.com\/harnessing-positioning-1\/\">allow the ball to move around in its container<\/a>. The hidden overflow is necessary to prevent any \u201cextras\u201d we add to the ball from showing up outside of the box.<\/p>\n<h3>The Ball CSS<\/h3>\n<p>Next, we\u2019ll style the ball:<\/p>\n<pre lang=\"css\">\n.box b {\n  display: block;\n  width: 20px;\n  height: 20px;\n  border-radius: 50%;\n  background-color: #3673cf;\n  box-shadow: inset -5px -5px 5px rgba(0,0,0,.6), 15px 15px 2px rgba(0,0,0,.04);\n  position: absolute;\n}<\/pre>\n<p>The absolute positioning is the most critical bit here: that\u2019s what allows us to move the ball within its container. You\u2019ll also notice a lot of similarities to how <a href=\"http:\/\/cssnewbie.com\/making-a-sphere-in-css\/\" title=\"Making a Sphere in CSS\">we created the sphere<\/a> in the last tutorial. This is a slightly simplified version: I\u2019ve rounded its corners and used an inset box-shadow to create a 3D effect, but at this small size I didn\u2019t bother with any other tweaks. I did, however, add a second box-shadow, which you can see on this line:<\/p>\n<pre lang=\"css\">box-shadow: inset -5px -5px 5px rgba(0,0,0,.6), 15px 15px 2px rgba(0,0,0,.04);<\/pre>\n<p>Some CSS3 properties accept multiple values, separated with a comma, and box-shadow is one of them. The first box-shadow, before the comma, is our shading. The second is a faint shadow to the bottom-right of the ball, which further suggests a light source to the top-left. And by moving the shadow 15 pixels away from the ball, it also gives our box the illusion of depth.<\/p>\n<p>After all that, we\u2019re left with something like this:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/cssdeck.com\/blog\/wp-content\/uploads\/2013\/01\/css-bouncing-ball-1.png\" alt=\"css-bouncing-ball-1\" width=\"550\" height=\"315\" class=\"alignnone size-full wp-image-678\" \/><\/p>\n<p>It\u2019s not much to look at without the animation, so let\u2019s move on.<\/p>\n<h3>The Animation Keyframes<\/h3>\n<p>To animate our ball, we\u2019re going to use CSS keyframes. Keyframes allow us to animate any number of CSS properties over time. We\u2019ll use two very simple keyframes to manage our mischief.<\/p>\n<p>First, let\u2019s create a keyframe to move our ball along the x-axis:<\/p>\n<pre lang=\"css\">\n@-webkit-keyframes moveX {\n  from { left: 0; } to { left: 480px; }\n}\n@-moz-keyframes moveX {\n  from { left: 0; } to { left: 480px; }\n}\n@-o-keyframes moveX {\n  from { left: 0; } to { left: 480px; }\n}\n@keyframes moveX {\n  from { left: 0; } to { left: 480px; }\n}<\/pre>\n<p>As you can see, this is really just the same keyframe repeated for each of the major browsers. Keyframes are a newer addition to CSS, so we\u2019re stuck using vendor prefixes for the short term. <\/p>\n<p>All this keyframe does is move our ball <strong>from<\/strong> the left side of the box <strong>to<\/strong> the right. Because \u2018left\u2019 positioning uses the left corner of the element to determine placement, our leftmost position is calculated as the width of the box, minus the width of the ball: 500px &#8211; 20px = 480px.<\/p>\n<p>We can apply the animation to our ball by adding the following rules to the ball:<\/p>\n<pre lang=\"css\">\n-webkit-animation: moveX 3s linear 0s infinite alternate;\n-moz-animation: moveX 3s linear 0s infinite alternate;\n-o-animation: moveX 3s linear 0s infinite alternate;\nanimation: moveX 3s linear 0s infinite alternate;<\/pre>\n<p>Again, we have one rule for each of the major browser prefixes. I\u2019m using animation shorthand here, so I\u2019ll walk through it. We\u2019re saying to animate the ball using the <strong>moveX<\/strong> keyframe rules, it should take <strong>3 seconds<\/strong> to complete the animation, we want <strong>linear<\/strong> easing (that is, don\u2019t slow down (ease) at the ends of the animation), we want a <strong>0 second<\/strong> starting delay, we want the animation to repeat <strong>infinitely<\/strong>, and we want it to <strong>alternate<\/strong> from front to back, instead of looping around to the beginning when it repeats.<\/p>\n<p>Of course, that only gives us an animation along the x-axis. Now, we could easily just change the \u201ctop\u201d values in addition to the \u201cleft\u201d values in our existing keyframe. But there\u2019s a problem with that. If we define the both in the same spot, the ball will always bounce from the top-left corner, to the bottom-right, and back. If that\u2019s what you want or need, perfect. But I want some variety.<\/p>\n<p>So instead, we\u2019ll create a second keyframe to control our movement on the y-axis:<\/p>\n<pre lang=\"css\">@-webkit-keyframes moveY {\n  from { top: 0; } to { top: 280px; }\n}\n@-moz-keyframes moveY {\n  from { top: 0; } to { top: 280px; }\n}\n@-o-keyframes moveY {\n  from { top: 0; } to { top: 280px; }\n}\n@keyframes moveY {\n  from { top: 0; } to { top: 280px; }\n}<\/pre>\n<p>This is basically the same as our moveX keyframes: we\u2019re moving the ball from the top of the box, to the bottom (minus the width of the ball). <\/p>\n<h3>Bring It All Together<\/h3>\n<p>And here\u2019s where it gets interesting. Elements can have more than one keyframe animation applied to them at the same time, separated with a comma, just like box-shadow. And more interestingly, each animation can have a different timing value! So let\u2019s change up our ball animation to look like this (I\u2019m only showing one for brevity):<\/p>\n<pre lang=\"css\">animation: moveX 3.05s linear 0s infinite alternate, \nmoveY 3.4s linear 0s infinite alternate;<\/pre>\n<p>moveX is still there, though I\u2019ve tweaked the animation to take 3.05 seconds to complete. Then, after a comma, we have our moveY animation, which takes 3.4 seconds to complete. <\/p>\n<p>Why the different times? It means that the animations will finish their loops at slightly different points. This makes the ball appear to bounce randomly about the container, seemingly never hitting the same spot. It does, of course \u2013 after 207.4 seconds in this example, according to math \u2013 but you can modify that frequency by changing the number of seconds the animations take.<\/p>\n<p>Here\u2019s the whole thing in action:<\/p>\n<pre class=\"codepen\" data-height=\"360\" data-type=\"result\" data-href=\"EBLkl\" data-user=\"rglazebrook\" data-safe=\"true\"><code><\/code><a href=\"http:\/\/codepen.io\/rglazebrook\/pen\/EBLkl\">Check out this Pen!<\/a><\/pre>\n<p><script async src=\"http:\/\/codepen.io\/assets\/embed\/ei.js\"><\/script><\/p>\n<p>Give it a try in the demo, and modify the animation values to see how it effects the movement of the ball. <\/p>\n<p><strong>Note:<\/strong> As with almost everything awesome and CSS3, you&#8217;ll need a modern browser to make this work. You should be fine with the latest versions of Chrome, Safari, Firefox, and Opera. IE10+ on this one, as IE9 and below doesn&#8217;t understand keyframes.<\/p>\n<div class=\"wp-socializer wpsr-share-icons \" data-lg-action=\"show\" data-sm-action=\"show\" data-sm-width=\"768\" ><h3>Share and Enjoy !<\/h3><div class=\"wpsr-si-inner\"><div class=\"wpsr-counter wpsrc-sz-32px\" style=\"color:#000\"><span class=\"scount\"><span data-wpsrs=\"\" data-wpsrs-svcs=\"facebook,twitter,linkedin,pinterest,print,pdf\">0<\/span><\/span><small class=\"stext\">Shares<\/small><\/div><div class=\"socializer sr-popup sr-32px sr-circle sr-opacity sr-pad sr-count-1 sr-count-1\"><span class=\"sr-facebook\"><a rel=\"nofollow\" href=\"https:\/\/www.facebook.com\/share.php?u=\" target=\"_blank\"  title=\"Share this on Facebook\"  style=\"color: #ffffff\" ><i class=\"fab fa-facebook-f\"><\/i><span class=\"ctext\"><span data-wpsrs=\"\" data-wpsrs-svcs=\"facebook\">0<\/span><\/span><\/a><\/span>\n<span class=\"sr-twitter\"><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/intent\/tweet?text=%20-%20%20\" target=\"_blank\"  title=\"Tweet this !\"  style=\"color: #ffffff\" ><i class=\"fab fa-twitter\"><\/i><\/a><\/span>\n<span class=\"sr-linkedin\"><a rel=\"nofollow\" href=\"https:\/\/www.linkedin.com\/sharing\/share-offsite\/?url=\" target=\"_blank\"  title=\"Add this to LinkedIn\"  style=\"color: #ffffff\" ><i class=\"fab fa-linkedin-in\"><\/i><\/a><\/span>\n<span class=\"sr-pinterest\"><a rel=\"nofollow\" href=\"https:\/\/www.pinterest.com\/pin\/create\/button\/?url=&amp;media=&amp;description=\" target=\"_blank\"  title=\"Submit this to Pinterest\"  style=\"color: #ffffff\" data-pin-custom=\"true\"><i class=\"fab fa-pinterest\"><\/i><span class=\"ctext\"><span data-wpsrs=\"\" data-wpsrs-svcs=\"pinterest\">0<\/span><\/span><\/a><\/span>\n<span class=\"sr-print\"><a rel=\"nofollow\" href=\"https:\/\/www.printfriendly.com\/print?url=\" target=\"_blank\"  title=\"Print this article \"  style=\"color: #ffffff\" ><i class=\"fa fa-print\"><\/i><\/a><\/span>\n<span class=\"sr-pdf\"><a rel=\"nofollow\" href=\"https:\/\/www.printfriendly.com\/print?url=\" target=\"_blank\"  title=\"Convert to PDF\"  style=\"color: #ffffff\" ><i class=\"fa fa-file-pdf\"><\/i><\/a><\/span><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>We&#8217;re going to create a ball that bounces infinitely &#8211; seemingly randomly &#8211; in its container. What&#8217;s the big whoop about that? We&#8217;ll do it entirely with CSS. [&#8230;]<\/p>\n<p><a class=\"more-link article\" href=\"https:\/\/cssdeck.com\/blog\/pure-css-bouncing-ball\/\" title=\"Click to read 'A Pure CSS Bouncing Ball'\">Read Article<\/a><\/p>\n","protected":false},"author":18,"featured_media":677,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[173,174],"tags":[203,79,49],"_links":{"self":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/posts\/673"}],"collection":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/users\/18"}],"replies":[{"embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/comments?post=673"}],"version-history":[{"count":0,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/posts\/673\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/media\/677"}],"wp:attachment":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/media?parent=673"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/categories?post=673"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/tags?post=673"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}