Calendar (implemented in HTML, CSS and JavaScript)

I wrote a calendar and only used (HTML, CSS and JavaScript) to implement it. Implement a calendar in the most native way.

The calendar effect is as follows:

1.HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>My Calendar</title>
  <link rel="stylesheet" href="index.css">
</head>
<body>
  <!-- Calendar container -->
  <div class="calendar">
    <!-- Calendar header -->
    <div id="head">
      <!-- Current time -->
      <div class="currentTime"></div>
      <!-- Year area -->
      <div class="yearArea">
        <button> & amp;lt;</button>
        <select></select>
        <button> &gt;</button>
      </div>
      <!-- Month area -->
      <div class="monthArea">
        <button> & amp;lt;</button>
        <select></select>
        <button> &gt;</button>
      </div>
      <!--Today's area -->
      <div class="todayArea">
        <button>Today</button>
      </div>
    </div>
    <!-- Calendar middle -->
    <div id="body">
      <!-- Weekday area -->
      <div class="weekArea">
        <div>一</div>
        <div>二</div>
        <div>three</div>
        <div>four</div>
        <div>五</div>
        <div style="color: red;">Six</div>
        <div style="color: red;">Day</div>
      </div>
      <!--Date area -->
      <div class="dateArea"></div>
    </div>
    <!-- Bottom of calendar -->
    <div id="foot">
      <div class="ring">
        <button>Previous song</button>
        <video src="music/01.mp3" width="350px" height="40px" controls autoplay></video>
        <button>Next song</button>
      </div>
    </div>
  </div>
  <script src="index.js"></script>
</body>
</html>

2. CSS

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

/*------------------------------------------------ Calendar container------------------------------------------------ */
.calendar {
  width: 100%;
  height: 100%;
  min-width: 830px;
  display: flex;
  flex-direction: column;
}

/*------------------------------------------------ Calendar header------------------------------------------------- - */
.calendar>#head {
  height: 120px;
  font-size: 24px;
  background-color: #87CEEB;
  display: flex;
  justify-content: center;
  align-items: center;
}
/* Current time, year area, month area */
.calendar>#head>.currentTime,
.calendar>#head>.yearArea,
.calendar>#head>.monthArea {
  display: flex;
  margin-right: 12px;
}
.calendar>#head>.currentTime {
  color: #ff6319;
}
/* Previous year, next year, last month, next month, today */
.calendar>#head>.yearArea button:nth-of-type(1),
.calendar>#head>.yearArea button:nth-of-type(2),
.calendar>#head>.monthArea button:nth-of-type(1),
.calendar>#head>.monthArea button:nth-of-type(2),
.calendar>#head>.todayArea button {
  min-width: 40px;
  height: 50px;
  font-size: 1em;
}
/* Year selection box, month selection box */
.calendar>#head>.yearArea select,
.calendar>#head>.monthArea select {
  min-width: 100px;
  height: 50px;
  font-size: 1em;
  text-align: center;
  outline: none;
}

/*------------------------------------------------ Calendar Central------------------------------------------------ */
.calendar>#body {
  flex-grow: 1;
  background-color: #d0d2d3;
  padding: 0 80px 50px;
}
/* Weekday area */
.calendar>#body>.weekArea {
  display: grid;
  grid-template-columns: repeat(7,1fr);
  gap: 20px;
}
.calendar>#body>.weekArea div {
  text-align: center;
  font-size: 30px;
  height: 80px;
  line-height: 80px;
}
/* date area */
.calendar>#body>.dateArea {
  display: grid;
  grid-template-columns: repeat(7,1fr);
  grid-template-rows: repeat(6,1fr);
  gap: 20px;
  height: calc(100% - 80px);
}
.calendar>#body>.dateArea div {
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 12px;
  font-size: 36px;
  transition: transform 0.5s, box-shadow 0.5s;
}
.calendar>#body>.dateArea div:hover {
  transform: translateY(-10px);
  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.5);
}

/*------------------------------------------------ Calendar bottom------------------------------------------------ */
.calendar>#foot {
  height: 100px;
  min-height: 50px;
  background-color: #8a7967;
  display: flex;
  justify-content: center;
}
.calendar>#foot>.ring {
  width: 500px;
  display: flex;
  justify-content: space-evenly;
  align-items: center;
}
.calendar>#foot>.ring button {
  height: 40px;
}

