You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用HTML/CSS/JS实现预订日历无需硬编码的更简便方法

完全不需要硬编码每个日期按钮,用JS结合Date对象动态生成日期格是最简便的实现方式,开发量很小。下面是具体实现思路和可直接复用的代码:

实现思路

  • 用JS内置Date对象自动计算当前展示月份的总天数、首日星期数,不用手动数日期
  • 所有日期元素通过循环动态生成,自动绑定选择事件,切换月份时重新渲染即可
  • 如果不需要自定义日历样式,直接用HTML原生日期输入框是成本最低的方案

可修改的完整代码示例

HTML部分

<div id="text">
  <input type="text" id="input-id" readonly>
</div>
<div id="calendar-wrap" style="visibility: hidden;">
  <!-- 日历头部:切换按钮+年月显示 -->
  <div class="cal-header">
    <button id="prev-month">&lt;</button>
    <span id="current-month-text"></span>
    <button id="next-month">&gt;</button>
  </div>
  <!-- 星期标题 -->
  <div class="week-header">
    <span>日</span><span>一</span><span>二</span><span>三</span><span>四</span><span>五</span><span>六</span>
  </div>
  <!-- 日期容器,动态生成内容 -->
  <div id="date-grid"></div>
</div>

CSS部分

#input-id{
  margin-left: 150px;
  padding: 4px 8px;
}
#calendar-wrap {
  width: 280px;
  border: 1px solid #eee;
  padding: 10px;
  margin-left: 150px;
}
.cal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}
.week-header, #date-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  text-align: center;
}
.week-header span {
  font-weight: bold;
  font-size: 12px;
  padding: 4px 0;
}
.date-item {
  padding: 6px 0;
  border: none;
  background: none;
  cursor: pointer;
  border-radius: 4px;
}
.date-item:hover {
  background: #f0f0f0;
}

JS部分

let calendarVisible = false;
const calendarWrap = document.querySelector("#calendar-wrap");
const inputEl = document.getElementById("input-id");
const prevBtn = document.getElementById("prev-month");
const nextBtn = document.getElementById("next-month");
const monthText = document.getElementById("current-month-text");
const dateGrid = document.getElementById("date-grid");

// 当前展示的年月,默认是当前时间
let currentYear = new Date().getFullYear();
let currentMonth = new Date().getMonth();

// 输入框点击切换日历显隐
inputEl.addEventListener("click", function() {
  calendarVisible = toggleCalendar(calendarVisible);
  if(calendarVisible) renderCalendar();
});

// 切换日历显隐逻辑
function toggleCalendar(status) {
  if (!status) {
    calendarWrap.style.visibility = "visible";
    inputEl.value = "";
    return true;
  } else {
    calendarWrap.style.visibility = "hidden";
    return false;
  }
}

// 渲染日历核心逻辑
function renderCalendar() {
  // 显示当前年月
  monthText.innerText = `${currentYear}年${currentMonth + 1}月`;
  // 清空之前的日期
  dateGrid.innerHTML = "";
  // 计算当月第一天是周几,当月总天数
  const firstDay = new Date(currentYear, currentMonth, 1).getDay();
  const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();

  // 补全当月第一天之前的空白格
  for(let i = 0; i < firstDay; i++) {
    const empty = document.createElement("span");
    dateGrid.appendChild(empty);
  }

  // 生成当月日期按钮
  for(let day = 1; day <= daysInMonth; day++) {
    const dateBtn = document.createElement("button");
    dateBtn.className = "date-item";
    dateBtn.innerText = day;
    // 绑定选择日期事件
    dateBtn.addEventListener("click", () => {
      // 格式化日期,补零
      const formatDay = String(day).padStart(2, '0');
      const formatMonth = String(currentMonth + 1).padStart(2, '0');
      inputEl.value = `${currentYear}-${formatMonth}-${formatDay}`;
      // 选完关闭日历
      toggleCalendar(true);
    })
    dateGrid.appendChild(dateBtn);
  }
}

// 切换月份逻辑
prevBtn.addEventListener("click", () => {
  currentMonth--;
  if(currentMonth < 0) {
    currentMonth = 11;
    currentYear--;
  }
  renderCalendar();
})
nextBtn.addEventListener("click", () => {
  currentMonth++;
  if(currentMonth > 11) {
    currentMonth = 0;
    currentYear++;
  }
  renderCalendar();
})

更轻量化的替代方案

如果不需要自定义日历的样式,直接把输入框的type改为date即可,浏览器会自带原生日历控件,支持月份切换、日期选择,完全不用写额外的JS逻辑,代码仅需修改一行:

<input type="date" id ="input-id">

内容的提问来源于stack exchange,提问作者Costas Mav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 06:57:03