Creating Interactive Calendars with HTML, CSS, JS, and Bootstrap

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.

  1. 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
Document

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">&nbsp;Fri&nbsp;</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">&nbsp;Fri&nbsp;</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

Leave a Reply

Your email address will not be published. Required fields are marked *