0 to Infinity HTML Lesson: Animation

Learn animation from the first moving box to interactive, controlled, useful web animations. We will use HTML, CSS, and JavaScript.

Practice Here: Embedded HTML Editor

Copy any full example from this lesson and paste it into the editor below. Then run it and change values like duration, color, movement, rotation, and scale.

Checkpoint: First run the examples without changing them. Then change one line at a time.

1. What is Animation?

Animation means changing something slowly over time so that the user sees movement.

Without animation

A button suddenly changes color. A box suddenly appears. A menu suddenly opens.

With animation

The color smoothly changes. The box fades in. The menu slides open.

Why use animation?

Animation helps users understand movement, attention, loading, success, error, and interaction.

Checkpoint: Animation is not only decoration. Good animation explains what is happening.

Full Example: Your First Animation Page

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>My First Animation</title>

  <style>
    body {
      min-height: 100vh;
      display: grid;
      place-items: center;
      margin: 0;
      background: #fff7ed;
      font-family: Arial, sans-serif;
    }

    .box {
      width: 120px;
      height: 120px;
      border-radius: 24px;
      background: #ff8a00;
      animation: moveBox 2s ease-in-out infinite alternate;
    }

    @keyframes moveBox {
      from {
        transform: translateX(-100px);
      }

      to {
        transform: translateX(100px);
      }
    }
  </style>
</head>

<body>
  <div class="box"></div>
</body>
</html>

2. CSS Transition: The First Smooth Change

A transition makes a change smooth. Move your mouse over the card below.

Hover me

