DEV Community

Cover image for CSS & React: How to bounce your logo
Jim Raptis
Jim Raptis

Posted on

CSS & React: How to bounce your logo

TLDR:
Build a smooth bouncing logo animation with pure CSS and use it in React. My impatient friends can scroll down the dark depths (=end) of this article and grab the valuable CSS snippet.

Bouncing logo of Loceye

👵 The Story

While I was craving for inspiration on Dribbble and cursing the trash Internet connection, I saw IT! It was small but beautiful! Μoving tirelessly back and forth and catching my breath every time it hits the ground.

From that time on, I was obsessed with this small devil!

Dribbble bouncing logo as spinner

As a front-end engineer that respects himself, I opened the dev tools to check the source code of the animation. Who would have thought that it was just a gif?

Kanye West meme

I was really disappointed!

From that time on, I had my heart set on building the god damn bounce!

But, enough of my emotional breakdown. Let’s get some 💩 done!

🧠 How

Before getting our hands dirty, I want to define our goal and how we’re gonna achieve it!

First of all, the Dribbble logo is a basketball, so it makes perfect sense to be bouncing. However, it doesn’t have to be a ball to make the animation look natural. Having a circular shape is enough and to convince you, our object will be an eye.

Eyerolling meme

My company, Loceye uses eye-tracking technology to understand users' behavior, and possible that eye thing makes sense now.

The second point is about the shadow! Maybe it’s not obvious to everyone but a bouncing eye transforms its shadow as it gets near the ground. The shadow gets bigger and bigger as the eye comes closer to the ground.

About the code implementation, we’re gonna need an SVG logo (PNG could work too with small adjustments) and a basic understanding of CSS animations. When we have a functional bouncing eye, I’ll show you how you can use it in any React project with no hassle as a loading component.

👨‍💻 Coding Section

Dr.House coding meme

Let’s start the coding section!

The idea behind the implementation is not rocket science! It works as simple as that. Define a container that will contain the logo and its shadow. The logo and the shadow will be positioned relative to their parent element.

For educational reasons, I’m gonna break down the whole animation concept into 4 parts.

💀 Part #1 — Static skeleton

We’re gonna define the static layout of our animation. For simplicity, the logo and its shadow will be two <div> elements with circular and rectangular shape respectively.

<div class="container">                                 
  <div class="logo"></div>
  <div class="shadow"/></div>
</div>
Enter fullscreen mode Exit fullscreen mode

Now, let’s declare some useful CSS variables and escape from the headache later. If you’re new into CSS variables and curious to learn more, you can visit this link and thank me later in the comment section.

<div class="container">                                 
  <div class="logo"></div>
  <div class="shadow"/></div>
</div>
Enter fullscreen mode Exit fullscreen mode

It’s time to position our main elements. The trick is the CSS attribute position. By defining position: relative at the container and position: absolute to its children, we achieve to position the ball and the shadow relative to their parent.

The tricky part here is to keep in mind that the top and left attributes calculate the absolute position of the top left element’s point.

CSS centering

For example, the elements can be horizontally centered inside the container if we set left: 50% and subtract the half of its width.

You can check my previous article to learn why.

The CSS classes below align the ball and the shadow inside their container using some plain calculations.

.container {
  position: relative;
}

.logo {
  position: absolute;
  top: var(--offset);
  left: calc(50% - var(--logo-size) / 2);                               
}

.shadow {
  position: absolute;
  top: calc(
    var(--offset) + 
    var(--drop-height) + 
    var(--logo-size) - 
    1.5  var(--shadow-height)
  );
  left: calc(50% - var(--logo-size) / 2);
}
Enter fullscreen mode Exit fullscreen mode

By now, our animation should look more static than ever!

🏃Part #2 — Movin’ it

It’s time to move the damn ball!!!

Half the magic lies on the @keyframes CSS at-rule, which controls the intermediate steps in a CSS animation sequence by defining styles for keyframes (or waypoints) along the animation sequence.

Our @keyframes bounce at-rule is gonna handle the translateY() and scale() CSS functions.

The function translateY() will reposition the ball vertically on the 2D plane from 0 to var(--drop-height) pixels. Simpler, it will move our ball downwards towards the ground by the specified pixels.

@keyframes bounce {
  from { 
    transform: translateY(0) scale(1);
  }
  to   { 
    transform: translateY(var(--drop-height)) scale(1, 0.7);
  }
}
Enter fullscreen mode Exit fullscreen mode

