用 grid-template-columns: repeat(7, 1fr) 和 grid-auto-rows: minmax(40px, auto) 可构建日历网格,但需解决首日对齐(用 grid-column-start 计算偏移)、跨月语义、等高容错(Safari 中改用 minmax(40px, max-content) 或 flex 内部处理)及小屏交互(切 column 流时同步改列数、包裹星期标题、确保触摸热区≥44px、为日期元素加 tabindex="0" 和 :focus-visible)。

直接用 grid-template-columns: repeat(7, 1fr) + grid-auto-rows: minmax(40px, auto) 就能撑出可用的日历网格,但“自适应”真正卡点不在列数,而在首日对齐、跨月语义、等高容错和小屏交互——这些不处理,Grid 会渲染出视觉正确但语义断裂、键盘不可达、Safari 下塌陷的假日历。
grid-template-columns: repeat(7, 1fr) 为什么不能写成百分比或固定像素
用 1fr 是因为浏览器对子像素渲染的累积误差会让 14.2857% 在某些分辨率下最后一列换行;固定像素(如 120px)在窄屏上溢出、宽屏上留白,且无法响应字体缩放。而 1fr 由 Grid 引擎动态均分容器剩余空间,无此问题。别碰 minmax(120px, 1fr) 这类混合写法——它在旧版 Safari 中会退化为固定宽,导致列错位。
首日偏移必须用 grid-column-start,而不是插入空 div
常见错误是生成 0–6 个 <div class="empty"></div> 占位,这带来三个问题:DOM 节点冗余、aria-hidden="true" 必须手动加、键盘 Tab 会停在空格上干扰导航。
- 正确做法:算出当月 1 号星期几,
date.getDay()返回 0(周日)到 6(周六),若按周一为周首,则偏移量 =date.getDay() === 0 ? 6 : date.getDay() - 1 - 给第一个日期元素加
grid-column-start: calc(<code>offset + 1)(注意列号从 1 开始) - 后续所有日期按 DOM 顺序自然填充,Grid 自动跳过空白列
grid-auto-rows: minmax(40px, auto) 在 Safari 中失效怎么办
Safari 对 minmax(min, auto) 的 auto 支持不稳定,常表现为行高塌陷成文字高度,尤其在 iOS 16+ 真机上。这不是 bug,而是 Safari 实现中 auto 未参与弹性计算。
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
立即学习“前端免费学习笔记(深入)”;
- 降级方案:改用
minmax(40px, max-content),但注意 Chrome 90 以下不支持max-content - 更稳妥做法:加一层
display: flex; flex-direction: column; height: 100%到每个日期单元格内部,再设min-height: 40px - 绝对不要设
height: 40px—— 会截断多行事件文本,且破坏可访问性字体缩放
小屏下 grid-auto-flow: column 不等于简单堆叠
在 @media (max-width: 480px) 下切 grid-auto-flow: column 是对的,但仅改这一条不够:
- 必须同步把
grid-template-columns改为1fr,否则仍保留 7 列导致内容横向溢出 - 星期标题需单独包裹,用
display: contents或独立 Grid 容器,避免它们也被column流打乱顺序 - 触摸热区至少
44px高,padding不够时用min-height: 44px补,别依赖transform: scale()—— 它不放大点击区域
最易被忽略的是键盘焦点流:Grid 本身不定义 Tab 顺序,tabindex="0" 得加在每个可交互日期上,且要配合 :focus-visible 样式;否则盲人用户用方向键切换时,会跳过整行或卡在空格上。

