3. JavaScript

//current time dom
let currentTime = document.getElementsByClassName('currentTime')[0];
// year area dom
let yearArea = document.getElementsByClassName('yearArea')[0];
let lastYearBtn = yearArea.querySelectorAll('button')[0]; //Previous year button
let yearSelect = yearArea.querySelector('select'); //Year drop-down box
let nextYearBtn = yearArea.querySelectorAll('button')[1]; //Next year button
//Month area dom
let monthArea = document.getElementsByClassName('monthArea')[0];
let lastMonthBtn = monthArea.querySelectorAll('button')[0]; //Last month button
let monthSelect = monthArea.querySelector('select'); //Month drop-down box
let nextMonthBtn = monthArea.querySelectorAll('button')[1]; //Next month button
// Today's area dom
let todayBtn = document.querySelector(".todayArea"); //Today button
//Date area dom
let dateArea = document.getElementsByClassName('dateArea')[0];
//Music area dom
let ring = document.getElementsByClassName('ring')[0];
let lastOneBtn = ring.querySelectorAll('button')[0]; //Previous song button
let videoPlayer = ring.querySelector('video'); //video element
let nextOneBtn = ring.querySelectorAll('button')[1]; //Next song button


//Create a list of years
for(let i=0;i<200;i + + ) {
  let y = 1900;
  let option = document.createElement('option');
  option.value = y + i;
  option.innerHTML = y + i + 'year';
  yearSelect.append(option);
}
//Create a list of months
for(let i=1;i<=12;i + + ) {
  let option = document.createElement('option');
  option.value = i;
  option.innerHTML = i + 'month';
  monthSelect.append(option);
}


//Bind click event (previous year button)
lastYearBtn.addEventListener('click',function() {
  clickYear(1);
})
//Bind click event (next year button)
nextYearBtn.addEventListener('click',function() {
  clickYear(2);
})
// Bind click event (previous month button)
lastMonthBtn.addEventListener('click',function() {
  clickMonth(1);
})
//Bind click event (next month button)
nextMonthBtn.addEventListener('click',function() {
  clickMonth(2);
})
//Bind change event (year drop-down box)
yearSelect.addEventListener('change',function(e) {
  changeYear(e.target.value);
})
//Bind change event (month drop-down box)
monthSelect.addEventListener('change',function(e) {
  changeMonth(e.target.value);
})
//Bind click event (today button)
todayBtn.addEventListener('click',function() {
  init();
})
//Bind click event (previous song button)
lastOneBtn.addEventListener('click',function() {
  let musicNo = videoPlayer.src.slice(-6,-4);
  if(musicNo<2) {
    alert('It’s already the first song~');
  } else {
    videoPlayer.src = videoPlayer.src.replace(musicNo,'0' + (musicNo-1));
  }
})
//Bind click event (next song button)
nextOneBtn.addEventListener('click',function() {
  let musicNo = videoPlayer.src.slice(-6,-4);
  if(musicNo>5) {
    alert('It’s the last song~');
  } else {
    videoPlayer.src = videoPlayer.src.replace(musicNo,'0' + (musicNo*1 + 1));
  }
})


