<!-- ローディング画面 -->
<div class="loading --js"></div>
<!-- メイン画面 -->
<main class="main --js --hidden">
  <div class="calendar">
    <button type="button" class="calendar__prev --js">前月</button>
    <div class="calendar__container --js">
      <p class="calendar__date">XXXX年XX月</p>
    </div>
    <button type="button" class="calendar__next --js">翌月</button>
  </div>
</main>
/* リセット */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* 共通 */
.--hidden {
  display: none;
}

/* ローディングブロック */
.loading {
  width: 48px;
  height: 48px;
  background-color: #ededed;
  border-radius: 50%;
  margin: calc(50vh - 24px) auto;
  animation: 1s 0s loading ease-in-out infinite;
}

@keyframes loading {
  0% {
    width: 48px;
    height: 48px;
    opacity: 0.8;
  }
  100% {
    width: 2px;
    height: 2px;
    opacity: 0;
    margin: calc(50vh - 1px) auto;
  }
}

/* メインブロック */
.main {
  width: 100%;
}

.calendar {
  width: 300px;
  margin: calc(50vh - 1.5em) auto;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
}
.calendar__container {
  width: 150px;
  text-align: center;
  overflow-x: hidden;
}

.calendar__next,
.calendar__prev {
  height: 3em;
}

/* 前月に移動するときに左へフェードアウト+右からフェードイン */
.calendar__date__prev {
  animation: 0.3s 0s fade_out_in_r ease forwards;
}
/* 翌月に移動するときに右へフェードアウト+左からフェードイン */
.calendar__date__next {
  animation: 0.3s 0s fade_out_in_l ease forwards;
}

/* 左へフェードアウト+右からフェードイン */
@keyframes fade_out_in_l {
  0% {
    transform: translateX(0px);
  }
  50% {
    transform: translateX(-150px);
  }
  51% {
    transform: translateX(150px);
  }
  100% {
    transform: translateX(0px);
  }
}

/* 右へフェードアウト+左からフェードイン */
@keyframes fade_out_in_r {
  0% {
    transform: translateX(0px);
  }
  50% {
    transform: translateX(150px);
  }
  51% {
    transform: translateX(-150px);
  }
  100% {
    transform: translateX(0px);
  }
}
"use strict";
//
// クラス----------------------------------------------
//
class Calendar {
  constructor() {
    let today = new Date();
    this.year = today.getFullYear();
    this.month = `0${today.getMonth() + 1}`.slice(-2);
  }

  prevMonth() {
    if (Number(this.month) === 1) {
      this.month = `12`;
      this.year += -1;
    } else {
      this.month = `0${Number(this.month) - 1}`.slice(-2);
    }
  }

  nextMonth() {
    if (Number(this.month) === 12) {
      this.month = `01`;
      this.year += 1;
    } else {
      this.month = `0${Number(this.month) + 1}`.slice(-2);
    }
  }
}
// ---------------------------------------------------

//
// 初回ロード-----------------------------------------
//
window.onload = init();

function init() {
  const calendar = new Calendar();
  // デフォルトで当月の年月を表示
  displayCal(calendar);
  // ローディング画面⇒メイン画面
  displayMain();

  // クリックイベント:前月を表示
  document
    .querySelector(".calendar__prev.--js")
    .addEventListener("click", function () {
      calendar.prevMonth();
      displayCalPrev(calendar);
    });
  // クリックイベント:翌月を表示
  document
    .querySelector(".calendar__next.--js")
    .addEventListener("click", () => {
      calendar.nextMonth();
      displayCalNext(calendar);
    });
}
// -------------------------------------------------------

//
// 関数---------------------------------------------------
//

// 関数:当月を表示させる
function displayCal(cal) {
  document.querySelector(
    ".calendar__container.--js"
  ).innerHTML = `<p class="calendar__date">${cal.year}年${cal.month}月</p>`;
}

// 関数:ローディング画面⇒メイン画面
function displayMain() {
  document.querySelector(".loading.--js").classList.add("--hidden");
  document.querySelector(".main.--js").classList.remove("--hidden");
}

// 関数:前月を表示させる
function displayCalPrev(cal) {
  document.querySelector(
    ".calendar__container.--js"
  ).innerHTML = `<p class="calendar__date__prev">${cal.year}年${cal.month}月</p>`;
}

// 翌月を表示させる
function displayCalNext(cal) {
  document.querySelector(
    ".calendar__container.--js"
  ).innerHTML = `<p class="calendar__date__next">${cal.year}年${cal.month}月</p>`;
}
// -----------------------------------------------------------

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.