Learn how to create a Janmashtami Dahi Handi animation using HTML, CSS, and JavaScript. Follow our guide for a realistic breaking effect and dynamic visuals.
Table of Contents
Janmashtami is a joyful festival celebrated across India to mark the birth of Lord Krishna. One of the most exciting parts of this celebration is the Dahi Handi event. During this event, people form human pyramids to break a pot filled with yogurt, which is hung high in the air. It’s a fun and colorful tradition that captures the spirit of teamwork and festivity.
In this blog post, we will show you how to create a vibrant Dahi Handi animation using HTML, CSS, and JavaScript. Whether you're a web development beginner or someone looking to add a festive touch to your website, this step-by-step guide will make the process easy and enjoyable. By the end of this tutorial, you'll have a lively animation that brings the excitement of Janmashtami to life on your web page.
Source Code
Step 1 (HTML Code):
This HTML code creates a webpage that features an animation for Janmashtami, a Hindu festival celebrating the birth of Lord Krishna. Here’s a breakdown of the components:
HTML Structure
<!DOCTYPE html>
: Declares the document type and version (HTML5).<html lang="en">
: Root element of the HTML document, withlang="en"
specifying the language as English.<head>
: Contains metadata and links to external resources.<meta charset="UTF-8" />
: Sets the character encoding to UTF-8, ensuring the webpage displays characters correctly.<meta name="viewport" content="width=device-width, initial-scale=1.0" />
: Ensures the webpage is responsive, adjusting its layout based on the device's width.<title>Janmashtami Dahi Handi Animation</title>
: Sets the title of the webpage, displayed in the browser tab.<link rel="stylesheet" href="styles.css" />
: Links to an external CSS file for styling the webpage.
<body>
: Contains the content visible on the webpage.<div class="container">
: A container div that holds all the elements for the animation and content.<div class="pot-piece piece1"></div>
through<div class="pot-piece piece10"></div>
: These divs represent pieces of a pot. Thepiece1
,piece2
, etc., classes are used to animate each piece differently.<img src="handi.png" alt="Handi" class="handi" id="handi" />
: An image of a pot (Handi) used in the animation, with anid
ofhandi
.<div id="cursor-area" class="cursor-area"></div>
: A div element used to track cursor movements for interactive effects.<img src="broken_handi.png" alt="Broken Handi" class="broken-handi" id="brokenHandi"/>
: An image of a broken pot, used for an animation effect, with anid
ofbrokenHandi
.<div class="curd">
: Contains severalcurd-drop
divs representing curd (a key component of the Dahi Handi festival).<div class="curd-drop"></div>
: Multiple divs for curd drops, animated to appear as if falling.
<div class="happy-janmashtami" id="janmashtamiText">Happy Janmashtami!</div>
: Displays a text message for the festival, with anid
ofjanmashtamiText
.
<script src="script.js"></script>
: Links to an external JavaScript file that contains the code to make the animation and interactive effects work.
Step 2 (CSS Code):
This CSS code creates a dynamic animation effect for the Dahi Handi celebration. Here's a breakdown of the code:
General Styles
body
:margin: 0;
andpadding: 0;
: Remove default margins and padding.height: 100vh;
: Full viewport height.display: flex; justify-content: center; align-items: center;
: Center the content both horizontally and vertically.background: #000;
: Black background color.overflow: hidden;
: Prevent scrolling.
Container
.container
:position: relative;
: Establish a positioning context for child elements.width: 200px; height: 100vh;
: Set width to 200px and height to 100% of viewport height.
Handi (Clay Pot)
.handi
:width: 100%; height: auto;
: Responsive width, automatic height.position: absolute; left: 50%; transform: translateX(-50%);
: Center horizontally.cursor: pointer;
: Pointer cursor on hover.transition: transform 0.3s ease;
: Smooth scaling effect on hover.
.handi:hover
:transform: translateX(-50%) scale(1.05);
: Slightly scale up the pot on hover.
Cursor Area
.cursor-area
:position: absolute;
: Positioned relative to the parent.width: 76px; height: 70px;
: Size of the cursor area.top: 111px; left: 96px;
: Positioning within the parent.cursor: url(...), auto;
: Custom cursor image.
Broken Handi
.broken-handi
:width: 100%; height: auto;
: Full width, automatic height.position: absolute; bottom: -25px;
: Positioned below the container.transform: translateX(-50%) translateY(200px);
: Positioned with translation.opacity: 0; z-index: 5;
: Initially hidden.
.handi-break
:animation: breakHandi 0.6s forwards ease-in-out;
: Animation for breaking the pot.
.show-broken-handi
:animation: showBrokenHandi 2.5s forwards ease-in-out;
: Animation for showing the broken pot.
Keyframes
@keyframes breakHandi
: Defines the animation for the pot breaking. It involves translating and rotating the pot, and reducing opacity.@keyframes showBrokenHandi
: Defines the animation for showing the broken pot, transitioning opacity and position.
Pot Pieces
.pot-piece
:position: absolute; width: 40px; height: 50px;
: Absolute positioning, defined size.background-color: #bd3a1e; border: 2px solid #bd3a1e;
: Background and border color.transform-style: preserve-3d;
: Maintain 3D transformations.box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
: Shadow effect.opacity: 0;
: Initially hidden.
.piecefall
:animation: piecefall 3s forwards;
: Animation for falling pieces with delays defined by CSS variables.
@keyframes piecefall
: Defines the animation for the pot pieces falling. It includes movement, rotation, and opacity changes.
Individual Pieces
Each piece (e.g., .piece1
, .piece2
) has different clipping paths, rotation values, and delays for falling animations. These give the impression of different shapes and fall patterns.
Curd Drops
.curd
:background: transparent; width: 110%; height: 20%;
: Transparent background with defined size.position: absolute; bottom: 0;
: Positioned at the bottom of the container.
.curd-drop
:background: #f4e9d8; width: 50px; height: 50px;
: Color and size for curd drops.border-radius: 0 50% 50%; transform: rotate(45deg);
: Rounded shape and rotation.
.curdfall
:animation: curdfall 2s ease-in;
: Animation for curd drops falling.
@keyframes curdfall
: Defines the animation for curd drops falling. It moves from top to bottom with varying sizes and delays.
Text Animation
.happy-janmashtami
:position: absolute; width: max-content;
: Centered text.top: 50%; left: 50%;
: Centered in the viewport.transform: translate(-50%, -50%);
: Centered text.color: #fff; font-size: 2em; font-family: 'Arial', sans-serif;
: Text styling.opacity: 0;
: Initially hidden.
.textAnimate
:animation: fadeInText 2s forwards;
: Animation for text fading in with a delay.
@keyframes fadeInText
: Defines the animation for text fading in. It includes text-shadow effects for a glowing appearance.
body {
margin: 0;
padding: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #000;
overflow: hidden;
}
.container {
position: relative;
width: 200px;
height: 100vh;
}
.handi {
width: 100%;
height: auto;
position: absolute;
left: 50%;
transform: translateX(-50%);
cursor: pointer;
transition: transform 0.3s ease;
}
.handi:hover {
transform: translateX(-50%) scale(1.05);
}
.cursor-area {
position: absolute;
width: 76px;
height: 70px;
top: 111px;
left: 96px;
cursor: url(https://www.codewithfaraz.com/project_images/dahi_handi/coconut.png), auto;
background-color: transparent;
}
.broken-handi {
width: 100%;
height: auto;
position: absolute;
bottom: -25px;
left: 50%;
transform: translateX(-50%) translateY(200px);
opacity: 0;
z-index: 5;
}
.handi-break {
animation: breakHandi 0.6s forwards ease-in-out;
}
.show-broken-handi {
animation: showBrokenHandi 2.5s forwards ease-in-out;
}
@keyframes breakHandi {
0% {
transform: translateX(-50%) translateY(0);
}
50% {
transform: translateX(-50%) translateY(-20px) rotate(10deg);
}
100% {
transform: translateX(-50%) translateY(100px) rotate(-45deg);
opacity: 0;
}
}
@keyframes showBrokenHandi {
to {
transform: translateX(-50%) translateY(0);
opacity: 1;
}
}
.pot-piece {
position: absolute;
width: 40px;
height: 50px;
background-color: #bd3a1e;
border: 2px solid #bd3a1e;
transform-style: preserve-3d;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
opacity: 0;
}
.piecefall {
animation: piecefall 3s forwards;
animation-delay: var(--delay);
}
@keyframes piecefall {
0% {
transform: translateY(-150%) rotate(var(--rotate));
opacity: 0;
}
20% {
opacity: 1;
}
70% {
opacity: 0;
}
100% {
transform: translateY(100vh) rotate(var(--rotate-end));
opacity: 0;
}
}
.piece1 {
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
--delay: 0.1s;
--rotate: 0deg;
--rotate-end: 90deg;
left: 10%;
}
.piece2 {
clip-path: polygon(50% 0%, 80% 20%, 60% 100%, 0% 50%);
--delay: 0.15s;
--rotate: 15deg;
--rotate-end: 180deg;
left: 25%;
}
.piece3 {
clip-path: polygon(0 0, 100% 0, 100% 50%, 50% 100%);
--delay: 0.2s;
--rotate: -20deg;
--rotate-end: 270deg;
left: 40%;
}
.piece4 {
clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 50%);
--delay: 0.25s;
--rotate: 30deg;
--rotate-end: 360deg;
left: 55%;
}
.piece5 {
clip-path: polygon(20% 0%, 100% 20%, 80% 100%, 0% 80%);
--delay: 0.3s;
--rotate: -45deg;
--rotate-end: 450deg;
left: 70%;
}
.piece6 {
clip-path: polygon(40% 0%, 100% 20%, 80% 100%, 0% 80%);
--delay: 0.35s;
--rotate: 60deg;
--rotate-end: 540deg;
left: 80%;
}
.piece7 {
clip-path: polygon(20% 0%, 100% 50%, 80% 100%, 0% 50%);
--delay: 0.4s;
--rotate: -90deg;
--rotate-end: 630deg;
left: 20%;
}
.piece8 {
clip-path: polygon(30% 0%, 100% 50%, 50% 100%, 0% 80%);
--delay: 0.45s;
--rotate: 120deg;
--rotate-end: 720deg;
left: 35%;
}
.piece9 {
clip-path: polygon(50% 0%, 100% 50%, 80% 100%, 0% 50%);
--delay: 0.5s;
--rotate: -150deg;
--rotate-end: 810deg;
top: 10%;
left: 50%;
}
.piece10 {
clip-path: polygon(0 0, 100% 20%, 50% 100%, 0% 50%);
--delay: 0.55s;
--rotate: 180deg;
--rotate-end: 900deg;
top: 20%;
left: 35%;
}
.curd {
background: transparent;
width: 110%;
height: 20%;
position: absolute;
bottom: 0;
}
.curd-drop {
background: #f4e9d8;
width: 50px;
height: 50px;
position: absolute;
left: 50%;
bottom: 500%;
border-radius: 0 50% 50%;
transform: translateX(-50%) rotate(45deg);
}
.curd-drop:nth-child(1) {
width: 50px;
height: 50px;
-webkit-animation-delay: 0.1875s;
animation-delay: 0.1875s;
}
.curd-drop:nth-child(2) {
width: 35px;
height: 35px;
-webkit-animation-delay: 0.375s;
animation-delay: 0.375s;
}
.curd-drop:nth-child(3) {
width: 25px;
height: 25px;
-webkit-animation-delay: 0.5625s;
animation-delay: 0.5625s;
}
.curd-drop:nth-child(4) {
width: 15px;
height: 15px;
-webkit-animation-delay: 0.65s;
animation-delay: 0.65s;
}
.curdfall {
-webkit-animation: curdfall 2s ease-in;
animation: curdfall 2s ease-in;
}
@-webkit-keyframes curdfall {
0% {
bottom: 500%;
}
50% {
bottom: -100px;
}
100% {
bottom: -200px;
}
}
@keyframes curdfall {
0% {
bottom: 500%;
}
50% {
bottom: -100px;
}
100% {
bottom: -200px;
}
}
.happy-janmashtami {
position: absolute;
width: max-content;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff;
font-size: 2em;
font-family: 'Arial', sans-serif;
opacity: 0;
z-index: 10;
}
.textAnimate {
animation: fadeInText 2s forwards;
animation-delay: 1.5s;
}
@keyframes fadeInText {
0% {
opacity: 0;
transform: translate(-50%, -40%);
}
100% {
opacity: 1;
transform: translate(-50%, -50%);
text-shadow: 0 0 10px #ff9933, 0 0 20px #ff9933, 0 0 30px #ff9933;
}
}
Step 3 (JavaScript Code):
This JavaScript code handles the visual effects when the user clicks on the handi. Here's a breakdown of what each part does:
- Element Selection:
const handi = document.getElementById('handi');
: Selects the HTML element with the IDhandi
.const brokenHandi = document.getElementById('brokenHandi');
: Selects the HTML element with the IDbrokenHandi
.const potPieces = document.querySelectorAll('.pot-piece');
: Selects all HTML elements with the classpot-piece
.const curdDrops = document.querySelectorAll('.curd-drop');
: Selects all HTML elements with the classcurd-drop
.const janmashtamiText = document.getElementById('janmashtamiText');
: Selects the HTML element with the IDjanmashtamiText
.const cursorArea = document.getElementById('cursor-area');
: Selects the HTML element with the IDcursor-area
.
- Event Listener:
cursorArea.addEventListener('click', breakHandi);
: Adds a click event listener to thecursorArea
element. When this element is clicked, thebreakHandi
function will be executed.
breakHandi
Function:handi.classList.add('handi-break');
: Adds the classmhandi-break
to thehandi
element, triggering a visual effect.brokenHandi.classList.add('show-broken-handi');
: Adds the classshow-broken-handi
to thebrokenHandi
element, making it visible its appearance.potPieces.forEach((piece) => piece.classList.add('piecefall'));
: Adds the classpiecefall
to each element with the classpot-piece
, causing them to fall.curdDrops.forEach((drop) => drop.classList.add('curdfall'));
: Adds the classcurdfall
to each element with the classcurd-drop
, causing them to fall.setTimeout(function () { cursorArea.style.display = 'none'; }, 1000);
: Hides thecursorArea
element by setting its display style tonone
after 1 second (1000 milliseconds).janmashtamiText.classList.add('textAnimate');
: Adds the classtextAnimate
to thejanmashtamiText
element, triggering an animation on the text.
const handi = document.getElementById('handi');
const brokenHandi = document.getElementById('brokenHandi');
const potPieces = document.querySelectorAll('.pot-piece');
const curdDrops = document.querySelectorAll('.curd-drop');
const janmashtamiText = document.getElementById('janmashtamiText');
const cursorArea = document.getElementById('cursor-area');
cursorArea.addEventListener('click', breakHandi);
function breakHandi() {
handi.classList.add('handi-break');
brokenHandi.classList.add('show-broken-handi');
potPieces.forEach((piece) => piece.classList.add('piecefall'));
curdDrops.forEach((drop) => drop.classList.add('curdfall'));
setTimeout(function () {
cursorArea.style.display = 'none';
}, 1000);
janmashtamiText.classList.add('textAnimate');
}
Final Output:
Conclusion:
Congratulations! You’ve just created a lively Dahi Handi animation to celebrate Janmashtami on your website. By following these simple steps with HTML, CSS, and JavaScript, you’ve not only added a festive touch but also practiced essential coding skills. This project is a great way to enhance your web development abilities while also celebrating a beautiful cultural tradition.
Feel free to customize the animation further by adjusting the styles or adding more interactive elements. As you continue to explore web development, you'll find many ways to incorporate animations and designs that make your projects more engaging. Enjoy sharing your creation and have a wonderful Janmashtami!
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 😊