/********************************** Click the previous and next year button************ ***************************/
function clickYear(type) {
  let y,m;
  for(let it of yearSelect.querySelectorAll('option')) {
    if(it.selected) {
      if(type == 1) {
        y = it.value > 1900 ? it.value - 1 : it.value;
      } else {
        y = it.value < 2099 ? it.value*1 + 1 : it.value;
      }
    }
  }
  for(let it of monthSelect.querySelectorAll('option')) {
    if(it.selected) {
      m = it.value;
    }
  }
  init(`${y}-${m}`);
}
/********************************** Click the up and down month buttons************ ***************************/
function clickMonth(type) {
  let y,m;
  for(let it of yearSelect.querySelectorAll('option')) {
    if(it.selected) {
      y = it.value;
    }
  }
  for(let it of monthSelect.querySelectorAll('option')) {
    if(it.selected) {
      if(type == 1) {
        m = it.value > 1 ? it.value - 1 : it.value;
      } else {
        m = it.value < 12 ? it.value*1 + 1 : it.value;
      }
    }
  }
  init(`${y}-${m}`);
}
/************************************ Change the year trigger********** ******************************/
function changeYear(val) {
  let m;
  for(let it of monthSelect.querySelectorAll('option')) {
    if(it.selected) {
      m = it.value;
    }
  }
  init(`${val}-${m}`);
}
/************************************ Change the month trigger************ ******************************/
function changeMonth(val) {
  let y;
  for(let it of yearSelect.querySelectorAll('option')) {
    if(it.selected) {
      y = it.value;
    }
  }
  init(`${y}-${val}`);
}
/************************************ Initialization data (year, month, date, etc.) *** *********************************/
function init(appoint) {
  let t = appoint===undefined ? new Date() : new Date(appoint);
  let year = t.getFullYear();
  let month = t.getMonth() + 1;
  //Default value of year selection box (current year)
  for(let it of yearSelect.querySelectorAll('option')) {
    if(it.value==year) {
      it.selected = "selected";
    }
  }
  //Default value of month selection box (current month)
  for(let it of monthSelect.querySelectorAll('option')) {
    if(it.value==month) {
      it.selected = "selected";
    }
  }
  //How many days are there in the current month?
  let currentMonthDays;
  if(month==1||month==3||month==5||month==7||month==8||month==10||month==12) {
    currentMonthDays = 31;
  } else if(month==4||month==6||month==9||month==11) {
    currentMonthDays = 30;
  } else {
    if((year % 4 == 0 & amp; & amp; year % 100 != 0) || year % 400 == 0) {
      currentMonthDays = 29;//February in leap year
    } else {
      currentMonthDays = 28;//February in ordinary years
    }
  }
  //Create date list
  dateArea.innerHTML = "";
  for(let i=0;i<42;i + + ) {
    dateArea.append(document.createElement('div'));
  }
  // What day of the week is the 1st of the current month (then start from the day of the first week and arrange the 1st, 2nd, 3rd...)
  let weekIndex = new Date(`${year}-${month}-01`).getDay(); // The subscript of the day of the week
  let dateArr = dateArea.children; // All grids of date (6*7)
  let dayNum = 1; // The specific date number that starts to increase from the 1st of the month (1-31)
  //Add specific content to the date of the current month
  for(let i=0;i<dateArr.length;i + + ) {
    if(weekIndex>0) {
      if(i>=weekIndex-1 & amp; & amp; currentMonthDays>0) {
        inFn(i);
      }
    } else {
      if(i>=6 & amp; & amp; currentMonthDays>0) {
        inFn(i);
      }
    }
  }
  function inFn(i) {
    let t = new Date();
    let ymStr = t.getFullYear() + "-" + (t.getMonth() + 1);
    let today = t.getDate(); //Today’s date
    dateArr[i].style.backgroundColor = today==dayNum & amp; & amp; (year + "-" + month==ymStr) ? "pink" : "#56a0d3";
    dateArr[i].value = dayNum;
    dateArr[i].innerHTML = dayNum;
    dayNum + + ;
    currentMonthDays--;
  }
  //Remove the grid shadow effect without date content
  for(let it of dateArr) {
    if(!it.value) {
      it.style.boxShadow = "none";
    }
  }
}
/********************************** Get the current time************ ******************************/
function getCurrentTime() {
  let t = new Date();
  let year = t.getFullYear();
  let month = t.getMonth() + 1 > 9 ? t.getMonth() + 1 : "0" + (t.getMonth() + 1);
  let date = t.getDate() > 9 ? t.getDate() : "0" + t.getDate();
  let hour = t.getHours() > 9 ? t.getHours() : "0" + t.getHours();
  let minute = t.getMinutes() > 9 ? t.getMinutes() : "0" + t.getMinutes();
  let second = t.getSeconds() > 9 ? t.getSeconds() : "0" + t.getSeconds();
  let weeks = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
  let week = weeks[t.getDay()];
  return year + "year" + month + "month" + date + "day" + hour + ":" + minute + ":" + second + " " + week;
}


// ------------execute program------------
init();
currentTime.innerHTML = getCurrentTime();
setInterval(() => {
  currentTime.innerHTML = getCurrentTime();
}, 1000);