But how? Here comes the rest of the magic! The animation CSS property applies an animation between styles. We set the animation-direction property alternating back and forth animation-iteration-count to infinite.

Smooth movement is anything and everything!

However, the most important property is the animation-timing-function, that specifies how an animation progresses through the duration of each cycle. I picked the cubic-bezier() timing function because it’s highly customizable and can give the desired natural feeling.

.logo {
  ...
  animation-name: bounce; 
  animation-duration: 0.5s;
  animation-direction: alternate;
  animation-timing-function: cubic-bezier(0.95, 0.05, 0.795, 0.035);
  animation-iteration-count: infinite;
}
Enter fullscreen mode Exit fullscreen mode

Of course, these floating point numbers are not random but precisely defined after hours of calculations. Just kidding!

Hopefully, Andrey Sitnik and Ivan Solovev build an amazing curated list of easing functions, the easing.net. My work was to pick easeInExpo and copy-paste the cubic-bezier() easing.

Preview cubic-bezier(0.95, 0.05, 0.795, 0.035))

Preview cubic-bezier(0.95, 0.05, 0.795, 0.035) at cubic-bezier.com

Another great tool is cubic-bezier.com by Lea Verou. Not only helps you visualize your cubic-bezier curve, but you can also compare it with some common easing functions.

🕶 Part #3— Shadow owes its birth to light.

It’s time to take care of our shadow. Considering our extended analysis on Step #2, the shadow movement should be easy as a pie (unless you’ve never baked a pie).

@keyframes grow {
  from {
    transform: scale(0.2, 0.5);                             
  }

  to {
    transform: scale(1, 0.1);   
  }
}
Enter fullscreen mode Exit fullscreen mode

As you can see, our only adjustment is on its scale() function. Our goal here is to “stretch” the shadow as the ball is coming closer.

So far, we have a fully-functional bouncing animation with two dummy objects. Let’s put the finishing touches at our next step.

🏀 Part #4 —Dat eye is bouncing

Everything is great by now, but something is missing. The lovely eye and its realistic shadow of course. Obviously, a ball cannot have a rectangular shadow.

I used a <svg> element with our .logo class to define my logo.

<div class="container">                                         
  <svg class="logo" ...>....</svg>
  <div class="shadow"/></div>
</div>
Enter fullscreen mode Exit fullscreen mode

However, it could work if you kept the <div>element and added a PNG image inside the .logo class, taking advantage of background-image property. Moreover, we should use background-size and border-radius to center it.

.logo { 
  ...   
  background-image: './path/to/logo.png';                           
  background-size: cover;
  border-radius:50% 50% 50% 50%;
}
Enter fullscreen mode Exit fullscreen mode

The last touch is adding the radial-gradient() function and create a fading natural shadow for our object.

.shadow {   
    ...
    background: radial-gradient(50% 50%, rgba(150,150,150,1), rgba(150,150,150,0.05));
}

Enter fullscreen mode Exit fullscreen mode

🎉🎉🎉 Kudos! The logo is bouncing! 🎉🎉🎉

If you were here to grab your CSS snippet, the above Pen will make you joyful. Thank you for being patient with my bad sense of humor and hope to see you around here again!


The rest of you, who want the React component should bear with my bad humor a little bit more.

Dr.Evil meme

⚛ Only React geeks here

About the React component, I took advantage of the powerful styled-components library, that allows you to write actual CSS code to style your components. Of course, you can use the traditional way and import your CSS file into your component.

A tricky point is that the <Logo> component is an <svg> element rendered as a React component. You can easily transform an svg element to React component using svgr web editor(CLI tool is available too). Don’t forget to include viewPort in your <Logo> component!

🏃‍♀️🏃 Impatient CSS lovers here

Conclusion

It’s not that difficult to create a cool animation using pure CSS stuff. You should only take a deep breath and define what you really want! Transferring your animation to the real world can really help you understand the basic requirements!

Check the functional React Sandbox and I’m gonna wait for your dirty bouncing animation at the comment section below 👇👇👇

Latest comments (2)

Collapse
 
clamstew profile image
Clay Stewart

I seriously wonder how much network traffic <desc>Created with Sketch.</desc> creates on the internet everyday.

Collapse
 
d__raptis profile image
Jim Raptis

Damn just noticed it! And it was initially built on Adobe Illustrator...🤣