Flex布局最适合按“周”为单位组织日历:外层容器用flex-direction: column纵向堆叠周,每个.week内部用flex-direction: row横向排列7个.day;用flex: 1实现等宽且抗padding/border干扰;需JS计算首日偏移并插入空.day占位;小屏应切换为grid或重排DOM,而非强行flex-wrap。

Flex 布局本身不能直接生成日历数据,但它是目前实现日历 UI 结构最简洁、最可控的方式——关键在于用 display: flex 控制行列流式排列,而非强行用 float 或 inline-block。
用 flex-direction: column 搭建周维度结构
日历本质是「7列 × N行」的网格,但 Flex 更适合按「周」为单位组织:每行一个 <div class="week">,内部 7 个 <div class="day"> 横向排列。这时候必须设 flex-direction: row(默认值),而不是 column——否则每天会堆成一列。
常见错误是把整个日历容器设成 column,结果所有日期垂直叠在一起。正确做法:
- 外层容器(
.calendar)用display: flex+flex-direction: column管理「周」的纵向堆叠 - 每个
.week内部再用display: flex+flex-direction: row排 7 天 - 避免嵌套多层 flex 容器导致
flex-basis计算混乱,尤其在 IE 中容易塌陷
用 flex: 1 实现等宽日期格子
7 列等宽不能靠 width: 14.2857% 硬写——小数精度和 border/padding 会让最后一列换行。用 Flex 的伸缩性更稳:
立即学习“前端免费学习笔记(深入)”;
- 给每个
.day设flex: 1(即flex-grow: 1; flex-shrink: 1; flex-basis: 0) - 这样它们会均分父容器(
.week)剩余空间,无视 padding 和 border 影响 - 如果某天需要突出显示(如今天),可单独加
flex: none并设固定宽高,避免挤压其他格子
处理首日偏移与月末空白格
Flex 不自动填满整行,所以必须手动补足开头空格(当月 1 号不是周一)和结尾空格(当月最后一天不是周日)。不能依赖 justify-content: space-between——它只调整已有子元素间距,不会插入占位节点。
实操建议:
- JavaScript 计算当月 1 号是星期几(
new Date(year, month, 1).getDay()),生成前offset个空<div class="day empty"></div> - 补空格时仍保留
flex: 1,只是内容为空、背景透明,确保宽度一致 - 别用
visibility: hidden或display: none——前者占位但看不见,后者破坏 flex 流,导致列数错乱
响应式断点下改用 flex-wrap: wrap?不推荐
有人想在小屏上让 7 列变单列滚动,尝试给 .week 加 flex-wrap: wrap 并设 flex-basis: 100%。这会导致两个问题:
- 每格宽度变成 100%,但高度不受控,日期数字可能被拉长或截断
- 原本按周组织的 DOM 结构被打破,语义混乱,屏幕阅读器无法理解日历逻辑
- 真正可行的是媒体查询切换整个布局:小屏改用
grid(更适配二维场景),或保持 flex 但把.week改成单列,同时重排 DOM 顺序(需 JS 介入)
Flex 做日历的核心约束很明确:它擅长一维布局,所以必须把「周」作为不可拆分的单元来设计;任何试图让它模拟二维 grid 的取巧方案,最终都会在边界情况(跨月、闰年、不同 locale 星期起始日)里暴露缺陷。


















