jQuery & DOM Manipulation

Custom Animations

15 min Lesson 25 of 30

Introduction to Custom Animations

While jQuery's built-in effects are useful, the animate() method gives you complete control over custom animations. You can animate any CSS numeric property, create complex animation sequences, and build sophisticated interactive experiences.

The animate() Method

The animate() method creates custom animations by changing CSS properties over time.

Basic Syntax:
$(selector).animate({
    property: value,
    property2: value2
}, duration, easing, callback);
Simple Animation Example:
<div id="box" style="width: 100px; height: 100px; background: blue;"></div>
<button id="animateBtn">Animate</button>

<script>
$(document).ready(function() {
    $("#animateBtn").click(function() {
        $("#box").animate({
            width: "300px",
            height: "300px",
            opacity: 0.5
        }, 1000);
    });
});
</script>

Animatable Properties

You can animate most CSS numeric properties. Here are the commonly animated properties:

Common Animatable Properties:
// Position
left, right, top, bottom

// Dimensions
width, height, padding, margin

// Visual
opacity, fontSize, lineHeight

// Border
borderWidth, borderRadius

// Examples
$("#box").animate({
    left: "250px",
    opacity: 0.8,
    fontSize: "20px",
    borderRadius: "50%"
}, 1000);
⚠️ Warning: Color properties (color, backgroundColor) cannot be animated with jQuery's animate() method alone. You need jQuery UI or a color animation plugin for color animations.

Relative Values

You can use relative values with "+=" or "-=" to animate from the current value.

Relative Animation:
// Move right by 50px from current position
$("#box").animate({
    left: "+=50px"
}, 500);

// Decrease width by 20px
$("#box").animate({
    width: "-=20px"
}, 500);

// Multiple relative animations
$("#box").animate({
    left: "+=100px",
    top: "-=50px",
    width: "+=50px"
}, 1000);

Easing Functions

Easing controls the speed of animation at different points in time. jQuery includes "linear" and "swing" (default).

Using Easing:
// Linear easing (constant speed)
$("#box").animate({
    left: "300px"
}, 1000, "linear");

// Swing easing (starts slow, speeds up, then slows down)
$("#box").animate({
    left: "300px"
}, 1000, "swing");

// With callback
$("#box").animate({
    left: "300px"
}, 1000, "swing", function() {
    alert("Animation complete!");
});
💡 Tip: For more easing options (like easeInOutQuad, easeOutBounce), include jQuery UI or a dedicated easing plugin.

Sequential Animations (Chaining)

Chain multiple animate() calls to create sequential animations.

Animation Chaining:
$("#box")
    .animate({ left: "250px" }, 1000)
    .animate({ top: "250px" }, 1000)
    .animate({ left: "0px" }, 1000)
    .animate({ top: "0px" }, 1000);

// With different properties in sequence
$("#box")
    .animate({ width: "300px" }, 500)
    .animate({ height: "300px" }, 500)
    .animate({ opacity: 0.3 }, 500)
    .animate({ opacity: 1 }, 500);

Simultaneous Animations

Animate multiple properties at once by including them in the same animate() call.

Multiple Properties:
// All properties animate together
$("#box").animate({
    width: "300px",
    height: "300px",
    left: "200px",
    top: "200px",
    opacity: 0.5,
    fontSize: "24px"
}, 2000);

Animation Queue Control

Use queue: false to animate properties independently from the queue.

Queue Control:
// Left animates in queue, opacity animates independently
$("#box")
    .animate({ left: "250px" }, 2000)
    .animate({ opacity: 0.5 }, { duration: 1000, queue: false });

// Stop current animation
$("#box").stop();

// Stop and clear queue
$("#box").stop(true);

// Stop, clear queue, and jump to end
$("#box").stop(true, true);

Practical Example: Animated Navigation

<style>
.nav-menu {
    list-style: none;
    padding: 0;
    margin: 0;
}
.nav-item {
    display: inline-block;
    position: relative;
    padding: 15px 20px;
    cursor: pointer;
    overflow: hidden;
}
.nav-underline {
    position: absolute;
    bottom: 0;
    left: 50%;
    width: 0;
    height: 3px;
    background: var(--primary);
    transform: translateX(-50%);
}
</style>

