In today’s digital age, interactive calendars are essential components of web applications. They facilitate date selection, scheduling, and time management. In this blog post, we’ll explore how to create three types of interactive calendars using HTML, CSS, JavaScript, and Bootstrap. These calendars cater to various needs, from selecting a single date to choosing date ranges spanning across one or two months.
- Simple Calendar for Single Date Selection-
Our first calendar implementation is a straightforward solution for selecting a single date. It provides users with a clear interface to pick a date from a single month view. This calendar is ideal for applications where precise date selection is required, such as appointment scheduling or event registration. Check its live demonstration here

HTML, CSS, SCRIPT, Head tags
<!DOCTYPE html>
<html
lang=”en”>
<head>
<meta
charset=”UTF-8″>
<meta name=”viewport”
content=”width=device-width, initial-scale=1.0″>
<title>Calendar</title>
<link
rel=”stylesheet” href=”style.css”>
<link
href=”https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css”
rel=”stylesheet”>
<link rel=”stylesheet”
href=”https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css”>
</head>
<body>
<style>
#home{
min-height: 95vh;
background-color: #090912;
background-image:
url(yellow.jpg);
background-size: cover;
}
.calendar {
position: absolute;
top: 0%;
background-color: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0,
0.1);
padding: 20px;
z-index: 1000;
display:
none;
left: -1px;
}
.bg-light-dark{
background-color: #08071b !important;
border: none
!important;
}
.day {
width: 14.28%;
text-align:
center;
padding: 5px;
border: 1px solid #ccc;
}
.active{
background-color: grey;
font-weight:
bolder;
}
.hover{
background-color: rgb(181, 181,
181);
font-weight: bolder;
cursor: pointer;
}
.form-control::placeholder {
color: white;
}
@media
(max-width:540px) {
.calendar {
padding: 10px;
}
.day{
font-size: 10px;
}
.nav-btns{
font-size:
12px;
}
}
</style>
<ul
class=”nav justify-content-center py-2 bg-dark”>
<li
class=”nav-item”>
<a href=”index.html”><button
class=”btn btn-light mx-1 nav-btns”>Single
Date</button></a>
</li>
<li
class=”nav-item”>
<a
href=”calendar.html”><button
class=”btn btn-light mx-1 nav-btns”>Date
Range</button></a>
</li>
<li
class=”nav-item”>
<a
href=”twomntthcalendar.html”><button
class=”btn btn-light mx-1 nav-btns”>Month
Range</button></a>
</li>
</ul>
<section id=”home”>
<h5
class=”text-center pt-5″>Simple Calendar for Single Date
Selection</h5>
<div
class=”container pt-2 d-flex justify-content-center “>
<div class=”card card-body bg-dark ”
style=”max-width: 600px;”>
<div class=”row”>
<div class=”col-12″>
<div
class=”input-group flex-nowrap”>
<input type=”text”
id=”dateInput” class=”form-control bg-light-dark text-light”
placeholder=”Select Date” readonly>
<button
id=”openCalendarBtn” class=”btn btn-primary”
style=”border-radius: 0px 3px 3px 0px;”><i
class=”bi bi-calendar-range”></i></button>
</div>
</div>
<div class=”col-12″>
<div id=”calendar” class=”calendar mt-3″>
<div
class=”row”>
<div class=”col-12 d-flex “>
<div class=”form-group w-100 “>
<select
id=”yearSelect” class=”form-control”>
<!– Year
options will be populated by JavaScript –>
</select>
</div>
<div
class=”form-group w-100 mx-2″>
<select
id=”monthSelect” class=”form-control”>
<option
value=”0″>January</option>
<option
value=”1″>February</option>
<option
value=”2″>March</option>
<option
value=”3″>April</option>
<option
value=”4″>May</option>
<option
value=”5″>June</option>
<option
value=”6″>July</option>
<option
value=”7″>August</option>
<option
value=”8″>September</option>
<option
value=”9″>October</option>
<option
value=”10″>November</option>
<option
value=”11″>December</option>
</select>
</div>
<h6 class=”text-end”>
<button
id=”closeCalendarBtn”
class=”btn btn-secondary”>X</button>
</h6>
</div>
<div class=”col-12″>
<div id=”calendarDays” class=”d-flex flex-wrap”>
<!– Calendar days will be populated by JavaScript –>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<script>
// calnedar 1
// Get elements
const dateInput =
document.getElementById(‘dateInput’);
const openCalendarBtn
= document.getElementById(‘openCalendarBtn’);
const calendar
= document.getElementById(‘calendar’);
const
closeCalendarBtn =
document.getElementById(‘closeCalendarBtn’);
const
yearSelect = document.getElementById(‘yearSelect’);
const
monthSelect = document.getElementById(‘monthSelect’);
const
calendarDays =
document.getElementById(‘calendarDays’);
// Function to
populate years in select
function populateYears() {
const
currentYear = new Date().getFullYear();
for (let i =
currentYear – 10; i <= currentYear + 10; i++) {
const
option = document.createElement(‘option’);
option.value =
i;
option.textContent = i;
yearSelect.appendChild(option);
}
// Select the first
option (index 0) by default
yearSelect.options[0].selected =
true;
}
// Function to populate calendar
days
function populateCalendar(year, month) {
// Select
the corresponding option in the year select
yearSelect.value
= year;
// Select the corresponding option in the month
select
monthSelect.value = month.toString();
calendarDays.innerHTML = ”;
const daysInMonth = new
Date(year, month + 1, 0).getDate();
const firstDayOfMonth =
new Date(year, month, 1).getDay(); // 0 is Sunday, 1 is Monday,
etc.
const daysOfWeek = [‘Sun’, ‘Mon’, ‘Tue’, ‘Wed’, ‘Thu’,
‘Fri’, ‘Sat’];
// Add days of the week headers
for
(let i = 0; i < 7; i++) {
const dayHeader =
document.createElement(‘div’);
dayHeader.textContent =
daysOfWeek[i];
dayHeader.classList.add(‘day’,
‘font-weight-bold’);
calendarDays.appendChild(dayHeader);
}
// Add empty
cells for days before the first day of the month
for (let i
= 0; i < firstDayOfMonth; i++) {
const emptyCell =
document.createElement(‘div’);
emptyCell.classList.add(‘day’);
calendarDays.appendChild(emptyCell);
}
// Add days
of the month
for (let i = 1; i <= daysInMonth; i++) {
const day = document.createElement(‘div’);
day.textContent =
i;
day.classList.add(‘day’);
day.addEventListener(‘click’, () => {
// Remove active class
from all dates
const allDays =
document.querySelectorAll(‘.day’);
allDays.forEach(day =>
day.classList.remove(‘active’));
// Add active class to the
clicked date
day.classList.add(‘active’);
dateInput.value = `${year}-${String(month + 1).padStart(2,
‘0’)}-${String(i).padStart(2, ‘0’)}`;
closeCalendar();
});
day.addEventListener(‘mouseover’, () => {
day.classList.add(‘hover’);
});
day.addEventListener(‘mouseleave’, () => {
day.classList.remove(‘hover’);
});
calendarDays.appendChild(day);
}
}
// Function to
open calendar
function openCalendar() {
calendar.style.display = ‘block’;
}
// Function to
close calendar
function closeCalendar() {
calendar.style.display = ‘none’;
}
// Event
listeners
openCalendarBtn.addEventListener(‘click’, () =>
{
populateYears();
populateCalendar(new
Date().getFullYear(), new Date().getMonth());
openCalendar();
});
closeCalendarBtn.addEventListener(‘click’,
closeCalendar);
yearSelect.addEventListener(‘change’, ()
=> {
populateCalendar(parseInt(yearSelect.value),
parseInt(monthSelect.value));
});
monthSelect.addEventListener(‘change’, () => {
populateCalendar(parseInt(yearSelect.value),
parseInt(monthSelect.value));
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calendar</title>
<link rel="stylesheet" href="style.css">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
</head>
<body>
<style>
#home{
min-height: 95vh;
background-color: #090912;
background-image: url(yellow.jpg);
background-size: cover;
}
.calendar {
position: absolute;
top: 0%;
background-color: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
padding: 20px;
z-index: 1000;
display: none;
left: -1px;
}
.bg-light-dark{
background-color: #08071b !important;
border: none !important;
}
.day {
width: 14.28%;
text-align: center;
padding: 5px;
border: 1px solid #ccc;
}
.active{
background-color: grey;
font-weight: bolder;
}
.hover{
background-color: rgb(181, 181, 181);
font-weight: bolder;
cursor: pointer;
}
.form-control::placeholder {
color: white;
}
@media (max-width:540px) {
.calendar {
padding: 10px;
}
.day{
font-size: 10px;
}
.nav-btns{
font-size: 12px;
}
}
</style>
<ul class="nav justify-content-center py-2 bg-dark">
<li class="nav-item">
<a href="index.html"><button class="btn btn-light mx-1 nav-btns">Single Date</button></a>
</li>
<li class="nav-item">
<a href="calendar.html"><button class="btn btn-light mx-1 nav-btns">Date Range</button></a>
</li>
<li class="nav-item">
<a href="twomntthcalendar.html"><button class="btn btn-light mx-1 nav-btns">Month Range</button></a>
</li>
</ul>
<section id="home">
<h5 class="text-center pt-5">Simple Calendar for Single Date Selection</h5>
<div class="container pt-2 d-flex justify-content-center ">
<!-- calendar 1 -->
<div class="card card-body bg-dark " style="max-width: 600px;">
<div class="row">
<div class="col-12">
<div class="input-group flex-nowrap">
<input type="text" id="dateInput" class="form-control bg-light-dark text-light" placeholder="Select Date" readonly>
<button id="openCalendarBtn" class="btn btn-primary" style="border-radius: 0px 3px 3px 0px;"><i class="bi bi-calendar-range"></i></button>
</div>
</div>
<div class="col-12">
<div id="calendar" class="calendar mt-3">
<div class="row">
<div class="col-12 d-flex ">
<div class="form-group w-100 ">
<select id="yearSelect" class="form-control">
<!-- Year options will be populated by JavaScript -->
</select>
</div>
<div class="form-group w-100 mx-2">
<select id="monthSelect" class="form-control">
<option value="0">January</option>
<option value="1">February</option>
<option value="2">March</option>
<option value="3">April</option>
<option value="4">May</option>
<option value="5">June</option>
<option value="6">July</option>
<option value="7">August</option>
<option value="8">September</option>
<option value="9">October</option>
<option value="10">November</option>
<option value="11">December</option>
</select>
</div>
<h6 class="text-end">
<button id="closeCalendarBtn" class="btn btn-secondary">X</button>
</h6>
</div>
<div class="col-12">
<div id="calendarDays" class="d-flex flex-wrap">
<!-- Calendar days will be populated by JavaScript -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<script>
// calnedar 1
// Get elements
const dateInput = document.getElementById('dateInput');
const openCalendarBtn = document.getElementById('openCalendarBtn');
const calendar = document.getElementById('calendar');
const closeCalendarBtn = document.getElementById('closeCalendarBtn');
const yearSelect = document.getElementById('yearSelect');
const monthSelect = document.getElementById('monthSelect');
const calendarDays = document.getElementById('calendarDays');
// Function to populate years in select
function populateYears() {
const currentYear = new Date().getFullYear();
for (let i = currentYear - 10; i <= currentYear + 10; i++) {
const option = document.createElement('option');
option.value = i;
option.textContent = i;
yearSelect.appendChild(option);
}
// Select the first option (index 0) by default
yearSelect.options[0].selected = true;
}
// Function to populate calendar days
function populateCalendar(year, month) {
// Select the corresponding option in the year select
yearSelect.value = year;
// Select the corresponding option in the month select
monthSelect.value = month.toString();
calendarDays.innerHTML = '';
const daysInMonth = new Date(year, month + 1, 0).getDate();
const firstDayOfMonth = new Date(year, month, 1).getDay(); // 0 is Sunday, 1 is Monday, etc.
const daysOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
// Add days of the week headers
for (let i = 0; i < 7; i++) {
const dayHeader = document.createElement('div');
dayHeader.textContent = daysOfWeek[i];
dayHeader.classList.add('day', 'font-weight-bold');
calendarDays.appendChild(dayHeader);
}
// Add empty cells for days before the first day of the month
for (let i = 0; i < firstDayOfMonth; i++) {
const emptyCell = document.createElement('div');
emptyCell.classList.add('day');
calendarDays.appendChild(emptyCell);
}
// Add days of the month
for (let i = 1; i <= daysInMonth; i++) {
const day = document.createElement('div');
day.textContent = i;
day.classList.add('day');
day.addEventListener('click', () => {
// Remove active class from all dates
const allDays = document.querySelectorAll('.day');
allDays.forEach(day => day.classList.remove('active'));
// Add active class to the clicked date
day.classList.add('active');
dateInput.value = `${year}-${String(month + 1).padStart(2, '0')}-${String(i).padStart(2, '0')}`;
closeCalendar();
});
day.addEventListener('mouseover', () => {
day.classList.add('hover');
});
day.addEventListener('mouseleave', () => {
day.classList.remove('hover');
});
calendarDays.appendChild(day);
}
}
// Function to open calendar
function openCalendar() {
calendar.style.display = 'block';
}
// Function to close calendar
function closeCalendar() {
calendar.style.display = 'none';
}
// Event listeners
openCalendarBtn.addEventListener('click', () => {
populateYears();
populateCalendar(new Date().getFullYear(), new Date().getMonth());
openCalendar();
});
closeCalendarBtn.addEventListener('click', closeCalendar);
yearSelect.addEventListener('change', () => {
populateCalendar(parseInt(yearSelect.value), parseInt(monthSelect.value));
});
monthSelect.addEventListener('change', () => {
populateCalendar(parseInt(yearSelect.value), parseInt(monthSelect.value));
});
</script>
</body>
</html>
2. Date Range Selection within a Single Month-
The second calendar extends the functionality to allow users to select a date range within the same month. It features two input fields for the start and end dates, along with a calendar interface for intuitive date selection. This calendar is useful for applications involving tasks or events spanning over a specific time frame within a month. Check its live demonstration here

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calendar Example</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<style>
#home{
min-height: 100vh;
background-image: url(bg-blue.jpg);
background-size: cover;
padding-top: 70px;
}
/* Custom styles */
.calendar {
position: absolute;
top: 0%;
background-color: #101220;
color: white;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
padding: 20px;
z-index: 1000;
display: none;
left: 1px;
justify-content: center;
}
.day {
width: 12.28%;
text-align: center;
padding: 5px 1px;
border: 1px solid #ccc;
border-radius: 15px;
margin: 2px;
}
.active {
background-color: rgb(0, 172, 206);
color: white;
font-weight: bolder;
}
.hover {
background-color: rgb(0, 172, 206);
font-weight: bolder;
cursor: pointer;
color: white;
}
.active-between{
background-color: rgb(103, 103, 103) !important;
}
#calendarDays{
margin-left: 30px;
}
@media (max-width:540px) {
.calendar {
padding: 10px;
}
.day {
font-size: 10px;
}
#calendarDays{
margin-left: 10px;
}
.nav-btns{
font-size: 12px;
}
}
.bg-light-dark{
background-color: #08071b !important;
border: 1px solid rgb(80, 80, 80) !important;
}
.form-control::placeholder {
color: white;
}
</style>
</head>
<body>
<ul class="nav justify-content-center py-2 bg-transparent fixed-top">
<li class="nav-item">
<a href="index.html"><button class="btn btn-light mx-1 nav-btns">Single Date</button></a>
</li>
<li class="nav-item">
<a href="calendar.html"><button class="btn btn-light mx-1 nav-btns">Date Range</button></a>
</li>
<li class="nav-item">
<a href="twomntthcalendar.html"><button class="btn btn-light mx-1 nav-btns">Month Range</button></a>
</li>
</ul>
<section id="home">
<h5 class="text-center pt-5">Date Range Selection within a Single Month</h5>
<div class="container pt-2 d-flex justify-content-center align-items-center">
<div class="card card-body bg-dark" style="max-width: 600px;">
<div class="row">
<div class="col-12 px-0">
<div class="input-group flex-nowrap">
<input type="text" id="startDateInput" class="form-control bg-light-dark text-light" placeholder="Select Start Date">
<input type="text" id="endDateInput" class="form-control bg-light-dark text-light" placeholder="Select End Date">
<button id="openCalendarBtn" class="btn btn-primary" style="border-radius: 0px 3px 3px 0px;"><i class="bi bi-calendar-range"></i></button>
</div>
</div>
<div class="col-12">
<div id="calendar" class="calendar mt-3">
<div class="row">
<div class="col-12 d-flex ">
<div class="form-group w-100 ">
<select id="yearSelect" class="form-control">
<!-- Year options will be populated by JavaScript -->
</select>
</div>
<div class="form-group w-100 mx-2">
<select id="monthSelect" class="form-control">
<option value="0">January</option>
<option value="1">February</option>
<option value="2">March</option>
<option value="3">April</option>
<option value="4">May</option>
<option value="5">June</option>
<option value="6">July</option>
<option value="7">August</option>
<option value="8">September</option>
<option value="9">October</option>
<option value="10">November</option>
<option value="11">December</option>
</select>
</div>
<h6 class="text-end">
<button id="closeCalendarBtn" class="btn btn-secondary">X</button>
</h6>
</div>
<div class="col-12">
<div id="calendarDays" class="d-flex flex-wrap">
<!-- Calendar days will be populated by JavaScript -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<script>
// Get elements
const openCalendarBtn = document.getElementById('openCalendarBtn');
const calendar = document.getElementById('calendar');
const closeCalendarBtn = document.getElementById('closeCalendarBtn');
const yearSelect = document.getElementById('yearSelect');
const monthSelect = document.getElementById('monthSelect');
const calendarDays = document.getElementById('calendarDays');
const startDateInput = document.getElementById('startDateInput');
const endDateInput = document.getElementById('endDateInput');
let selectedStartDate = null;
let selectedEndDate = null;
// Function to populate years in select
function populateYears() {
const currentYear = new Date().getFullYear();
for (let i = currentYear - 10; i <= currentYear + 10; i++) {
const option = document.createElement('option');
option.value = i;
option.textContent = i;
yearSelect.appendChild(option);
}
// Select the first option (index 0) by default
yearSelect.options[0].selected = true;
}
// Function to populate calendar days
function populateCalendar(year, month) {
// Select the corresponding option in the year select
yearSelect.value = year;
// Select the corresponding option in the month select
monthSelect.value = month.toString();
calendarDays.innerHTML = '';
const daysInMonth = new Date(year, month + 1, 0).getDate();
const firstDayOfMonth = new Date(year, month, 1).getDay(); // 0 is Sunday, 1 is Monday, etc.
const daysOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
// Add days of the week headers
for (let i = 0; i < 7; i++) {
const dayHeader = document.createElement('div');
dayHeader.textContent = daysOfWeek[i];
dayHeader.classList.add('day', 'font-weight-bold');
calendarDays.appendChild(dayHeader);
}
// Add empty cells for days before the first day of the month
for (let i = 0; i < firstDayOfMonth; i++) {
const emptyCell = document.createElement('div');
emptyCell.classList.add('day');
calendarDays.appendChild(emptyCell);
}
// Add days of the month
for (let i = 1; i <= daysInMonth; i++) {
const day = document.createElement('div');
day.textContent = i;
day.classList.add('day');
day.addEventListener('click', () => {
if (!selectedStartDate) {
selectedStartDate = new Date(year, month, i);
startDateInput.value = `${String(i).padStart(2, '0')}-${String(month + 1).padStart(2, '0')}-${year}`;
day.classList.add('active');
} else if (!selectedEndDate) {
selectedEndDate = new Date(year, month, i);
endDateInput.value = `${String(i).padStart(2, '0')}-${String(month + 1).padStart(2, '0')}-${year}`;
day.classList.add('active');
// Ensure end date is greater than or equal to start date
if (selectedEndDate < selectedStartDate) {
const temp = selectedStartDate;
selectedStartDate = selectedEndDate;
selectedEndDate = temp;
startDateInput.value = `${selectedStartDate.getFullYear()}-${String(selectedStartDate.getMonth() + 1).padStart(2, '0')}-${String(selectedStartDate.getDate()).padStart(2, '0')}`;
endDateInput.value = `${selectedEndDate.getFullYear()}-${String(selectedEndDate.getMonth() + 1).padStart(2, '0')}-${String(selectedEndDate.getDate()).padStart(2, '0')}`;
}
// Add .active-between class to dates between start and end dates
const allDays = document.querySelectorAll('.day');
allDays.forEach(day => {
const dayValue = parseInt(day.textContent);
if (dayValue > selectedStartDate.getDate() && dayValue < selectedEndDate.getDate()) {
day.classList.add('active-between');
}
});
} else {
// Reset selection if a third date is clicked
const allDays = document.querySelectorAll('.day');
allDays.forEach(day => {
day.classList.remove('active');
day.classList.remove('active-between');
});
selectedStartDate = null;
selectedEndDate = null;
startDateInput.value = '';
endDateInput.value = '';
// Start new selection
selectedStartDate = new Date(year, month, i);
startDateInput.value = `${year}-${String(month + 1).padStart(2, '0')}-${String(i).padStart(2, '0')}`;
day.classList.add('active');
}
});
day.addEventListener('mouseover', () => {
day.classList.add('hover');
});
day.addEventListener('mouseleave', () => {
day.classList.remove('hover');
});
calendarDays.appendChild(day);
}
}
// Function to open calendar
function openCalendar() {
calendar.style.display = 'block';
}
// Function to close calendar
function closeCalendar() {
calendar.style.display = 'none';
}
// Event listeners
openCalendarBtn.addEventListener('click', () => {
populateYears();
const today = new Date();
populateCalendar(today.getFullYear(), today.getMonth());
openCalendar();
});
closeCalendarBtn.addEventListener('click', closeCalendar);
yearSelect.addEventListener('change', () => {
populateCalendar(parseInt(yearSelect.value), parseInt(monthSelect.value));
});
monthSelect.addEventListener('change', () => {
populateCalendar(parseInt(yearSelect.value), parseInt(monthSelect.value));
});
</script>
</body>
</html>
3. Date Range Selection across Two Months-
Our third calendar enhances the previous functionality by enabling users to select date ranges spanning across two adjacent months. It presents a more flexible option for scenarios where events or tasks may extend beyond a single month boundary while maintaining the same year. This calendar is particularly suitable for planning purposes, such as project timelines or vacation scheduling. Check its live demonstration here

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calendar</title>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<style>
#home {
min-height: 95vh;
background-color: #090912;
background-image: url(dark.jpg);
background-size: cover;
}
.day {
width: 14.28%;
text-align: center;
padding: 3px 4px;
border: 1px solid #ccc;
border-radius: 15px;
margin: 2px;
background-color: purple;
color: white;
}
.dates {
width: 14.28%;
text-align: center;
padding: 3px 4px;
border: 1px solid #ccc;
border-radius: 15px;
margin: 2px;
background-color: rgb(255, 255, 255);
color: rgb(0, 0, 0);
cursor: pointer;
}
.dates:hover {
background-color: rgb(232, 232, 232);
}
.active-date {
background-color: #007bff;
color: #fff;
}
.active-date:hover {
background-color: #007bff;
color: #fff;
}
.yearinput {
border: none;
background-color: transparent;
text-align: center;
font-size: 20px;
font-weight: 700;
max-width: 100px;
outline: none;
}
.active-between{
background-color: rgb(232, 232, 232);
}
.startdateselected , .Enddateselected{
background-color: rgb(247, 193, 247);
padding: 4px 6px;
border: 1px solid rgb(190, 0, 190);
color: purple;
border-radius: 5px;
}
.startdateselected b , .Enddateselected b{
color: rgb(4, 0, 128);
}
@media (max-width: 540px) {
.day {
font-size: 10px;
}
.dates {
font-size: 14px;
}
.startdateselected , .Enddateselected{
font-size: 15px;
text-align: center;
}
.nav-btns{
font-size: 12px;
}
}
</style>
</head>
<body>
<ul class="nav justify-content-center py-2 bg-dark">
<li class="nav-item">
<a href="index.html"><button class="btn btn-light mx-1 nav-btns">Single Date</button></a>
</li>
<li class="nav-item">
<a href="calendar.html"><button class="btn btn-light mx-1 nav-btns">Date Range</button></a>
</li>
<li class="nav-item">
<a href="twomntthcalendar.html"><button class="btn btn-light mx-1 nav-btns">Month Range</button></a>
</li>
</ul>
<section id="home">
<h5 class="text-center pt-5 text-light">Date Range Selection across Two Months</h5>
<div class="container py-2 ">
<div class="card mx-auto" style="max-width: 700px;">
<div class="card-head">
<div class="row justify-content-center align-items-center">
<div class="col-12 d-flex justify-content-center align-items-center mt-2">
<i class="bi bi-arrow-left-circle-fill btn btn-dark mx-3" id="yearDecrement" onclick=" decrementYear()"></i>
<input type="text" name="" id="year" value="2024" class="yearinput" readonly>
<i class="bi bi-arrow-right-circle-fill btn btn-dark mx-3" id="yearIncrement" onclick="incrementYear()"></i>
</div>
</div>
</div>
<div class="card-body">
<div class="row justify-content-center">
<div class="col-md-6 border rounded py-3 px-1">
<div class="row justify-content-center">
<div class="col-10 d-flex justify-content-between align-items-center border rounded p-2 mx-1 my-2">
<i class="bi bi-arrow-left-circle-fill btn btn-outline-dark" id="monthDecrement1"></i>
<span id="month1"></span>
<i class="bi bi-arrow-right-circle-fill btn btn-outline-dark" id="monthIncrement1"></i>
</div>
<div class="col-12">
<div class="d-flex justify-content-between">
<span class="day">Sun</span>
<span class="day">Mon</span>
<span class="day">Tue</span>
<span class="day">Wed</span>
<span class="day">Thu</span>
<span class="day"> Fri </span>
<span class="day">Sat</span>
</div>
<div class="dates-wrap" id="datesWrap1"></div>
</div>
</div>
</div>
<div class="col-md-6 border rounded py-3 px-1">
<div class="row justify-content-center">
<div class="col-10 d-flex justify-content-between align-items-center border rounded p-2 mx-1 my-2">
<i class="bi bi-arrow-left-circle-fill btn btn-outline-dark" id="monthDecrement2"></i>
<span id="month2"></span>
<i class="bi bi-arrow-right-circle-fill btn btn-outline-dark" id="monthIncrement2"></i>
</div>
<div class="col-12">
<div class="d-flex justify-content-between">
<span class="day">Sun</span>
<span class="day">Mon</span>
<span class="day">Tue</span>
<span class="day">Wed</span>
<span class="day">Thu</span>
<span class="day"> Fri </span>
<span class="day">Sat</span>
</div>
<div class="dates-wrap" id="datesWrap2"></div>
</div>
</div>
</div>
<div class="col-12 mt-2 d-md-flex justify-content-between px-0">
<h5 class="mb-0 mt-1 startdateselected"><b>From</b> <span id="startdateselected">Not Selceted</span></h5>
<h5 class="mb-0 mt-1 Enddateselected"><b>To</b> <span id="Enddateselected">Not Selceted</span></h5>
</div>
</div>
</div>
</div>
</div>
</section>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script>
window.onload = function() {
var currentDate = new Date();
var currentYear = currentDate.getFullYear();
var currentMonthIndex = currentDate.getMonth();
document.getElementById('year').value = currentYear;
document.getElementById('month1').innerText = monthLong[currentMonthIndex];
var nextMonthIndex = (currentMonthIndex + 1) % 12;
document.getElementById('month2').innerText = monthLong[nextMonthIndex];
generateMonthDates(currentYear, currentMonthIndex, 'datesWrap1');
generateMonthDates(currentYear, nextMonthIndex, 'datesWrap2');
updateMonthIndices();
addDateEventListeners();
};
var newYear = parseInt(document.getElementById('year').value);
var monthLong = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
// Global variables to store current month indices
var month1Index = 0;
var month2Index = 1;
// Function to update month text
function updateMonthText(monthElement, index) {
monthElement.innerText = monthLong[index];
}
// Update global month indices
function updateMonthIndices() {
month1Index = monthLong.indexOf(document.getElementById("month1").innerText);
month2Index = monthLong.indexOf(document.getElementById("month2").innerText);
}
// Function to get the number of days in a month
function daysInMonth(year, month) {
return new Date(year, month + 1, 0).getDate();
}
// Function to get the first day of the month
function firstDayOfMonth(year, month) {
return new Date(year, month, 1).getDay();
}
// Function to generate dates for a month
function generateMonthDates(year, month, datesWrapId) {
const datesWrap = document.getElementById(datesWrapId);
datesWrap.innerHTML = ''; // Clear previous dates
const totalDays = daysInMonth(year, month);
const firstDay = firstDayOfMonth(year, month);
let currentDay = 1;
// Add dates for the month
for (let i = 0; i < 5; i++) {
const datesRow = document.createElement('div');
datesRow.className = 'd-flex datesrow' + (i + 1);
for (let j = 0; j < 7; j++) {
if (i === 0 && j < firstDay) {
// Add empty slot before the first day of the month
const emptySlot = document.createElement('span');
emptySlot.className = 'dates';
emptySlot.textContent = '0';
emptySlot.style.visibility = 'hidden'; // Hide spans with content 0
datesRow.appendChild(emptySlot);
} else if (currentDay <= totalDays) {
// Add dates for the current month
const dateElement = document.createElement('span');
dateElement.className = 'dates';
dateElement.textContent = currentDay;
datesRow.appendChild(dateElement);
currentDay++;
} else {
// Add hidden slot for the remaining days
const emptySlot = document.createElement('span');
emptySlot.className = 'dates';
emptySlot.style.visibility = 'hidden'; // Hide spans with content 0
emptySlot.textContent = '0';
datesRow.appendChild(emptySlot);
}
}
datesWrap.appendChild(datesRow);
}
}
// Update calendar when year or month changes
function updateCalendar() {
generateMonthDates(newYear, month1Index, 'datesWrap1');
generateMonthDates(newYear, month2Index, 'datesWrap2');
addDateEventListeners();
}
// Function to handle year increment
function incrementYear() {
newYear += 1;
document.getElementById('year').value = newYear;
updateCalendar();
}
// Function to handle year decrement
function decrementYear() {
newYear -= 1;
document.getElementById('year').value = newYear;
updateCalendar();
}
// Event listeners for increment buttons
document.getElementById("monthIncrement1").addEventListener("click", function() {
month1Index = (month1Index + 1) % 12;
updateMonthText(document.getElementById("month1"), month1Index);
updateMonthIndices();
updateCalendar();
});
document.getElementById("monthIncrement2").addEventListener("click", function() {
month2Index = (month2Index + 1) % 12;
updateMonthText(document.getElementById("month2"), month2Index);
updateMonthIndices();
updateCalendar();
});
// Event listeners for decrement buttons
document.getElementById("monthDecrement1").addEventListener("click", function() {
month1Index = (month1Index - 1 + 12) % 12;
updateMonthText(document.getElementById("month1"), month1Index);
updateMonthIndices();
updateCalendar();
});
document.getElementById("monthDecrement2").addEventListener("click", function() {
month2Index = (month2Index - 1 + 12) % 12;
updateMonthText(document.getElementById("month2"), month2Index);
updateMonthIndices();
updateCalendar();
});
// Define variables to store start and end dates
var startDateElement = null;
var endDateElement = null;
function handleDateClick(dateElement) {
var month1 = document.getElementById('month1').innerText;
var month2 = document.getElementById('month2').innerText;
if (dateElement.parentElement.parentElement.id === 'datesWrap1') {
if (startDateElement === null) {
startDateElement = {
element: dateElement,
date: dateElement.textContent,
month: month1,
year: document.getElementById('year').value
};
dateElement.classList.add('active-date');
removeActiveBetween();
} else if (endDateElement === null && dateElement !== startDateElement.element) {
endDateElement = {
element: dateElement,
date: dateElement.textContent,
month: month1,
year: document.getElementById('year').value
};
dateElement.classList.add('active-date');
markDatesBetween(startDateElement.element, endDateElement.element);
} else if (dateElement !== startDateElement.element && dateElement !== endDateElement.element) {
startDateElement.element.classList.remove('active-date');
endDateElement.element.classList.remove('active-date');
startDateElement = {
element: dateElement,
date: dateElement.textContent,
month: month1,
year: document.getElementById('year').value
};
endDateElement = null;
dateElement.classList.add('active-date');
removeActiveBetween();
} else {
startDateElement.element.classList.remove('active-date');
endDateElement.element.classList.remove('active-date');
startDateElement = {
element: dateElement,
date: dateElement.textContent,
month: month1,
year: document.getElementById('year').value
};
endDateElement = null;
dateElement.classList.add('active-date');
removeActiveBetween();
}
} else if (dateElement.parentElement.parentElement.id === 'datesWrap2') {
if (startDateElement === null) {
startDateElement = {
element: dateElement,
date: dateElement.textContent,
month: month2,
year: document.getElementById('year').value
};
dateElement.classList.add('active-date');
removeActiveBetween();
} else if (endDateElement === null && dateElement !== startDateElement.element) {
endDateElement = {
element: dateElement,
date: dateElement.textContent,
month: month2,
year: document.getElementById('year').value
};
dateElement.classList.add('active-date');
markDatesBetween(startDateElement.element, endDateElement.element);
} else if (dateElement !== startDateElement.element && dateElement !== endDateElement.element) {
startDateElement.element.classList.remove('active-date');
endDateElement.element.classList.remove('active-date');
startDateElement = {
element: dateElement,
date: dateElement.textContent,
month: month2,
year: document.getElementById('year').value
};
endDateElement = null;
dateElement.classList.add('active-date');
removeActiveBetween();
} else {
startDateElement.element.classList.remove('active-date');
endDateElement.element.classList.remove('active-date');
startDateElement = {
element: dateElement,
date: dateElement.textContent,
month: month2,
year: document.getElementById('year').value
};
endDateElement = null;
dateElement.classList.add('active-date');
removeActiveBetween();
}
}
if (startDateElement !== null && endDateElement !== null) {
document.getElementById('startdateselected').innerText = startDateElement.date + " " + startDateElement.month + " " + startDateElement.year;
document.getElementById('Enddateselected').innerText = endDateElement.date + " " + endDateElement.month + " " + endDateElement.year;
}
// Check if end date is smaller than start date and swap them if needed
if (startDateElement !== null && endDateElement !== null) {
const startMonthIndex = monthLong.indexOf(startDateElement.month);
const endMonthIndex = monthLong.indexOf(endDateElement.month);
const startDate = new Date(startDateElement.year, startMonthIndex, startDateElement.date);
const endDate = new Date(endDateElement.year, endMonthIndex, endDateElement.date);
if (endDate < startDate) {
const temp = startDateElement;
startDateElement = endDateElement;
endDateElement = temp;
startDateElement.element.classList.add('active-date');
endDateElement.element.classList.add('active-date');
// Update displayed dates
document.getElementById('startdateselected').innerText = startDateElement.date + " " + startDateElement.month + " " + startDateElement.year;
document.getElementById('Enddateselected').innerText = endDateElement.date + " " + endDateElement.month + " " + endDateElement.year;
}
}
if (startDateElement !== null && endDateElement !== null) {
markDatesBetween(startDateElement.element, endDateElement.element);
} else {
removeActiveBetween();
}
}
// Function to remove active-between class from all dates
function removeActiveBetween() {
const dates = document.querySelectorAll('.dates');
dates.forEach(date => date.classList.remove('active-between'));
}
// Function to mark dates between start and end date with .active-between class
function markDatesBetween(startDateElement, endDateElement) {
const dates = document.querySelectorAll('.dates');
const startIndex = Array.from(dates).indexOf(startDateElement);
const endIndex = Array.from(dates).indexOf(endDateElement);
for (let i = startIndex + 1; i < endIndex; i++) {
dates[i].classList.add('active-between');
}
}
// Function to add event listeners to date elements
function addDateEventListeners() {
document.querySelectorAll('.dates').forEach(function(dateElement) {
dateElement.addEventListener('click', function() {
handleDateClick(dateElement);
});
});
}
addDateEventListeners();
</script>
</body>
</html>
Interactive calendars play a crucial role in enhancing user experience and functionality in web applications. By leveraging HTML, CSS, JavaScript, and Bootstrap, we’ve demonstrated how to create three distinct types of calendars catering to different use cases. Whether it’s selecting a single date, defining date ranges within a month, or spanning across two months, these calendars provide users with intuitive tools for effective date management. Feel free to integrate and customize these calendars into your projects to streamline date-related interactions and improve overall user satisfaction.
Whether you need a custom-designed calendar, additional functionalities, or a comprehensive web development solution, VyomsCode is here to help. Get in touch with us to discuss your project requirements and let us transform your ideas into reality.
– Tripti