Advanced Animations Using CSS
Creating advanced CSS animations is great for UX and design purposes. You can make an interactive website that pleases the visitor and makes them remember your website. Animations sounds like a hard topic but once you understand them you will be able to create amazing websites like this one! Yes, this is only created with CSS!
First, let’s dive into the magic and power of the cubic-bezier
function.
cubic-bezier
: What Is It And How Can We Use It?
The cubic-bezier
function in CSS is an easing function that gives you complete control of how your animation behaves with respect to time. Here is the official definition:
“A cubic Bézier easing function is a type of easing function defined by four real numbers that specify the two control points, P1 and P2, of a cubic Bézier curve whose end points P0 and P3 are fixed at (0, 0) and (1, 1) respectively. The x coordinates of P1 and P2 are restricted to the range [0, 1].”
— CSS Easing Functions Level 1 W3C Candidate Recommendation Draft, 1 April 2021
If you want to learn more about easing functions, you can check out this article by Adrian Bece. It goes behind the scenes of how linear, cubic-bezier
and staircase functions work.
The x-axis (time) is restricted between [0,1]. However, the y-axis (output) isn’t limited to a certain range.
Our goal for the cubic-bezier is to create the sliding parabola at the beginning of the required animation. But in order to get there, we’ll start small and learn how to create a parabolic curve using cubic-bezier.
The Parabolic Curve
From the definition of the parabolic curve, you may notice that making a perfect parabolic curve seems impossible because P0 must be at (0, 0) and P3 must be at (1, 1) while parabolic curves start and end at the same horizontal axis, so we’ll need P3 to be at (1, 0).
It’s true that we can’t make a perfect parabola. However, we can create something close to it.
Creating The Ball
We need to create an object that we will model for our animation, I chose a ball because it is simple, but of course you are free to use whatever object you want.
Add the following code to your HTML and CSS files:
<div class="ball"></div>
.ball {
background-color: burlywood;
height: 50px;
width: 50px;
border: 1px solid black;
border-radius: 50px;
position: fixed;
left: 10px;
top: 300px;
}
You should get something like this:
Moving The Ball Along The X-Axis
We want to create two animations, one across the x-axis and one across the y-axis. The x-axis animation is a linear animation that moves the ball from one point to the other.
- Add a keyframes, we’ll call it x:
@keyframes x {
to {
left: 500px;
}
}
- Add the keyframe to the animation attribute in the ball class:
.ball {
background-color: burlywood;
height: 50px;
width: 50px;
border: 1px solid black;
border-radius: 50px;
position: fixed;
left: 10px;
top: 300px;
animation: x 2s linear forwards;
}
Now the ball is moving along the x axis!
The Sliding Part
Creating the part the ball slides at can be done using the cubic-bezier function! The animation is made up of 2 animations, one along the x-axis and the other is along the y-axis. The x-axis animation is a normal linear animation along the x-axis. We can define its keyframes as follows:
@keyframes x {
to {
left: 500px;
}
}
add it to your animation property in the ball path, as follows:
animation: x 4s linear forwards
The y-axis animation is the one where we will use the cubic-bezier function. Let’s first define the keyframes of the animation. We want the difference between the starting point and the ending point to be so small, that the ball reaches almost the same height.
@keyframes y {
to {
top: 299.5px;
}
}
Now let’s think about the cubic-bezier function. We want our path to move slowly to the right first then when it slides, it should go faster.
- Moving slowly to the right means that P1 will be along the x-axis. So, we know it is at (V, 0)
- We need to choose a suitable V that makes our animation go slowly to the right but not too much so that it takes up the whole space. In this case I found that 0.55 fits best
- To achieve the sliding effect, we need to move P2 down the y-axis (negative value) so P2=(X, -Y)
- Y should be a big value. In this case, I chose Y=800
- To get X, we know that our animation speed should be faster when sliding and slower when going up again. So, the closer X is to zero, The steeper the animation will be at sliding. In this case, let X = 0.8
Now you have your cubic-bezier function, it will be cubic-bezier(0.55, 0, 0.2, -800)
.
Let’s add keyframes to our animations property:
animation: x 4s linear forwards,
y 4s cubic-bezier(0.55, 0, 0.2, -800) forwards;
This is the first part of our animation, so the animation delay is zero. We should add an animation-delay property because starting from the next animation, the animations will start at a different time than the first animation.
animation-delay: 0s, 0s;
Note: If you’re unsure about the values of the cubic-bezier function, you can check out this website where you can visualize cubic-beziers and get an idea where P0 and P1 should be at.
Adding An Animation Along The X-Axis
Before making the loop, the ball should move along the x-axis for a short while so that there is space between both animations. So, let’s do that!
- Define the keyframes:
@keyframes x2 {
to {
left: 600px;
}
}
- Add it to the animation property:
animation: x 4s linear forwards,
y 4s cubic-bezier(0.55, 0, 0.2, -800) forwards, x2 0.5s linear forwards;
This animation should start after the sliding animation and the sliding animation takes four seconds, so the animation delay will be four seconds:
animation-delay: 0s, 0s, 4s;
The Result
Moving The Ball Along The X-Axis (Again)
We’re almost done! We just need to move the ball after the animation along the x-axis so that the ball doesn’t stop exactly after the loop, the way it does in the picture above.
- Add the keyframes:
@keyframes x3 {
to {
left: 1000px;
}
}
- Add the keyframes to the animation property:
animation: x 4s linear forwards,
y 4s cubic-bezier(0.55, 0, 0.2, -800) forwards, x2 0.5s linear forwards,
pointOfCircle 0s linear forwards, loop 3s linear forwards,
x3 2s linear forwards;
- Adding the suitable delay, here it will be 7.5s:
animation-delay: 0s, 0s, 4s, 4.5s, 4.5s, 7.5s;
The Final Output
See the Pen rollercoaster by Yosra Emad.
ConclusionIn this article, we covered how to combine multiple keyframes to create a complex animation path. We also covered cubic-beziers and how to use them to create your own easing function. I would recommend going on and creating your own animation path to get your hands dirty with animations. If you need any help or want to give feedback, you’re more than welcome to send a message to any of the links here. Have a wonderful day/night!