Having Fun with Animations: Mimicking a Sine Wave with cubic-bezier()
After our pit stop exploring Dynamic CSS, it’s time to have some fun! This article is for the curious minds who love pushing CSS to unexpected places. Today, we’ll explore animations, transitions, and cubic-bezier() by breaking down an incredible deep dive by Temani Afif — with a few twists of our own.
The Setup
Let’s start simple:
1️⃣ We begin with a square and a small symbol in one corner. This will help us track how the square moves while animating.
<div class="square"> <div class="corner"></div></div>2️⃣ Our goal? Animate the element along a sine wave! This means our square will move from its initial position to a max point, then a min point, then back to its starting position.
If you remember how cubic-bezier() works, the curve defines how an element’s property changes over time. Since the start and end points are always fixed at (0,0) and (1,1), you might think it’s impossible to create a sine-like motion with cubic-bezier().
But what if… we move p1 and p2 very, very, very far in opposite directions while making the property change very, very, very small? Boom! We now have a curve that mimics a sine wave.
The Curiosity Begins
Step 1: Moving Horizontally
First, let’s translate our square along the x-axis using our modified cubic-bezier curve.
@property --translateX { syntax: '<length>'; initial-value: 0px; inherits: false;}.square { translate: var(--translateX) 0px;}.animate { animation: _translateX 2s; animation-timing-function: cubic-bezier(.5,-900,.5,900); animation-iteration-count: infinite;}@keyframes _translateX { to { --translateX: 1px; }}Step 2: Moving Vertically
Now, let’s do the same along the y-axis, but with a smaller property change to keep the motion subtle.
Step 3: The Infinity Path
If we combine both x and y translations, adjusting their timing slightly… we should see our square follow the shape of an infinity sign (∞).
@property --translateX { syntax: '<length>'; initial-value: 0px; inherits: false;}@property --translateY { syntax: '<length>'; initial-value: 0px; inherits: false;}.square { translate: var(--translateX) var(--translateY);}.animate { animation: _translateX 2s, _translateY 1s; animation-timing-function: cubic-bezier(.5,-900,.5,900); animation-iteration-count: infinite;}@keyframes _translateX { to { --translateX: 1px; }}@keyframes _translateY { to { --translateY: .2px; }}Don’t tell me that isn’t cool. 😎
Bend It Like Beckham! ⚽️
For those who don’t know, Bend it like Beckham refers to kicking a soccer ball with spin so that it curves mid-air. If you’ve been paying attention to our square, you may have noticed it never actually rotates as it moves.
Let’s change that.
Step 4: Adding Rotation
Let’s add a rotation to our square and make it spin 😵💫.
@property --rotate { syntax: '<angle>'; initial-value: 0deg; inherits: false;}.square { transform: rotate(var(--rotate));}.animate { animation: _rotate 1s; animation-timing-function: linear; animation-iteration-count: infinite;}@keyframes _rotate { to { --rotate: -360deg; }}But we’re not stopping there! By rotating our square while it moves, we start to see something very interesting — it starts following unexpected and mesmerizing paths.
@property --rotate { syntax: '<angle>'; initial-value: 0deg; inherits: false;}@property --translate { syntax: '<length>'; initial-value: 0px; inherits: false;}.square { transform: rotate(var(--rotate)) translate(var(--translate));}.animate { animation: _rotate 1s, _translate 4s; animation-timing-function: linear, cubic-bezier(.5,-900,.5,900); animation-iteration-count: infinite;}@keyframes _rotate { to { --rotate: -360deg; }}@keyframes _translate { to { --translate: 1px; }}Now, play with different animation durations, and you can create entirely new patterns!
In the next example the rotation is slower than the translation.
You can even chain multiple transforms together for some truly mind-bending motion paths.
Where Do We Go from Here?
I think we’ve had enough of smooth curves for now 😆. But if you’re curious, there’s still more to explore — like the steps() and linear() timing functions.
CSS is full of hidden gems — some well-known, others waiting to be uncovered. Next time, we’ll dive into more fascinating CSS functions and features that can reshape the way you think about styling.
Get ready to level up your CSS toolkit! 🚀
открыть бот


