使用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"><</button> <span id="current-month-text"></span> <button id="next-month">></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
相关产品推荐
相关产品推荐

