用 + CSS Grid 实现轻量可控甘特图:横轴为时间(列)、纵轴为任务(行),用 grid-column 控制起止,列宽用 repeat(var(--days), 1fr) 均分,任务行高设为 minmax(32px, auto),起始列需按日期偏移动态计算,悬停提示用绝对定位浮层,IE11 降级为 Flex 单行布局。

用 + CSS Grid 做可读甘特图,别碰 SVG纯 HTML 实现甘特图, 会卡死语义、 难维护宽度和响应式,真正轻量可控的是 CSS Grid。核心思路是:横轴为时间(列),纵轴为任务(行),每个 表示一个时间块,用 grid-column 控制起止列。常见错误是把天数硬编码成固定像素宽——一旦缩放或换分辨率,进度条就错位。正确做法是让列宽由容器自动均分,再用 grid-column: span X 表达持续天数。
- 时间刻度统一用 CSS 自定义属性定义,比如
--days: 14,后续所有列数、跨度都基于它计算
- 每行任务高度建议设为
minmax(32px, auto),避免文字换行撑高后错位
- 不要给甘特块加
width 或 left —— 它们只该靠 grid-column-start / end 定位
grid-column 算不准?检查日期对齐方式
甘特图最常出错的地方不是布局,而是“第 3 天”到底从哪一列开始。如果项目从周一启动,但你的网格第一列是周日,所有 grid-column: 3 / span 5 就全偏了 1 格。
必须统一基准:用 JavaScript 预算出「起始日期到网格首列的偏移天数」,生成对应 grid-column-start 值。例如起始日是周三,网格首列为周一,则偏移 = 2,第 1 个任务若从起始日开始,就要写 grid-column: 3(不是 1)。
- 别在 HTML 里手写
style="grid-column: 5" —— 动态数据必须走 JS 注入 style 或 class
- 跨月时注意:CSS Grid 列数固定,不能自动增减,需提前按最大跨度(如 60 天)设好列数
- 用
fr 单位定义列宽(如 repeat(60, 1fr)),比 px 或 % 更稳
鼠标悬停显示详情,但别用 title 属性
title 属性触发慢、样式不可控、移动端不一致,甘特块上需要的是即时、带格式的提示。直接用 浮层更可靠。关键点在于定位:浮层必须用 position: absolute 相对于甘特容器(不是单个块),否则滚动时错位。同时要禁用 pointer-events 在子元素上,避免遮挡点击。
- 浮层内容用
data-* 属性存原始信息(如 data-start="2024-05-10"),JS 渲染时格式化,避免 HTML 里硬编码日期字符串
- 添加
pointer-events: none 到浮层内部文字,确保鼠标能穿透到下方真实可点击区域
- 用
transform: translateY(-8px) 微调浮层位置,比 top: -24px 更平滑,不影响文档流
IE 不支持 Grid?那就用 Flex 模拟单行甘特
真要兼容 IE11,Grid 必须降级。但别整个重写——只对 IE 加载一套 display: flex 的横向布局,每行一个任务,用 flex-basis 按比例算宽度(如 14 天总长,第 3 天开始、持续 5 天 → 前 2 天留空 + 后 5 天占宽)。
重点不是“能不能做”,而是“要不要做”。IE 用户看到略简陋但数据正确的进度块,远好过空白或报错。降级方案只保留:任务名、色块、天数区间,砍掉悬停、拖拽、跨行连接线。
- 检测用
@supports not (display: grid),不是 UA 字符串判断
- Flex 版本中,所有宽度用
% 或 calc(),禁用 fr 和 span
- IE 下放弃响应式缩放,固定最小宽度 800px,防止列挤成一条线
时间块的边界对齐比颜色还重要。很多人花两小时调渐变,结果第 7 天的块和第 8 天之间有 1px 缝隙——那不是 CSS 问题,是起始列计算少加了 1。
纯 HTML 实现甘特图, 常见错误是把天数硬编码成固定像素宽——一旦缩放或换分辨率,进度条就错位。正确做法是让列宽由容器自动均分,再用 甘特图最常出错的地方不是布局,而是“第 3 天”到底从哪一列开始。如果项目从周一启动,但你的网格第一列是周日,所有 必须统一基准:用 JavaScript 预算出「起始日期到网格首列的偏移天数」,生成对应 关键点在于定位:浮层必须用 真要兼容 IE11,Grid 必须降级。但别整个重写——只对 IE 加载一套 重点不是“能不能做”,而是“要不要做”。IE 用户看到略简陋但数据正确的进度块,远好过空白或报错。降级方案只保留:任务名、色块、天数区间,砍掉悬停、拖拽、跨行连接线。 时间块的边界对齐比颜色还重要。很多人花两小时调渐变,结果第 7 天的块和第 8 天之间有 1px 缝隙——那不是 CSS 问题,是起始列计算少加了 1。 会卡死语义、
难维护宽度和响应式,真正轻量可控的是 CSS Grid。核心思路是:横轴为时间(列),纵轴为任务(行),每个 grid-column 控制起止列。grid-column: span X 表达持续天数。
--days: 14,后续所有列数、跨度都基于它计算minmax(32px, auto),避免文字换行撑高后错位width 或 left —— 它们只该靠 grid-column-start / end 定位
grid-column 算不准?检查日期对齐方式grid-column: 3 / span 5 就全偏了 1 格。grid-column-start 值。例如起始日是周三,网格首列为周一,则偏移 = 2,第 1 个任务若从起始日开始,就要写 grid-column: 3(不是 1)。
style="grid-column: 5" —— 动态数据必须走 JS 注入 style 或 classfr 单位定义列宽(如 repeat(60, 1fr)),比 px 或 % 更稳鼠标悬停显示详情,但别用
title 属性title 属性触发慢、样式不可控、移动端不一致,甘特块上需要的是即时、带格式的提示。直接用 position: absolute 相对于甘特容器(不是单个块),否则滚动时错位。同时要禁用 pointer-events 在子元素上,避免遮挡点击。
data-* 属性存原始信息(如 data-start="2024-05-10"),JS 渲染时格式化,避免 HTML 里硬编码日期字符串pointer-events: none 到浮层内部文字,确保鼠标能穿透到下方真实可点击区域transform: translateY(-8px) 微调浮层位置,比 top: -24px 更平滑,不影响文档流IE 不支持 Grid?那就用 Flex 模拟单行甘特
display: flex 的横向布局,每行一个任务,用 flex-basis 按比例算宽度(如 14 天总长,第 3 天开始、持续 5 天 → 前 2 天留空 + 后 5 天占宽)。
@supports not (display: grid),不是 UA 字符串判断% 或 calc(),禁用 fr 和 span
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