<ul class="nav-menu">
    <li class="nav-item">
        Home
        <div class="nav-underline"></div>
    </li>
    <li class="nav-item">
        About
        <div class="nav-underline"></div>
    </li>
    <li class="nav-item">
        Services
        <div class="nav-underline"></div>
    </li>
</ul>

<script>
$(document).ready(function() {
    $(".nav-item").hover(
        function() {
            $(this).find(".nav-underline")
                .stop()
                .animate({ width: "100%" }, 300);
        },
        function() {
            $(this).find(".nav-underline")
                .stop()
                .animate({ width: "0" }, 300);
        }
    );
});
</script>

Progress Bar Animation

Create an animated progress bar that fills smoothly.

<style>
.progress-container {
    width: 100%;
    height: 30px;
    background: var(--bg-light);
    border-radius: 15px;
    overflow: hidden;
    margin: 20px 0;
}
.progress-bar {
    width: 0;
    height: 100%;
    background: linear-gradient(90deg, var(--primary), var(--primary-light));
    border-radius: 15px;
    position: relative;
}
.progress-text {
    position: absolute;
    width: 100%;
    text-align: center;
    line-height: 30px;
    color: white;
    font-weight: bold;
}
</style>

<div class="progress-container">
    <div class="progress-bar">
        <span class="progress-text">0%</span>
    </div>
</div>
<button id="startProgress">Start Upload</button>

<script>
$(document).ready(function() {
    $("#startProgress").click(function() {
        var progressBar = $(".progress-bar");
        var progressText = $(".progress-text");

        progressBar.animate({ width: "100%" }, {
            duration: 3000,
            easing: "linear",
            step: function(now) {
                var percentage = Math.floor(now);
                progressText.text(percentage + "%");
            },
            complete: function() {
                progressText.text("Complete!");
            }
        });
    });
});
</script>
💡 Tip: The step callback executes during each animation step, perfect for updating text or creating custom effects.

Animated Counter

Create a counting animation for statistics or metrics.

<style>
.stat-box {
    display: inline-block;
    padding: 30px;
    margin: 20px;
    background: var(--bg-light);
    border-radius: 10px;
    text-align: center;
    min-width: 200px;
}
.stat-number {
    font-size: 48px;
    font-weight: bold;
    color: var(--primary);
}
.stat-label {
    font-size: 16px;
    color: var(--text-light);
    margin-top: 10px;
}
</style>

<div class="stat-box">
    <div class="stat-number" data-target="1250">0</div>
    <div class="stat-label">Happy Clients</div>
</div>

<div class="stat-box">
    <div class="stat-number" data-target="5680">0</div>
    <div class="stat-label">Projects Completed</div>
</div>

<script>
$(document).ready(function() {
    function animateCounter(element) {
        var target = parseInt(element.attr("data-target"));

        $({ counter: 0 }).animate({ counter: target }, {
            duration: 2000,
            easing: "swing",
            step: function() {
                element.text(Math.floor(this.counter));
            },
            complete: function() {
                element.text(target.toLocaleString());
            }
        });
    }

    // Trigger animation when element is in viewport
    $(".stat-number").each(function() {
        animateCounter($(this));
    });
});
</script>

Bouncing Effect

Create a bouncing animation using sequential animations.

<style>
#ball {
    width: 50px;
    height: 50px;
    background: var(--primary);
    border-radius: 50%;
    position: absolute;
    top: 0;
    left: 50px;
}
</style>

<div id="ball"></div>
<button id="bounceBtn">Bounce Ball</button>

<script>
$(document).ready(function() {
    $("#bounceBtn").click(function() {
        $("#ball")
            .animate({ top: "300px" }, 500, "linear")
            .animate({ top: "100px" }, 400, "linear")
            .animate({ top: "300px" }, 300, "linear")
            .animate({ top: "200px" }, 200, "linear")
            .animate({ top: "300px" }, 100, "linear")
            .animate({ top: "280px" }, 50, "linear");
    });
});
</script>

Parallax Scrolling Effect

Create a simple parallax effect using animation based on scroll position.

<style>
.parallax-container {
    height: 500px;
    overflow: hidden;
    position: relative;
}
.parallax-layer {
    position: absolute;
    width: 100%;
    height: 100%;
}
#layer1 { background: url("layer1.png") center/cover; }
#layer2 { background: url("layer2.png") center/cover; }
#layer3 { background: url("layer3.png") center/cover; }
</style>

