cohort分析表必须用table而非div,因其本质是二维结构化数据:行代表入组时间、列代表留存周期、单元格为数值,需原生行列对齐、表头语义关联(scope)、屏幕阅读器支持及excel导出保真;div模拟会丢失可访问性、响应式错位、打印分页断裂、键盘导航失效。

cohort 分析表为什么必须用 table 而不是 div 布局
因为同期群(cohort)本质是二维矩阵:行是用户入组时间(如“2024-01 新客”),列是留存周期(如“D1/D7/D30”),单元格是百分比或人数。语义上这是典型的数据表格,table 提供原生的行列对齐、表头关联(scope)、屏幕阅读器支持,而用 div 模拟会丢失可访问性,且响应式对齐极易错位。
常见错误是强行用 display: grid 套三层嵌套实现“看起来像表格”,结果导出 Excel 时全乱、打印时分页断裂、键盘导航失效。真正需要的是语义正确 + 样式可控,不是视觉仿制。
<table> 必须带 <code><thead> 和 <code><tbody>,首行用 <code><th scope="col">,首列用 <code><th scope="row"><li>横向滚动区域需包裹在 <code><div class="cohort-scroll"> 内,设 <code>overflow-x: auto,但table本身不设width: 100%,否则列宽被压缩失真- 避免给
td设固定width,改用min-width配合table-layout: fixed控制列宽一致性
如何让 cohort 表格支持动态列数(比如自动从 D1 到 D90)
硬编码 <th>D1</th>
<th>D7</th>
<th>D30</th> 是最常见反模式——业务要求加到 D90 时就得改 HTML,后端数据字段一变就崩。正确做法是前端根据数据结构动态生成列头。
假设后端返回的 JSON 是:
{"cohorts": [{"name": "2024-01", "retention": [0.42, 0.28, 0.15, ...]}, ...], "days": [1, 7, 14, 30, 60, 90]}
那么渲染逻辑应为:
- 先遍历
data.days生成<th>,内容为 <code>"D" + day,不写死任何数字 - 每行
tr中,按顺序取cohort.retention[i]渲染td,值为空时显示-而非0,避免误导 - 列数变化时,CSS 不依赖类名(如
.d7-col),而是用属性选择器:td:nth-child(2) { background: #f0f9ff; } - 在
<style></style>中提前定义 10 级色阶::root { --cohort-0: #f8f9fa; --cohort-10: #28a745; ... } - 后端或 JS 在渲染
td时,根据数值映射为整数等级(如 0.0–0.1→0,0.1–0.2→1…),写入data-level="7" - CSS 直接写:
td[data-level="7"] { background-color: var(--cohort-7); },无计算、无重排 - 注意:低于 0.01 的值统一标为
data-level="0",避免出现“几乎看不见的浅绿”造成误读 - 日期行(cohort name)必须设
z: "yyyy-mm"格式码,否则 Excel 默认当文本,无法排序 - 所有留存率单元格设
t: "n"(数字)+z: "0.00%",而不是传字符串"42%" - 表头第一格(左上角)留空,不要填“Cohort”,否则 Excel 会把它当数据列;真正的 cohort 标题用
!merges合并单元格实现 - 导出前调用
worksheet["!cols"]固定列宽,防止 Excel 自动缩列导致 D90 列显示为“######”
cohort 单元格颜色渐变怎么用纯 CSS 实现且不卡顿
用 JS 循环每个 td 计算背景色(比如 hsl(120 - value * 120, 70%, 60%))在 50×50 表格里会明显掉帧。更稳的方式是预设 CSS 变量 + 自定义属性驱动。
导出 cohort 表格为 Excel 时日期列和百分比格式总出错
浏览器直接右键“另存为 Excel”不可靠,table2excel 类库又已过时。真正能保格式的是用 SheetJS (xlsx) 手动构造 worksheet,并显式设置单元格类型。
颜色、合并、格式这些细节漏一项,业务方拿到 Excel 就得手动调半天——cohort 分析的价值不在生成而在复用,格式稳定才是第一优先级。











