日历网格应使用repeat(auto-fit, minmax(40px, 1fr)))实现响应式列数,用grid-column-start配合星期偏移定位首日,grid-auto-rows设为minmax(60px, auto)防抖动,状态样式仅通过class控制不增删元素。

日历网格结构怎么用 grid-template-columns 动态适配屏幕?
固定列数会破坏响应性,比如在手机上显示 7 列(周一到周日)就必然横向滚动。真正可行的做法是让 grid-template-columns 配合 repeat() 和 minmax() 自适应:
- 在桌面端用 repeat(7, 1fr) 均分宽度
- 在移动端改用 repeat(auto-fit, minmax(40px, 1fr))),让浏览器自动计算能放几列,同时保证最小宽度不致内容挤压
- 必须搭配 grid-auto-flow: column 或显式设置 grid-template-rows,否则日期单元格可能错行
注意:auto-fit 和 auto-fill 行为不同——auto-fit 会收缩空轨道,auto-fill 保留空位,日历必须用 auto-fit 避免出现空白列。
如何用 grid-column 跳过首行的空白日期单元格?
每月 1 号不一定从周一开头,需要在日历顶部预留空单元格占位。不能靠 JS 插入空 <div>,而应利用 Grid 的定位能力: <p>
- 先算出当月 1 日是星期几(0=周日,1=周一……),得出需跳过的列数 <code>offset
- 给第一个日期单元格设 grid-column: span 1 / -1 不起作用,正确做法是用 grid-column-start:
.day-1 { grid-column-start: 2; } /* 如果 1 号是周二,就从第 2 列开始 */
- 更稳妥的是统一用 grid-column: <code>start / end,例如 grid-column: 3 / 4 表示放在第 3 列
容易踩坑:CSS 里列号从 1 开始计数,但 JS 的 getDay() 返回 0(周日)→ 6(周六),换算时别漏掉 +1 或取模调整。
为什么 grid-auto-rows 设成固定高度会导致月份切换时布局抖动?
如果直接写 grid-auto-rows: 60px,遇到 5 行或 6 行的月份(如 2023 年 10 月有 6 行),最后一行会被强行撑高或截断。
- 正确做法是设为 grid-auto-rows: minmax(60px, auto),既保底高度,又允许内容撑开
- 若需所有行等高,用 grid-auto-rows: 1fr + 显式定义 grid-template-rows,但必须提前知道最大行数(通常是 6)
- 配合 grid-template-rows: repeat(6, minmax(60px, auto)) 最稳,避免动态行数带来的重排
注意:一旦用了 grid-template-rows,就必须确保总行数 ≥ 实际所需(比如设 6 行,哪怕某月只用 5 行),否则多余日期会溢出容器。
如何让「今天」和「本月外日期」在视觉上区分又不破坏 Grid 结构?
不能靠增删元素来标记状态,否则 Grid 轨道数会变,引发布局偏移。应该复用同一套 DOM,仅靠 class 控制样式:
- 给每个日期单元格加类名,如 is-today、is-other-month
- 用 opacity: 0.5 或 color: #ccc 处理非本月日期,但别用 display: none —— 它会让 Grid 计算轨道时忽略该格子,导致后续日期错位
- 「今天」高亮可用 background-color + border-radius,但注意不要设 padding 过大,否则影响 minmax() 的尺寸收敛
关键点:所有状态样式都必须基于现有格子,不能改变网格项数量或顺序。否则响应式切换时,JS 重新渲染或 CSS 重排极易出错。











