CSS Animation – calc() Function & Gradients: Create an Isometric Tornado - Part 2

Build an animated isometric tornado using only CSS! Learn how calc() and gradients create a stunning 3D vortex effect from scratch

CSS Animation – calc() Function & Gradients: Create an Isometric Tornado - Part 2
Photo by Marija Zaric / Unsplash

Introduction

Ready to build a stunning 3D tornado animation using only HTML and CSS? In this step-by-step article, you’ll learn how the CSS calc() function, smart translate movements, and smooth animation settings work together to create a natural swirling effect.

  • In Part 1, you learned how to build each part of the isometric tornado by combining multiple CSS properties and functions. Focusing on shaping basic HTML <div> elements into layered tornado rings, helped you understand how structure and styling work together to form the final design.
  • In Part 2, this article, we’ll bring everything to life with animation. You’ll use the CSS calc() function to control movement and create a smooth, natural side‑to‑side swaying motion, making your tornado feel dynamic, fluid, and realistic.

CSS functions and properties explored in this article:

  • calc()
  • will-change
  • translate
  • animation
  • animation-delay
  • @keyframes
  • CSS Custom Properties (Variables)

Preview

A quick preview of what you’ll be animating in this two-part article series.

Isometric Tornado - Animation Preview
Isometric Tornado - Animation Preview

If you haven’t checked out Part 1 yet, we highly recommend giving it a quick read before diving into Part 2. It not only covers the core building concepts of the project but gives you the essential foundation you’ll need to follow the animation techniques introduced here easily.

calc() Function & Gradients: Create an Isometric Tornado - Part 1
Learn to build an animated 3D isometric tornado using only CSS—no images or JavaScript required!

Prerequisites

Essential CSS and HTML knowledge will help you understand the concepts and techniques introduced in this article. Jump over to this article if you require an HTML and CSS primer.

We assume you have configured tools to modify CSS. If not, this article will guide you through the setup process.

Please read this article if you’re unfamiliar with CSS animation and the @keyframes at-rule property.

HTML Structure

<div class="container">
  <div class="environment">
    <div class="tornado-funnel">
      <div class="ring" style="--i: 1; --w: 10px"></div>
      <div class="ring" style="--i: 2; --w: 20px"></div>
      <div class="ring" style="--i: 3; --w: 30px"></div>
      <div class="ring" style="--i: 4; --w: 40px"></div>
      <div class="ring" style="--i: 5; --w: 50px"></div>
      <div class="ring" style="--i: 6; --w: 62px"></div>
      <div class="ring" style="--i: 7; --w: 75px"></div>
      <div class="ring" style="--i: 8; --w: 90px"></div>
      <div class="ring" style="--i: 9; --w: 108px"></div>
      <div class="ring" style="--i: 10; --w: 128px"></div>
      <div class="ring" style="--i: 11; --w: 150px"></div>
      <div class="ring" style="--i: 12; --w: 175px"></div>
      <div class="ring" style="--i: 13; --w: 205px"></div>
      <div class="ring" style="--i: 14; --w: 238px"></div>
      <div class="ring" style="--i: 15; --w: 275px"></div>
      <div class="ring" style="--i: 16; --w: 315px"></div>
    </div>
  </div>
</div>

container is the outermost enclosure. It enables the content to be centered and draws a light gray border. The rest of the <div>s represent each animation sequence.

Keep the HTML structure as is for the animation to display correctly.

Body and Container <div> CSS

CSS code for the body and container <div>.

/* Body and Container Settings */
/* Center shapes */
body {
  margin: 0;
  padding: 0;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
}

/* Set background and border color */
.container {
  min-width: 500px;
  height: 500px;
  border: 5px solid #d3d3d3;
  background: #ffffff;
  position: relative;
  margin: 5px;
  display: flex;
  justify-content: center;
  align-items: center;
}

Custom Properties

/* Custom Properties */
:root {
  --animation-length: 2.5s;
  --animation-easing: ease-in-out;
  --animation-iteration: infinite alternate;
}

By defining these variables inside the :root pseudo-class, you're placing them at the very top level of your document—the <html> element.

This means your animation settings are globally available. Think of :root as your central control panel, where any selector in your CSS can easily access and reuse these values.

