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

用 <div> + CSS Grid 做可读甘特图,别碰 SVG<p>纯 HTML 实现甘特图,<code><table> 会卡死语义、<code><svg></svg> 难维护宽度和响应式,真正轻量可控的是 CSS Grid。核心思路是:横轴为时间(列),纵轴为任务(行),每个 <div> 表示一个时间块,用 <code>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 属性触发慢、样式不可控、移动端不一致,甘特块上需要的是即时、带格式的提示。直接用 <div class="tooltip"> 浮层更可靠。<p>关键点在于定位:浮层必须用 <code>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。



















