Bootstrap 5 日历网格用 row 包 7 个 col-1 实现等宽星期头,日期格子补空至42个(6×7)防塌陷;签到按钮仅对当天及之前日期启用,需服务端传 today 字符串比对;iPhone X+ 底部安全区用 padding-bottom: env(safe-area-inset-bottom) 配合 viewport-fit=cover;日历按钮须放大热区并禁用文字选择。

Bootstrap 5 的日历网格怎么用 col 和 row 实现七列星期头
Bootstrap 本身不带日历组件,得自己搭结构。核心是用 row 包住 7 个 col-1(或 col-auto)做星期栏,再用多个同结构的 row 拼日期格子。注意别用 col-md-* 这类断点类——手机端必须始终是 7 列等宽,否则星期错位。
常见错误是直接套用 table,结果在 iOS Safari 上缩放异常;也有人用 flex-wrap 手动换行,但容易因日期数不是 7 的倍数(如 31 天从周三开始)导致最后一行塌陷。稳妥做法是补空格日期( 或空 div),总数凑够 42(6 行 × 7 列)。
- 星期头文字用
text-center small text-muted控制字号和对齐 - 每个日期格子加
aspect-ratio: 1/1(现代浏览器)或固定padding-top: 100%+position: relative做正方形 - 避免给格子设
height,否则在小屏上文字会被截断
怎么让签到按钮只在当天和之前日期生效
签到逻辑不能只靠样式隐藏,得结合日期判断动态加 class。用 JavaScript 获取当前日期(new Date()),遍历所有日期格子的 data-date 属性(格式建议 YYYY-MM-DD),比对后给过期/当天格子加 active 或 disabled 类,未来日期加 disabled 并移除点击事件。
容易踩的坑是时区问题:用户手机系统时区和服务器时间不一致时,new Date().toDateString() 可能比服务端返回的“今日”早或晚一天。推荐统一用服务端下发的 today 字符串做比对,前端只负责渲染。
- HTML 中每个日期格子写成:
<div class="date-cell" data-date="2024-06-15">15</div> - 禁用状态用
opacity: 0.4; pointer-events: none;,比disabled属性更可靠(div不支持disabled) - 签到成功后,立刻给对应格子加
checkedclass,并更新本地缓存(localStorage),避免刷新丢失状态
怎么适配 iPhone X 及以上机型的底部安全区
如果日历区域紧贴页面底部,iPhone X+ 会把最后几行盖在 Home Indicator 下面。不能只靠 padding-bottom: env(safe-area-inset-bottom)——这会让整个日历下移,留白过大。正确做法是给日历容器加 padding-bottom: env(safe-area-inset-bottom),同时用 body { padding-bottom: env(safe-area-inset-bottom) } 抬高整个页面底边,再用 min-height: 100vh 防止内容过短时安全区失效。
另外,iOS Safari 对 position: fixed 元素在滚动时有重绘延迟,如果签到按钮是吸底浮动的,别用 fixed,改用 position: sticky; bottom: 0 + 父容器 overflow-y: auto 更稳。
- 务必在
里加 viewport:<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> - 测试时真机连 Safari 开发者工具,勾选 “Show rulers”,看底部是否被遮挡
- 安卓机不用管
env(safe-area-inset-bottom),它会自动降级为 0
为什么用 btn-sm 会导致点击热区太小
Bootstrap 的 btn-sm 在手机上默认 padding: 0.25rem 0.5rem,手指点击极易误触相邻格子。这不是设计缺陷,而是它本就面向桌面端小工具按钮。日历里的签到操作需要明确反馈,必须放大热区。
解决方案不是全局覆盖 .btn-sm,而是在日历专用 class 下重置,比如给格子内按钮加 calendar-btn 类,然后写:.calendar-btn { padding: 0.75rem; font-size: 0.9rem; }。这样既不影响其他地方的 btn-sm,又保证手指可精准点中。
- Android 用户习惯长按触发,所以记得加
user-select: none防止误选文字 - 点击反馈用
:active { transform: scale(0.95); }比改背景色更直观 - 如果用图标代替数字(如 ✔️),确保图标字体大小 ≥ 18px,否则在 2x 屏上模糊
firstDayIndex = new Date(year, month, 1).getDay(),然后补 firstDayIndex 个空格,别信网上抄来的“固定补 3 个”。


















