Create Janmashtami Dahi Handi Animation with HTML, CSS, and JavaScript

Faraz

By Faraz -

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.


create-janmashtami-dahi-handi-animation-with-html-css-and-javascript.webp

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Conclusion
  6. Preview

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

  1. <!DOCTYPE html>: Declares the document type and version (HTML5).
  2. <html lang="en">: Root element of the HTML document, with lang="en" specifying the language as English.
  3. <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.
  4. <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. The piece1, 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 an id of handi.
      • <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 an id of brokenHandi.
      • <div class="curd">: Contains several curd-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 an id of janmashtamiText.
  5. <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; and padding: 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:

  1. Element Selection:
    • const handi = document.getElementById('handi');: Selects the HTML element with the ID handi.
    • const brokenHandi = document.getElementById('brokenHandi');: Selects the HTML element with the ID brokenHandi.
    • const potPieces = document.querySelectorAll('.pot-piece');: Selects all HTML elements with the class pot-piece.
    • const curdDrops = document.querySelectorAll('.curd-drop');: Selects all HTML elements with the class curd-drop.
    • const janmashtamiText = document.getElementById('janmashtamiText');: Selects the HTML element with the ID janmashtamiText.
    • const cursorArea = document.getElementById('cursor-area');: Selects the HTML element with the ID cursor-area.
  2. Event Listener:
    • cursorArea.addEventListener('click', breakHandi);: Adds a click event listener to the cursorArea element. When this element is clicked, the breakHandi function will be executed.
  3. breakHandi Function:
    • handi.classList.add('handi-break');: Adds the classmhandi-break to the handi element, triggering a visual effect.
    • brokenHandi.classList.add('show-broken-handi');: Adds the class show-broken-handi to the brokenHandi element, making it visible its appearance.
    • potPieces.forEach((piece) => piece.classList.add('piecefall'));: Adds the class piecefall to each element with the class pot-piece, causing them to fall.
    • curdDrops.forEach((drop) => drop.classList.add('curdfall'));: Adds the class curdfall to each element with the class curd-drop, causing them to fall.
    • setTimeout(function () { cursorArea.style.display = 'none'; }, 1000);: Hides the cursorArea element by setting its display style to none after 1 second (1000 milliseconds).
    • janmashtamiText.classList.add('textAnimate');: Adds the class textAnimate to the janmashtamiText 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:

create-janmashtami-dahi-handi-animation-with-html-css-and-javascript.gif

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 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post

Please allow ads on our site🥺