Learn how to create an Indian Independence Day flag animation using HTML, CSS, and GSAP. Follow this easy step-by-step guide to add interactive animations to your web projects.
![Create Indian Independence Day Flag Animation using HTML, CSS & GSAP create-indian-independence-day-flag-animation-using-html-css-and-gsap.webp](img/create-indian-independence-day-flag-animation-using-html-css-and-gsap.webp)
Table of Contents
Indian Independence Day, celebrated on the 15th of August every year, marks the day when India gained freedom from British rule in 1947. This historic event is a significant milestone in the nation's history, symbolizing the end of nearly 200 years of colonial oppression. The day is a tribute to the countless freedom fighters and leaders who sacrificed their lives for the country's independence. In 2024, India proudly celebrates 78 years of freedom, reflecting on the journey from colonial rule to becoming a sovereign republic.
Over the years, Independence Day has become a moment of national pride and unity. Across the country, people participate in various celebrations, from flag-hoisting ceremonies to cultural events that honor India's rich heritage and diversity. The day also serves as a reminder of the values of democracy, freedom, and equality that form the foundation of the nation. As we commemorate this important occasion, it's also a time to reflect on the progress India has made in various fields and the challenges that lie ahead.
In the digital age, technology plays a crucial role in how we celebrate and share the spirit of Independence Day. Creating animations for special occasions like Independence Day can add a unique touch to your web projects. With the right tools, such as HTML, CSS, and JavaScript, you can create an engaging flag animation that will captivate your audience. One of the most powerful tools for creating animations on the web is GSAP (GreenSock Animation Platform). GSAP is a JavaScript library that makes it easy to create complex animations with just a few lines of code.
In this blog, we'll guide you through the process of creating an Indian flag animation using HTML, CSS, and GSAP. Whether you're a beginner or an experienced web developer, this tutorial will help you add a beautiful and interactive flag animation to your website. We'll cover everything from setting up the HTML structure to styling with CSS and animating the flag using GSAP.
By the end of this guide, you'll have a complete Independence Day flag animation that you can proudly showcase on your website. Let's dive in and start creating!
Source Code
Step 1 (HTML Code):
First, we'll create the basic structure of the webpage using HTML. We'll include a div element for the flag, rope, and flagpole.
Here's a breakdown of the code:
<!DOCTYPE html>
and <html lang="en">
<!DOCTYPE html>
: This declaration defines the document type and version of HTML (HTML5 in this case).<html lang="en">
: The opening tag for the HTML document, with the language set to English.
<head>
The <head>
section contains metadata and links to external resources:
<meta charset="UTF-8">
: Sets the character encoding to UTF-8, supporting a wide range of characters.<meta name="viewport" content="width=device-width, initial-scale=1.0">
: Ensures the page is responsive, adjusting to different screen sizes.<title>Happy Independence Day</title>
: Sets the title of the webpage, which appears in the browser tab.<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap">
: Links to the Google Fonts API to use the "Poppins" font family.<link rel="stylesheet" href="styles.css">
: Links to an external CSS file (styles.css
) for styling the webpage.
<body>
The <body>
section contains the main content of the webpage:
<div class="container">
- This
<div>
acts as the main container for all the content on the page.
<div class="flag-container">
- This
<div>
contains elements related to the flag and its animation.
Flag Elements
<div class="pole"></div>
: Represents the flagpole.<div class="flag" id="flag">
: Contains the three sections of the flag.<div class="saffron"></div>
: The saffron (top) part of the Indian flag.<div class="white">
: The white (middle) part of the flag, which also contains the Ashoka Chakra.<img src="https://i.ibb.co/qy2Xkr4/ashoka-chakra.png"
: The Ashoka Chakra image is embedded in the middle section of the flag.
<div class="green"></div>
: The green (bottom) part of the flag.
Rope Elements
<div class="rope-group group-1">
: Represents a group of rope segments used for animation.<div class="rope" id="rope">
: Contains an SVG (Scalable Vector Graphics) of the rope.<svg>
: Defines the SVG container for the rope drawing.<path id="rope" d="M50 0 V310"
: The main rope path.- Other paths (
#rope-original
,#rope-extended
,#rope-compressed
,#rope-end
): These are used for different stages or styles of rope animation, hidden initially with theclass="hidden"
attribute.
<div class="message" id="message">
- This section displays the Independence Day message.
<h1>Happy Independence Day!</h1>
: The main heading displaying the message.<p>Celebrating 78 Years of Freedom</p>
: A paragraph underneath the heading.
External JavaScript Files
<script src="https://unpkg.co/gsap@3/dist/gsap.min.js"></script>
: Links to the GSAP (GreenSock Animation Platform) library for animations.<script src="https://asse....MorphSVGPlugin3.min.js"></script>
: Links to the MorphSVG plugin, which helps animate SVG elements.<script src="script.js"></script>
: Links to an external JavaScript file (script.js
) that contains custom animation logic for the flag and rope.
Step 2 (CSS Code):
Next, we'll style the flag, rope, and flagpole using CSS. The flag will have three colors (saffron, white, and green) with the Ashoka Chakra in the center.
Here's a breakdown of each section:
1. body Selector:
body { margin: 0; padding: 0; font-family: 'Poppins', sans-serif; background: #242437; display: flex; justify-content: center; align-items: center; height: 100vh; }
- margin & padding: Removes default spacing around the page.
- font-family: Sets the text font to 'Poppins'.
- background: Sets the background color to a dark shade #242437.
- display, justify-content, align-items: Centers content both vertically and horizontally using Flexbox.
- height: Ensures the body takes up the full height of the viewport.
2. .container Selector:
.container { display: flex; flex-direction: row; align-items: center; }
- display: Sets the container as a Flexbox.
- flex-direction: Aligns items in a row (horizontally).
- align-items: Vertically centers the items within the container.
3. .flag-container Selector:
.flag-container { position: relative; width: 200px; height: 400px; }
- position: Allows positioning of child elements relative to this container.
- width & height: Defines the size of the container.
4. .pole Selector:
.pole { content: ""; position: absolute; left: 20px; width: 1em; height: 100%; border-radius: 0 0 0.5em 0.5em/0 0 0.3em 0.3em; background-image: linear-gradient(#7777, #6660, #555), linear-gradient(90deg, #777, #fff, #555); }
- content: Ensures the element is generated (usually for ::before or ::after pseudo-elements).
- position: Positions the pole relative to its container.
- border-radius: Adds rounded corners at the bottom of the pole.
- background-image: Adds linear gradients to create a metallic pole effect.
5. .pole::before & .pole::after Selectors:
.pole::before { content: ""; position: absolute; top: 100%; left: 50%; width: 4em; height: 4em; transform: translate(-50%, -50%) rotateX(90deg); background-image: radial-gradient(#0004, #0000 60%); } .pole::after { content: ""; position: absolute; top: 0%; left: 50%; width: 1em; height: 0.4em; border-radius: 50%; transform: translate(-50%, -50%); background-image: radial-gradient(circle at top, #aaa, #333); }
- ::before: Creates a shadow or base at the bottom of the pole.
- ::after: Adds a decorative element at the top of the pole, a cap, or top ornament.
6. .flag Selector:
.flag { position: absolute; top: 50%; left: 36px; width: 180px; height: 110px; display: flex; flex-direction: column; transition: top 2s ease-in-out; overflow: hidden; }
- position: Positions the flag relative to its container.
- flex-direction: Arranges flag stripes in a vertical column.
- transition: Smooth transition for changes in the flag's vertical position.
7. .saffron, .white, .green Selectors:
.saffron { height: 33%; background-color: #FF9933; } .white { height: 34%; background-color: #fff; position: relative; } .green { height: 33%; background-color: #128807; }
- height & background-color: Define the color and size of each stripe of the flag (saffron, white, and green).
8. .ashoka-chakra Selector:
.ashoka-chakra { width: 40px; height: 40px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) rotate(0deg); animation: chakra-spin 5s linear infinite; }
- position: Centers the Ashoka Chakra within the white stripe.
- animation: Rotates the Ashoka Chakra continuously using the chakra-spin keyframes.
9. .rope-group & Related Selectors:
.rope-group { width: 20px; z-index: 10; position: absolute; top: 14px; left: 18px; display: flex; flex-direction: column; gap: 1px 0; }
- z-index: Ensures the rope is layered above other elements.
- gap: Spaces out individual ropes within the group.
.rope-group .rope-bundle { width: 100%; height: 3px; border-radius: 20px; background: #222; transform: rotate(var(--rotate)); }
- transform: Rotates each rope bundle by a specified angle, controlled by CSS variables.
10. .rope & .rope-label Selectors:
.rope { position: absolute; bottom: 0; cursor: pointer; }
- cursor: Indicates that the rope is interactive (clickable).
.rope-label { position: absolute; bottom: 0; left: 50%; transform: translateX(-50%) rotate(-90deg); background-color: #a0522d; color: #fff; padding: 5px; font-size: 14px; text-align: center; cursor: pointer; user-select: none; }
- transform: Rotates the label to align with the rope.
11. .message Selector:
.message { margin-left: 50px; font-size: 24px; opacity: 0; color: #fff; transition: opacity 2s ease-in-out; }
- opacity: Starts hidden, then fades in smoothly.
- transition: Controls the fade-in effect.
12. @keyframes for Text and Chakra Animation:
@keyframes text-glow { 0% { text-shadow: 0 0 10px #ff9933, 0 0 20px #ff9933, 0 0 30px #ff9933; } 100% { text-shadow: 0 0 20px #138808, 0 0 30px #138808, 0 0 40px #138808; } } @keyframes chakra-spin { from { transform: translate(-50%, -50%) rotate(0deg); } to { transform: translate(-50%, -50%) rotate(360deg); } }
- text-glow: Creates a glowing effect for text that alternates between saffron and green colors.
- chakra-spin: Rotates the Ashoka Chakra in a full circle continuously.
body {
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
background: #242437;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
display: flex;
flex-direction: row;
align-items: center;
}
.flag-container {
position: relative;
width: 200px;
height: 400px;
}
.pole {
content: "";
position: absolute;
left: 20px;
width: 1em;
height: 100%;
border-radius: 0 0 0.5em 0.5em/0 0 0.3em 0.3em;
background-image: linear-gradient(#7777, #6660, #555), linear-gradient(90deg, #777, #fff, #555);
}
.pole::before {
content: "";
position: absolute;
top: 100%;
left: 50%;
width: 4em;
height: 4em;
transform: translate(-50%, -50%) rotateX(90deg);
background-image: radial-gradient(#0004, #0000 60%);
}
.pole::after {
content: "";
position: absolute;
top: 0%;
left: 50%;
width: 1em;
height: 0.4em;
border-radius: 50%;
transform: translate(-50%, -50%);
background-image: radial-gradient(circle at top, #aaa, #333);
}
.flag {
position: absolute;
top: 50%;
left: 36px;
width: 180px;
height: 110px;
display: flex;
flex-direction: column;
transition: top 2s ease-in-out;
overflow: hidden;
}
.saffron {
height: 33%;
background-color: #FF9933;
}
.white {
height: 34%;
background-color: #fff;
position: relative;
}
.green {
height: 33%;
background-color: #128807;
}
.ashoka-chakra {
width: 40px;
height: 40px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(0deg);
animation: chakra-spin 5s linear infinite;
}
.rope-group {
width: 20px;
z-index: 10;
position: absolute;
top: 14px;
left: 18px;
display: flex;
flex-direction: column;
gap: 1px 0;
}
.rope-group .rope-bundle {
width: 100%;
height: 3px;
border-radius: 20px;
background: #222;
transform: rotate(var(--rotate));
}
.rope-group .rope-1 {
--rotate: 10deg
}
.rope-group .rope-2 {
--rotate: -4deg
}
.rope-group .rope-3 {
--rotate: 6deg
}
.rope-group .rope-4 {
--rotate: 0deg
}
.rope-group .rope-5 {
--rotate: -6deg
}
.rope-group .rope-6 {
--rotate: 6deg
}
.rope-group .rope-7 {
--rotate: -2deg
}
.rope-group .rope-8 {
--rotate: -10deg
}
.rope-group.group-1 :is(.rope-2, .rope-5) {
--rotate: 10deg
}
.rope-group.group-1 :is(.rope-3, .rope-6) {
--rotate: -10deg
}
.rope {
position: absolute;
bottom: 0;
cursor: pointer;
}
.rope svg {
width: 100%;
height: auto;
}
.hidden {
visibility: hidden;
}
.rope-label {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%) rotate(-90deg);
background-color: #a0522d;
color: #fff;
padding: 5px;
font-size: 14px;
text-align: center;
cursor: pointer;
user-select: none;
}
.message {
margin-left: 50px;
font-size: 24px;
opacity: 0;
color: #fff;
transition: opacity 2s ease-in-out;
}
.message h1 {
font-size: 2.5rem;
margin: 0;
padding: 0;
animation: text-glow 1s infinite alternate;
}
.message p {
font-size: 1.2rem;
margin: 10px 0 0 0;
animation: text-glow 1s infinite alternate;
}
@keyframes text-glow {
0% {
text-shadow: 0 0 10px #ff9933, 0 0 20px #ff9933, 0 0 30px #ff9933;
}
100% {
text-shadow: 0 0 20px #138808, 0 0 30px #138808, 0 0 40px #138808;
}
}
@keyframes chakra-spin {
from {
transform: translate(-50%, -50%) rotate(0deg);
}
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
Step 3 (JavaScript Code):
Now comes the fun part—animating the flag using GSAP. We'll create an interactive effect for the flag and rope.
Here's a breakdown of what the code does:
Variables and Setup
isChecked
: A boolean variable that tracks the state of the flag (raised or lowered). It starts asfalse
, indicating the flag is initially lowered.flag
: The flag element, selected by its ID (flag
), which will be animated.svg
: Another reference to the sameflag
element, which might be redundant in this context.
Function: raiseFlag()
This function handles the animation and state change of the flag and rope.
tl = gsap.timeline();
: This creates a new timeline for GSAP animations, allowing multiple animations to be sequenced together.- Conditional Logic:
if (isChecked)
: Checks whether the flag is currently raised (isChecked
istrue
).- If
isChecked
istrue
(flag is raised):- Animates the rope to compress and then return to its
original state using
morphSVG
. - Moves the end of the rope upwards (y: 250) and then downwards (y: 300) with a bouncing effect.
- Toggles the
isChecked
state tofalse
. - Moves the flag's
top
position to50%
, effectively lowering it.
- Animates the rope to compress and then return to its
original state using
- If
else
: If the flag is currently lowered (isChecked
isfalse
):- The same sequence of animations occurs, but:
- The
isChecked
state is toggled totrue
. - The flag's
top
position is set to11%
, raising the flag.
- The
- The same sequence of animations occurs, but:
setTimeout
:- After a 2-second delay, a message element's opacity is set to
1
, making it visible. This could be a message indicating the flag has been raised or lowered.
- After a 2-second delay, a message element's opacity is set to
Event Listener
document.querySelector('.rope').addEventListener('click', raiseFlag);
:- This line adds a click event listener to an element with the class
rope
. - When the rope element is clicked, the
raiseFlag()
function is triggered, initiating the flag-raising animation.
- This line adds a click event listener to an element with the class
let isChecked = false;
function raiseFlag() {
const flag = document.getElementById('flag');
const svg = document.getElementById('flag');
const tl = gsap.timeline();
if (isChecked) {
tl.to(
"#rope",
{ duration: 0.4, morphSVG: "#rope-compressed", ease: "bounce.out" },
"up"
);
tl.to(
"#rope",
{ duration: 0.2, morphSVG: "#rope-original", ease: "bounce.out" },
"down"
);
tl.to("#rope-end", { duration: 0.4, y: 250, ease: "bounce.out" }, "up");
tl.to("#rope-end", { duration: 0.2, y: 300, ease: "bounce.out" }, "down");
isChecked = !isChecked;
flag.style.top = '50%';
} else {
tl.to(
"#rope",
{ duration: 0.4, morphSVG: "#rope-compressed", ease: "bounce.out" },
"up"
);
tl.to(
"#rope",
{ duration: 0.2, morphSVG: "#rope-original", ease: "bounce.out" },
"down"
);
tl.to("#rope-end", { duration: 0.4, y: 250, ease: "bounce.out" }, "up");
tl.to("#rope-end", { duration: 0.2, y: 300, ease: "bounce.out" }, "down");
isChecked = !isChecked;
flag.style.top = '11%';
}
setTimeout(() => {
message.style.opacity = '1';
}, 2000);
}
document.querySelector('.rope').addEventListener('click', raiseFlag);
Final Output:
![Create Indian Independence Day Flag Animation using HTML, CSS & GSAP create-indian-independence-day-flag-animation-using-html-css-and-gsap.gif](img/create-indian-independence-day-flag-animation-using-html-css-and-gsap.gif)
See the Pen Untitled by Faraz (@codewithfaraz) on CodePen.
Conclusion:
Creating an Indian Independence Day flag animation using HTML, CSS, and GSAP is a rewarding project that adds a touch of patriotism to your web pages. With the steps outlined in this guide, you can easily create a beautiful animation that will impress your audience. GSAP is a powerful tool that simplifies the process of creating complex animations, making it accessible even for beginners.
Whether you're building a website for Independence Day or just want to enhance your web development skills, this project is a great way to celebrate the spirit of freedom. Give it a try, and feel free to experiment with different effects to make the animation uniquely yours.
Jai Hind!
That’s a wrap!
I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.
Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee
And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!
Thanks!
Faraz 😊