Understanding the Animation Variables:

1.--animation-length: 2.5s;

This sets how long one full animation cycle takes.

A 2.5-second duration feels just right:

  • Fast enough to look lively and dynamic
  • Slow enough to stay smooth and easy on the eyes

It creates that perfect balance for natural-looking motion.

2.--animation-easing: ease-in-out;

This controls how the animation moves over time.

Instead of moving at a constant speed, ease-in-out makes the motion feel more realistic:

  • Starts slowly
  • Speeds up in the middle
  • Slows down again at the end

The result? A smooth, organic flow—not stiff or robotic.

3.--animation-iteration: infinite alternate;

This is where the animation really comes to life!

  • infinite → keeps the animation running forever
  • alternate → reverses direction each cycle

Instead of jumping back to the start, the motion flows back and forth seamlessly, creating a continuous, natural rhythm—just like a real swirling tornado.

Next, let’s take a look at the animation settings.

Animation

The animation properties define how the motion behaves, using the custom variables you set earlier in :root. By referencing them, you keep your code clean, consistent, and easy to tweak anytime.

Isometric Tornado - Swerving Left
Isometric Tornado - Swerving Left
.ring {
	animation: vortexKinematics 
var(--animation-length) 
var(--animation-easing) 
var(--animation-iteration);
}

Here’s what’s happening in the above code:

  • The animation is named vortexKinematics, which links directly to your @keyframes described in a later section.
  • var(--animation-length) controls the speed of the motion.
  • var(--animation-easing) shapes the flow of movement.
  • var(--animation-iteration) decides how the animation repeats.

By centralizing these values, you can adjust the entire animation system just by updating a few variables—no need to rewrite multiple rules.

Let’s dive into the animation-delay property.

.ring {
	animation-delay: calc(var(--i) * -0.15s);
}

This line introduces what we can call the Chronological Phase Shifter (or simply, the wave delay). It’s the small but powerful detail that turns your design from a stiff, solid stack of rings into a smooth, flowing tornado animation.

If all 16 rings started their animation at the exact same time, they would move together in perfect sync. The result? A rigid, pipe-like structure that feels unnatural.

By adding a calculated delay using calc(), each ring starts at a slightly different moment. This creates a soft, cascading wave effect, where every ring follows the motion of the one before it.

1.The Index Value → var(--i)

Each ring has its own index number defined in the HTML.

For example:

  • Ring 1 → --i: 1
  • Ring 5 → --i: 5

2.The Timing Formula → * -0.15s

This index is multiplied by a small negative delay. So the browser calculates:

  • Ring 1 → -0.15s
  • Ring 2 → -0.30s
  • Ring 5 → -0.75s

3.The “Time Travel” Effect

Normally, a positive delay makes an animation wait before starting.

But a negative delay does something special:

  • It tells the browser to start immediately, but as if the animation has already been running.

The Final Result: A Living Wave

Because each ring is slightly ahead in time:

  • Higher rings appear further along in the animation cycle
  • Lower rings follow behind

This creates a continuous ripple effect from bottom to top—right from the first frame.

will-change CSS Property

.ring {
	will-change: translate, rotate;
}

This single line—will-change: translate, rotate;—may look small, but it’s a powerful performance hint that keeps your animation running smoothly.

Think of it as a friendly “heads-up notice” to the browser.
You’re telling it: “Get ready—these elements are about to move and rotate a lot!”

Normally, the browser uses the CPU to handle layouts and updates. That works fine for simple pages—but your tornado is different. It has many layers moving and rotating continuously, which can make the CPU work too hard and cause lag or stuttering.

The browser prepares in advance by:

  • Moving the elements to the GPU (graphics card)
  • Creating a dedicated rendering layer just for them

Because the GPU is designed for fast visual processing, your rings can move and spin smoothly, like objects in a video game. The browser doesn’t need to constantly repaint everything, so your animation stays fluid and responsive.

Let’s move to the last section in this article and tackles the animation keyframes.

Keyframes

Welcome to the core engine of your tornado!

The @keyframes vortexKinematics block is where all the motion magic happens. It transforms your design from something stiff into a smooth, organic swirling storm.

Modern CSS lets you move elements in 3D space using:

