Public Holiday Finder with HTML, CSS & JavaScript
30 DAYS 30 PROJECT CHALLENGE
Day #30
Project Overview
A Public Holiday Finder built using HTML, CSS, and JavaScript that allows users to search public holidays by country and year.
The application intelligently uses multiple data sources to ensure accurate results, including Google’s public holiday calendar for India and a public REST API for other countries.
Key Features
- Search public holidays by country and year.
- Supports India holidays using Google Public Holiday Calendar.
- Uses a public REST API for other supported countries.
- Displays holiday name and date in a clean list format.
- Handles unavailable data and future years gracefully.
- Fully frontend-based with no API keys required.
- Clean, responsive, and user-friendly interface.
HTML Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Public Holiday Finder</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="holiday-container">
<h2>Public Holiday Finder</h2>
<div class="controls">
<select id="country">
<option value="US">United States</option>
<option value="IN">India</option>
<option value="GB">United Kingdom</option>
<option value="AU">Australia</option>
<option value="CA">Canada</option>
</select>
<input type="number" id="year" placeholder="Year (e.g. 2025)" />
</div>
<button onclick="getHolidays()">Find Holidays</button>
<div id="holidayList" class="holiday-list"></div>
</div>
<script src="script.js"></script>
</body>
</html>
CSS Code
* {
box-sizing: border-box;
font-family: "Segoe UI", sans-serif;
}
body {
min-height: 100vh;
background: #042453;
display: flex;
justify-content: center;
align-items: flex-start;
padding-top: 40px;
}
.holiday-container {
background: #ffffff;
width: 420px;
padding: 25px;
border-radius: 14px;
box-shadow: 0 20px 40px rgba(0,0,0,0.25);
}
h2 {
text-align: center;
margin-bottom: 15px;
}
.controls {
display: flex;
gap: 10px;
margin-bottom: 10px;
}
select,
input {
flex: 1;
padding: 10px;
border-radius: 6px;
border: 1px solid #ccc;
}
button {
width: 100%;
padding: 10px;
border: none;
border-radius: 6px;
background: #4f46e5;
color: white;
cursor: pointer;
margin-bottom: 15px;
}
.holiday-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.holiday-card {
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 10px;
font-size: 14px;
}
.holiday-card span {
font-size: 12px;
color: #555;
}
.error {
color: red;
text-align: center;
}
Javascript Code
const holidayList = document.getElementById("holidayList");
function getHolidays() {
const country = document.getElementById("country").value;
const year = document.getElementById("year").value || new Date().getFullYear();
holidayList.innerHTML = "Loading...";
// 🇮🇳 INDIA → Google Calendar (ICS)
if (country === "IN") {
const icsUrl =
"https://calendar.google.com/calendar/ical/en.indian%23holiday%40group.v.calendar.google.com/public/basic.ics";
fetch(`https://api.allorigins.win/raw?url=${encodeURIComponent(icsUrl)}`)
.then(res => res.text())
.then(data => {
const events = data.split("BEGIN:VEVENT").slice(1);
const holidays = events
.map(event => {
const summary = event.match(/SUMMARY:(.*)/);
const date = event.match(/DTSTART;VALUE=DATE:(\d+)/);
if (!summary || !date) return null;
return {
name: summary[1],
date:
date[1].slice(0, 4) +
"-" +
date[1].slice(4, 6) +
"-" +
date[1].slice(6, 8)
};
})
.filter(h => h && h.date.startsWith(year));
if (!holidays.length) {
holidayList.innerHTML =
"<p class='error'>No holidays found for this year.</p>";
return;
}
holidayList.innerHTML = "";
holidays.forEach(h => {
holidayList.innerHTML += `
<div class="holiday-card">
<strong>${h.name}</strong><br>
<span>${h.date}</span>
</div>
`;
});
})
.catch(() => {
holidayList.innerHTML =
"<p class='error'>Unable to fetch India holidays.</p>";
});
return;
}
// 🌍 OTHER COUNTRIES → Nager.Date
fetch(`https://date.nager.at/api/v3/PublicHolidays/${year}/${country}`)
.then(res => res.json())
.then(data => {
holidayList.innerHTML = "";
data.forEach(h => {
holidayList.innerHTML += `
<div class="holiday-card">
<strong>${h.localName}</strong><br>
${h.name}<br>
<span>${h.date}</span>
</div>
`;
});
})
.catch(() => {
holidayList.innerHTML =
"<p class='error'>Unable to fetch holidays.</p>";
});
}
Related Projects
Day 20 : Form Auto-Save (Local Storage)
Automatically saves form input data and restores it on reload.
Concepts: LocalStorage usage, input event handling, persistent UI state.
Day 27 : Recipe Finder App
Searches and displays recipes dynamically using a public food API.
Concepts: API integration, async data fetching, dynamic UI rendering.
Day 28 : Language Translator
Translates text between multiple languages using a public translation API.
Concepts: API integration, async data handling, form handling, dynamic UI updates.