Full Example: Hover Transition Card

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>CSS Transition Card</title>

  <style>
    body {
      min-height: 100vh;
      margin: 0;
      display: grid;
      place-items: center;
      background: #fff7ed;
      font-family: Arial, sans-serif;
    }

    .card {
      width: 220px;
      height: 150px;
      border-radius: 24px;
      background: linear-gradient(135deg, #fb923c, #facc15);
      color: white;
      display: grid;
      place-items: center;
      font-size: 24px;
      font-weight: bold;
      transition:
        transform 0.5s ease,
        border-radius 0.5s ease,
        background 0.5s ease,
        box-shadow 0.5s ease;
    }

    .card:hover {
      transform: translateY(-25px) rotate(4deg) scale(1.08);
      border-radius: 45px;
      background: linear-gradient(135deg, #7c3aed, #2563eb);
      box-shadow: 0 18px 35px rgba(37, 99, 235, 0.35);
    }
  </style>
</head>

<body>
  <div class="card">Hover me</div>
</body>
</html>
Checkpoint: Transition needs two states: a starting state and an ending state.

3. CSS Keyframes: Planned Motion

@keyframes lets us describe animation steps. Below, the ball moves from one vertical position to another.

CSS

Full Example: Bouncing Ball

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Bouncing Ball Animation</title>

  <style>
    body {
      min-height: 100vh;
      margin: 0;
      display: grid;
      place-items: center;
      background: #fff7ed;
      font-family: Arial, sans-serif;
    }

    .stage {
      width: 320px;
      height: 260px;
      border: 3px dashed #fb923c;
      border-radius: 24px;
      display: grid;
      place-items: center;
      background: #ffedd5;
      overflow: hidden;
    }

    .ball {
      width: 80px;
      height: 80px;
      border-radius: 50%;
      background: radial-gradient(circle at 30% 30%, white, #fb923c, #c2410c);
      animation: bounce 1s ease-in-out infinite alternate;
    }

    @keyframes bounce {
      from {
        transform: translateY(70px);
      }

      to {
        transform: translateY(-70px);
      }
    }
  </style>
</head>

<body>
  <div class="stage">
    <div class="ball"></div>
  </div>
</body>
</html>
Checkpoint: Use transition for simple state change. Use keyframes for planned motion.

4. Transform: Move, Rotate, Scale

Most modern animations use transform. It is fast and smooth.

Full Example: Spin and Grow

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Transform Animation</title>

  <style>
    body {
      min-height: 100vh;
      margin: 0;
      display: grid;
      place-items: center;
      background: #eff6ff;
      font-family: Arial, sans-serif;
    }

    .shape {
      width: 100px;
      height: 100px;
      background: linear-gradient(135deg, #2563eb, #7c3aed);
      border-radius: 22px;
      animation: spinAndGrow 2.2s linear infinite;
      box-shadow: 0 12px 24px rgba(37, 99, 235, 0.25);
    }

    @keyframes spinAndGrow {
      0% {
        transform: rotate(0deg) scale(0.7);
      }

      50% {
        transform: rotate(180deg) scale(1.25);
        border-radius: 50%;
      }

      100% {
        transform: rotate(360deg) scale(0.7);
      }
    }
  </style>
</head>

<body>
  <div class="shape"></div>
</body>
</html>
Important: Prefer animating transform and opacity. They are usually smoother than animating width, height, top, or left.

5. Timing Functions: The Feeling of Motion

Animation is not only about movement. It is also about speed.

Move

Full Example: Timing Function Demo

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Timing Function Demo</title>

  <style>
    body {
      margin: 0;
      min-height: 100vh;
      display: grid;
      place-items: center;
      background: #fff7ed;
      font-family: Arial, sans-serif;
    }

    .panel {
      width: min(90vw, 600px);
      background: white;
      border: 2px solid #fed7aa;
      border-radius: 24px;
      padding: 24px;
    }

    .track {
      height: 160px;
      border: 3px dashed #fb923c;
      border-radius: 20px;
      display: flex;
      align-items: center;
      padding: 20px;
      overflow: hidden;
      background: #ffedd5;
    }

    .ball {
      width: 70px;
      height: 70px;
      border-radius: 50%;
      background: #ff8a00;
      display: grid;
      place-items: center;
      color: white;
      font-weight: bold;
    }

    select,
    button {
      margin-top: 14px;
      padding: 10px 14px;
      border-radius: 999px;
      font-size: 16px;
    }

    button {
      border: none;
      background: #ff8a00;
      color: white;
      font-weight: bold;
      cursor: pointer;
    }
  </style>
</head>

<body>
  <div class="panel">
    <h1>Timing Function Demo</h1>

    <div class="track">
      <div class="ball" id="ball">Go</div>
    </div>

    <select id="timing">
      <option value="linear">linear</option>
      <option value="ease">ease</option>
      <option value="ease-in">ease-in</option>
      <option value="ease-out">ease-out</option>
      <option value="ease-in-out">ease-in-out</option>
      <option value="cubic-bezier(.68,-0.55,.27,1.55)">bounce-like</option>
    </select>

    <button onclick="runDemo()">Run</button>
    <button onclick="resetDemo()">Reset</button>
  </div>

  <script>
    const ball = document.getElementById("ball");
    const timing = document.getElementById("timing");

    function runDemo() {
      ball.style.transition = "transform 1s " + timing.value;
      ball.style.transform = "translateX(380px) rotate(360deg)";
    }

    function resetDemo() {
      ball.style.transition = "transform 0.3s ease";
      ball.style.transform = "translateX(0) rotate(0)";
    }
  </script>
</body>
</html>

6. Interactive Animation Playground

Change the sliders and see how transform changes the object.

Live CSS

transform: translateX(0px) rotate(0deg) scale(1);
border-radius: 24px;

Full Example: Slider Controlled Animation

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Interactive Animation Playground</title>

  <style>
    body {
      margin: 0;
      min-height: 100vh;
      background: #fff7ed;
      font-family: Arial, sans-serif;
      display: grid;
      place-items: center;
    }

    .panel {
      width: min(92vw, 700px);
      background: white;
      border: 2px solid #fed7aa;
      border-radius: 24px;
      padding: 24px;
      box-shadow: 0 14px 30px rgba(124, 45, 18, 0.14);
    }

    .stage {
      height: 230px;
      border: 3px dashed #fb923c;
      border-radius: 20px;
      display: grid;
      place-items: center;
      background: #ffedd5;
      overflow: hidden;
      margin-bottom: 20px;
    }

    .object {
      width: 90px;
      height: 90px;
      border-radius: 24px;
      background: linear-gradient(135deg, #ff8a00, #dc2626);
      transition: transform 0.25s ease, border-radius 0.25s ease;
    }

    label {
      display: block;
      font-weight: bold;
      margin-top: 12px;
    }

    input {
      width: 100%;
    }

    pre {
      background: #111827;
      color: #e5e7eb;
      padding: 16px;
      border-radius: 14px;
      overflow-x: auto;
    }
  </style>
</head>

<body>
  <div class="panel">
    <h1>Animation Playground</h1>

    <div class="stage">
      <div class="object" id="object"></div>
    </div>

    <label>Move X: <span id="moveText">0</span>px</label>
    <input id="move" type="range" min="-220" max="220" value="0" />

    <label>Rotate: <span id="rotateText">0</span>deg</label>
    <input id="rotate" type="range" min="0" max="360" value="0" />

    <label>Scale: <span id="scaleText">1</span></label>
    <input id="scale" type="range" min="0.5" max="2" value="1" step="0.1" />

    <label>Border Radius: <span id="radiusText">24</span>px</label>
    <input id="radius" type="range" min="0" max="50" value="24" />

    <h2>Live CSS</h2>
    <pre id="output"></pre>
  </div>

  <script>
    const object = document.getElementById("object");

    const move = document.getElementById("move");
    const rotate = document.getElementById("rotate");
    const scale = document.getElementById("scale");
    const radius = document.getElementById("radius");

    const moveText = document.getElementById("moveText");
    const rotateText = document.getElementById("rotateText");
    const scaleText = document.getElementById("scaleText");
    const radiusText = document.getElementById("radiusText");
    const output = document.getElementById("output");

    function updateAnimation() {
      const x = move.value;
      const r = rotate.value;
      const s = scale.value;
      const br = radius.value;

      object.style.transform =
        "translateX(" + x + "px) rotate(" + r + "deg) scale(" + s + ")";

      object.style.borderRadius = br + "px";

      moveText.textContent = x;
      rotateText.textContent = r;
      scaleText.textContent = s;
      radiusText.textContent = br;

      output.textContent =
        "transform: translateX(" + x + "px) rotate(" + r + "deg) scale(" + s + ");\\n" +
        "border-radius: " + br + "px;";
    }

    move.addEventListener("input", updateAnimation);
    rotate.addEventListener("input", updateAnimation);
    scale.addEventListener("input", updateAnimation);
    radius.addEventListener("input", updateAnimation);

    updateAnimation();
  </script>
</body>
</html>

7. Animated Scene: Car, Cloud, Sun

A scene is many small animations working together.

Full Example: Animated Car Scene

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Animated Scene</title>

  <style>
    body {
      margin: 0;
      min-height: 100vh;
      display: grid;
      place-items: center;
      background: #fff7ed;
      font-family: Arial, sans-serif;
    }

    .scene {
      width: min(92vw, 800px);
      height: 300px;
      position: relative;
      background: linear-gradient(#bfdbfe, #dbeafe 62%, #86efac 62%, #22c55e);
      border-radius: 24px;
      overflow: hidden;
      border: 3px solid #93c5fd;
    }

    .sun {
      position: absolute;
      top: 30px;
      right: 55px;
      width: 70px;
      height: 70px;
      background: #facc15;
      border-radius: 50%;
      box-shadow: 0 0 35px #facc15;
      animation: pulseSun 2s ease-in-out infinite alternate;
    }

    @keyframes pulseSun {
      from {
        transform: scale(1);
      }

      to {
        transform: scale(1.18);
      }
    }

    .cloud {
      position: absolute;
      top: 70px;
      left: -130px;
      width: 130px;
      height: 45px;
      background: white;
      border-radius: 999px;
      animation: moveCloud 8s linear infinite;
    }

    .cloud::before,
    .cloud::after {
      content: "";
      position: absolute;
      background: white;
      border-radius: 50%;
    }

    .cloud::before {
      width: 55px;
      height: 55px;
      top: -22px;
      left: 20px;
    }

    .cloud::after {
      width: 70px;
      height: 70px;
      top: -35px;
      left: 55px;
    }

    @keyframes moveCloud {
      from {
        transform: translateX(0);
      }

      to {
        transform: translateX(950px);
      }
    }

    .car {
      position: absolute;
      bottom: 80px;
      left: 20px;
      width: 140px;
      height: 55px;
      background: #ef4444;
      border-radius: 28px 36px 12px 12px;
      animation: driveCar 5s ease-in-out infinite alternate;
    }

    .car::before {
      content: "";
      position: absolute;
      width: 62px;
      height: 35px;
      background: #bfdbfe;
      top: -24px;
      left: 36px;
      border-radius: 20px 20px 0 0;
    }

    .wheel {
      position: absolute;
      bottom: -15px;
      width: 32px;
      height: 32px;
      background: #111827;
      border-radius: 50%;
      border: 5px solid #e5e7eb;
      animation: wheelSpin 0.7s linear infinite;
    }

    .wheel.one {
      left: 22px;
    }

    .wheel.two {
      right: 22px;
    }

    @keyframes driveCar {
      from {
        transform: translateX(0);
      }

      to {
        transform: translateX(600px);
      }
    }

    @keyframes wheelSpin {
      to {
        transform: rotate(360deg);
      }
    }
  </style>
</head>

<body>
  <div class="scene">
    <div class="sun"></div>
    <div class="cloud"></div>

    <div class="car">
      <div class="wheel one"></div>
      <div class="wheel two"></div>
    </div>
  </div>
</body>
</html>

8. Useful Animation Patterns

Loader

Progress Bar

Typewriter

Animation makes websites alive.

Full Example: Loader, Progress Bar, Typewriter

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Useful Animation Patterns</title>

  <style>
    body {
      margin: 0;
      min-height: 100vh;
      display: grid;
      place-items: center;
      background: #fff7ed;
      font-family: Arial, sans-serif;
    }

    .grid {
      width: min(92vw, 900px);
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
      gap: 20px;
    }

    .card {
      background: white;
      border: 2px solid #fed7aa;
      border-radius: 24px;
      padding: 24px;
      text-align: center;
    }

    .loader {
      width: 82px;
      height: 82px;
      border: 10px solid #ffedd5;
      border-top-color: #ff8a00;
      border-radius: 50%;
      margin: 20px auto;
      animation: loaderSpin 1s linear infinite;
    }

    @keyframes loaderSpin {
      to {
        transform: rotate(360deg);
      }
    }

    .progress-track {
      height: 20px;
      background: #ffedd5;
      border-radius: 999px;
      overflow: hidden;
      margin-top: 38px;
    }

    .progress-fill {
      width: 0%;
      height: 100%;
      background: linear-gradient(90deg, #16a34a, #facc15, #ff8a00);
      animation: loadingBar 3s ease-in-out infinite;
    }

    @keyframes loadingBar {
      0% {
        width: 0%;
      }

      50% {
        width: 82%;
      }

      100% {
        width: 100%;
      }
    }

    .typewriter {
      max-width: max-content;
      overflow: hidden;
      border-right: 4px solid #c2410c;
      white-space: nowrap;
      animation:
        typing 4s steps(34, end) infinite alternate,
        blink 0.65s step-end infinite;
      font-weight: bold;
      color: #9a3412;
      margin: 42px auto;
    }

    @keyframes typing {
      from {
        width: 0;
      }

      to {
        width: 34ch;
      }
    }

    @keyframes blink {
      50% {
        border-color: transparent;
      }
    }
  </style>
</head>

<body>
  <div class="grid">
    <div class="card">
      <h2>Loader</h2>
      <div class="loader"></div>
    </div>

    <div class="card">
      <h2>Progress Bar</h2>
      <div class="progress-track">
        <div class="progress-fill"></div>
      </div>
    </div>

    <div class="card">
      <h2>Typewriter</h2>
      <div class="typewriter">Animation makes websites alive.</div>
    </div>
  </div>
</body>
</html>

9. Scroll Animation

Scroll animation means an element appears when it enters the screen.

Step 1

The element starts hidden using opacity 0.

Step 2

JavaScript observes when the element enters the screen.

Step 3

A class is added. The element fades and moves into place.

Full Example: Scroll Reveal Animation

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Scroll Reveal Animation</title>

  <style>
    body {
      margin: 0;
      background: #fff7ed;
      font-family: Arial, sans-serif;
      line-height: 1.7;
    }

    header {
      min-height: 80vh;
      display: grid;
      place-items: center;
      text-align: center;
      background: linear-gradient(135deg, #ff8a00, #facc15);
      color: white;
      padding: 30px;
    }

    main {
      max-width: 900px;
      margin: auto;
      padding: 40px 16px;
    }

    .card {
      background: white;
      border: 2px solid #fed7aa;
      border-radius: 24px;
      padding: 24px;
      margin: 30px 0;
      box-shadow: 0 14px 30px rgba(124, 45, 18, 0.14);

      opacity: 0;
      transform: translateY(45px);
      transition: opacity 0.8s ease, transform 0.8s ease;
    }

    .card.visible {
      opacity: 1;
      transform: translateY(0);
    }
  </style>
</head>

<body>
  <header>
    <div>
      <h1>Scroll Down</h1>
      <p>Cards will appear when they enter the screen.</p>
    </div>
  </header>

  <main>
    <div class="card">
      <h2>Card 1</h2>
      <p>This card fades in and moves upward.</p>
    </div>

    <div class="card">
      <h2>Card 2</h2>
      <p>The browser observes when it becomes visible.</p>
    </div>

    <div class="card">
      <h2>Card 3</h2>
      <p>Then JavaScript adds the visible class.</p>
    </div>
  </main>

  <script>
    const observer = new IntersectionObserver(function(entries) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add("visible");
        }
      });
    }, {
      threshold: 0.25
    });

    document.querySelectorAll(".card").forEach(function(card) {
      observer.observe(card);
    });
  </script>
</body>
</html>

10. Mini Quiz

Question: Which two CSS properties are usually best for smooth animation?

11. Practice Tasks

Level 1

Create a button that becomes bigger on hover.

Level 2

Create a ball that bounces forever.

Level 3

Create a loading spinner using border and rotate.

Level 4

Create a card that fades in when the page scrolls.

Level 5

Create sliders to control move, rotate, and scale.

Infinity Level

Create a small animated story: sun rises, bird flies, car moves, title appears.

12. Full Mini Project: Animated Landing Page

This final example combines title animation, button hover, floating cards, and repeated motion.

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Animated Landing Page</title>

  <style>
    * {
      box-sizing: border-box;
    }

    body {
      margin: 0;
      min-height: 100vh;
      font-family: Arial, sans-serif;
      background:
        radial-gradient(circle at top left, rgba(255, 138, 0, 0.25), transparent 30%),
        radial-gradient(circle at bottom right, rgba(37, 99, 235, 0.18), transparent 30%),
        #fff7ed;
      color: #1f2937;
      overflow-x: hidden;
    }

    .hero {
      min-height: 100vh;
      display: grid;
      place-items: center;
      padding: 30px;
      text-align: center;
      position: relative;
    }

    .hero-content {
      max-width: 760px;
      background: rgba(255, 255, 255, 0.86);
      border: 2px solid #fed7aa;
      border-radius: 30px;
      padding: 40px;
      box-shadow: 0 20px 45px rgba(124, 45, 18, 0.14);
      animation: fadeUp 1s ease both;
    }

    h1 {
      font-size: clamp(2.2rem, 7vw, 5rem);
      margin: 0;
      color: #9a3412;
      animation: titlePop 1.2s ease both;
    }

    p {
      font-size: 1.2rem;
      line-height: 1.7;
    }

    button {
      border: none;
      border-radius: 999px;
      background: #ff8a00;
      color: white;
      padding: 16px 26px;
      font-size: 18px;
      font-weight: bold;
      cursor: pointer;
      transition: transform 0.3s ease, box-shadow 0.3s ease;
      animation: softPulse 1.6s ease-in-out infinite alternate;
    }

    button:hover {
      transform: translateY(-5px) scale(1.08);
      box-shadow: 0 18px 32px rgba(249, 115, 22, 0.35);
    }

    .floating-card {
      position: absolute;
      width: 110px;
      height: 110px;
      border-radius: 24px;
      display: grid;
      place-items: center;
      color: white;
      font-weight: bold;
      box-shadow: 0 16px 30px rgba(15, 23, 42, 0.18);
    }

    .card-one {
      top: 12%;
      left: 8%;
      background: #2563eb;
      animation: floatOne 3s ease-in-out infinite alternate;
    }

    .card-two {
      right: 8%;
      bottom: 14%;
      background: #7c3aed;
      animation: floatTwo 3.4s ease-in-out infinite alternate;
    }

    .card-three {
      right: 12%;
      top: 14%;
      background: #16a34a;
      animation: spinSlow 5s linear infinite;
    }

    @keyframes fadeUp {
      from {
        opacity: 0;
        transform: translateY(40px);
      }

      to {
        opacity: 1;
        transform: translateY(0);
      }
    }

    @keyframes titlePop {
      0% {
        opacity: 0;
        transform: scale(0.75);
      }

      70% {
        transform: scale(1.08);
      }

      100% {
        opacity: 1;
        transform: scale(1);
      }
    }

    @keyframes softPulse {
      from {
        box-shadow: 0 0 0 rgba(249, 115, 22, 0.2);
      }

      to {
        box-shadow: 0 0 35px rgba(249, 115, 22, 0.65);
      }
    }

    @keyframes floatOne {
      from {
        transform: translateY(0) rotate(-5deg);
      }

      to {
        transform: translateY(35px) rotate(8deg);
      }
    }

    @keyframes floatTwo {
      from {
        transform: translateY(0) rotate(5deg);
      }

      to {
        transform: translateY(-35px) rotate(-8deg);
      }
    }

    @keyframes spinSlow {
      to {
        transform: rotate(360deg);
      }
    }

    @media (max-width: 700px) {
      .floating-card {
        display: none;
      }

      .hero-content {
        padding: 28px;
      }
    }
  </style>
</head>

<body>
  <main class="hero">
    <div class="floating-card card-one">HTML</div>
    <div class="floating-card card-two">CSS</div>
    <div class="floating-card card-three">JS</div>

    <section class="hero-content">
      <h1>Animation</h1>
      <p>
        Animation makes a web page feel alive.
        Start with transitions, then learn keyframes,
        then control motion with JavaScript.
      </p>
      <button>Start Learning</button>
    </section>
  </main>
</body>
</html>

13. Final Understanding

Transition

For smooth change between two states.

Keyframes

For planned motion with steps.

Transform

For fast movement, rotation, and scaling.

JavaScript

For user-controlled animation.

Infinity Rule: Do not animate everything. Animate only when it helps the user understand, enjoy, or interact.