translate: X-axis Y-axis Z-axis;
Isometric Tornado - Left Position
Isometric Tornado - Left Position
@keyframes vortexKinematics {
  0% {
    translate: 
	calc(var(--i) * -2.5px) 
	calc(var(--i) * -2.5px) 
    calc(var(--i) * 18px);
    rotate: 0deg;
  }

  100% {
    translate: 
	calc(var(--i) * 2.5px) 
	calc(var(--i) * 2.5px)
    calc(var(--i) * 18px);
    rotate: 180deg;
  }
}

By plugging in var(--i) (each ring’s index), every ring gets its own unique position in space. Let’s breakdown the animation code in detail.

1.Z‑Axis → Building the Funnel Height

calc(var(--i) * 18px)

This value stays the same from 0% to 100%. It lifts each ring upward and creates the vertical stack of the tornado.

Example:

  • Ring 1 → 18px
  • Ring 5 → 90px
  • Ring 16 → 288px

This is what gives your tornado its height and structure.

Isometric Tornado - Semi Center Position
Isometric Tornado - Semi Center Position

2.X & Y Axes: The Sway Motion

  • At 0%: calc(var(--i) * -2.5px)
  • At 100%: calc(var(--i) * 2.5px)

This creates a side-to-side movement.

  • Lower rings move very little → stable base
  • Higher rings move much more → wide, dramatic swing

Example:

  • Ring 1 → moves only ±2.5px (almost still)
  • Ring 16 → moves ±40px (big sweeping motion!)

This scaling makes the tornado feel anchored at the bottom and wild at the top.

Isometric Tornado - Swerving Right
Isometric Tornado - Swerving Right

3.Rotation → Spinning Energy

rotate: 0deg180deg;

While the rings sway, they also spin in place. Because your rings have a textured gradient:

  • The rotation makes patterns shift and swirl
  • It looks like debris, wind, and storm particles

Quick Customization Tips

Want to adjust your tornado’s personality?

  • More violent motion: Increase 2.5px4px or 5px
  • Taller funnel: Increase 18px25px or 30px

In short:

  • Z-axis builds the height
  • X/Y adds motion
  • Rotation adds energy

Together, they create a tornado that feels alive, dynamic, and realistic.

You can see and play with the complete code on Pyxofy’s CodePen page.

See the Pen CSS Animation – calc() Function & Gradients: Create an Isometric Tornado by Pyxofy (@pyxofy) on CodePen.

Conclusion

This article highlighted the true power of modern CSS. You explored how powerful CSS features like @keyframes, translate, and rotate can simulate realistic motion. The calc() function safely reads each HTML index to automate vertical height and wide lateral sways through the 3D translate property. The animation performance is optimized using will-change for a smoother viewing experience.

By combining multi-axis positioning, scaled movement using var(--i), and negative animation-delay, each ring moves naturally in a flowing wave. The Z-axis builds height, while X and Y create dynamic sway. Together, these properties turn simple elements into a smooth, organic tornado animation, showing how CSS can produce complex visual effects without JavaScript.

What CSS animations will you make with? Share your masterpiece with us on LinkedIn, Threads, Bluesky, Mastodon, X (Twitter) @pyxofy, or Facebook.

We hope you liked this article. Kindly share it with your network. We appreciate it.

CSS Animation – Jumping Box with @property – Part 1
You can make an orange-colored 3D-ish box jump up and down with CSS. Learn how to make this animation in this step-by-step article.
CSS Art – Using polygon() and scale() Functions Together
Want your images to pop and stand out from the rest? Learn how to use CSS polygon(), scale(), drop shadows, and more in this step-by-step article.
JavaScript - オブジェクトの基本【初心者向け】
この記事では、オブジェクトとは何か、プロパティやメソッドの意味、オブジェクトを作る方法であるオブジェクトリテラルとコンストラクタについて、初心者向けに簡単に紹介します。
スクラッチプログラミング - プラットフォーマーのつくりかた【じゅうりょくジャンプ】
プラットフォームゲームのジャンプをくふうしてみましょう。スプライトが着地(ちゃくち)するときに、地面(じめん)にしずんでしまうことがあります。それをふせぐプログラムをつくっていきますよ。