<div class="parallax-container">
    <div class="parallax-layer" id="layer1"></div>
    <div class="parallax-layer" id="layer2"></div>
    <div class="parallax-layer" id="layer3"></div>
</div>

<script>
$(document).ready(function() {
    $(window).scroll(function() {
        var scrolled = $(window).scrollTop();

        // Different layers move at different speeds
        $("#layer1").css("top", -(scrolled * 0.2) + "px");
        $("#layer2").css("top", -(scrolled * 0.5) + "px");
        $("#layer3").css("top", -(scrolled * 0.8) + "px");
    });
});
</script>

Card Flip Animation

Create an interactive card flip effect.

<style>
.flip-card {
    width: 300px;
    height: 200px;
    position: relative;
    cursor: pointer;
}
.flip-card-front, .flip-card-back {
    position: absolute;
    width: 100%;
    height: 100%;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    font-weight: bold;
}
.flip-card-front {
    background: var(--primary);
    color: white;
}
.flip-card-back {
    background: var(--primary-light);
    color: white;
    display: none;
}
</style>

<div class="flip-card">
    <div class="flip-card-front">Front</div>
    <div class="flip-card-back">Back</div>
</div>

<script>
$(document).ready(function() {
    var isFlipped = false;

    $(".flip-card").click(function() {
        var front = $(this).find(".flip-card-front");
        var back = $(this).find(".flip-card-back");

        if (!isFlipped) {
            front.animate({ width: "0", opacity: 0 }, 200, function() {
                front.hide();
                back.css({ width: "0", opacity: 0 }).show()
                    .animate({ width: "100%", opacity: 1 }, 200);
            });
            isFlipped = true;
        } else {
            back.animate({ width: "0", opacity: 0 }, 200, function() {
                back.hide();
                front.css({ width: "0", opacity: 0 }).show()
                    .animate({ width: "100%", opacity: 1 }, 200);
            });
            isFlipped = false;
        }
    });
});
</script>
⚠️ Warning: For true 3D flip effects, use CSS3 transforms instead of jQuery animations. CSS transforms provide better performance and smoother animations.

Animation Delay

Use delay() to add pauses between animations.

// Delay before next animation
$("#box")
    .animate({ left: "250px" }, 1000)
    .delay(2000) // Wait 2 seconds
    .animate({ top: "250px" }, 1000);

// Multiple delays
$("#box")
    .fadeOut(500)
    .delay(1000)
    .fadeIn(500)
    .delay(1000)
    .fadeOut(500);

Clearing Animation Queue

Manage the animation queue to prevent unwanted animation buildup.

// Clear all queued animations
$("#box").clearQueue();

// Clear specific queue
$("#box").clearQueue("fx");

// Finish all animations immediately
$("#box").finish();

// Example: Hover with queue management
$("#box").hover(
    function() {
        $(this).stop(true, false).animate({
            width: "200px"
        }, 300);
    },
    function() {
        $(this).stop(true, false).animate({
            width: "100px"
        }, 300);
    }
);

📝 Exercise: Interactive Dashboard Widget

Task: Create an animated dashboard widget that:

  1. Has a circular progress indicator that animates from 0% to 75%
  2. Shows a counter that counts from 0 to 1,500 over 2 seconds
  3. Expands vertically when clicked to reveal detailed statistics
  4. Has 3 sub-metrics that slide in sequentially when expanded
  5. Uses color changes to indicate different value ranges (green for good, yellow for warning, red for critical)
  6. Includes a refresh button that replays all animations

Bonus Challenge: Add sparkline charts that draw themselves using animation, and make the entire widget responsive to different screen sizes.

Performance Best Practices

  • Use CSS3 transitions/animations when possible (better performance)
  • Avoid animating too many elements simultaneously
  • Use stop() before new animations to prevent queue buildup
  • Animate transform and opacity for best performance
  • Avoid animating colors with jQuery (use CSS or jQuery UI)
  • Consider using requestAnimationFrame for complex animations
  • Test on mobile devices as they may have slower animation performance

Summary

  • animate() - Create custom animations on numeric CSS properties
  • Use relative values (+=, -=) for incremental animations
  • Chain animations for sequential effects
  • Combine properties in one animate() for simultaneous effects
  • step callback updates during animation progress
  • delay() adds pauses between animations
  • stop(), clearQueue(), finish() manage animation queue
  • Easing controls animation speed curve (linear, swing)