91861565bb
- Introduced API guidelines for interface contracts and request handling. - Added design tokens usage guidelines for consistent styling across the project. - Established DTO guidelines for defining request parameters and response data types. - Created frontend structure guidelines to clarify directory organization and code placement rules. - Compiled a comprehensive frontend development guideline document covering various aspects of the development process. - Implemented quality guidelines to ensure code maintainability and adherence to best practices.
7.8 KiB
7.8 KiB
id, title, created, updated, status, scope, category, confidence, last_verified, promotion_target, projects, tags
| id | title | created | updated | status | scope | category | confidence | last_verified | promotion_target | projects | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 20260724-bounded-list-flex-height-chain | 有界列表页使用连续 Flex 高度链并收敛滚动视口 | 2026-07-24 | 2026-07-24 | candidate | global | frontend-layout | medium | 2026-07-24 | none |
|
|
有界列表页使用连续 Flex 高度链并收敛滚动视口
Trigger
列表页、主从工作台或树表页面需要填满应用内容区,同时保持标题、筛选、操作栏和分页可见,只让表格数据区、树节点区或详情正文滚动;或者当前页面出现双滚动条、分页被挤出视口、h-full 不生效、窗口高度变化后布局失效。
Context
usercenter-react 的商场管理页面曾需要移除固定像素高度推算,使应用外壳、路由页面、Tabs、组织树和数据表形成连续的有界高度链。修复后,普通内容页仍由共享 <main> 滚动,有界工作台则填满 <main> 并把滚动交给最小内容视口。
这项经验的核心不是“给页面加 flex-col”,而是同时解决两个契约:高度从视口向后代连续传递,滚动权从外层收敛到最小内容区域。任一中间层缺少明确高度或 min-h-0,后代的 h-full、flex-1 和 overflow-auto 都可能无法按预期工作。
Evidence
- 2026-07-24:重新检查
usercenter-react当前源码、项目规范和 Git 历史;中央经验库搜索“有界列表页 / 连续 Flex 高度链 / min-h-0 / 滚动视口”无重叠条目。 usercenter-react/src/shared/layout/app-layout.tsx:207-236:应用根节点使用h-dvh overflow-hidden,内容列使用flex h-full min-h-0 flex-col,共享<main>使用min-h-0 flex-1 overflow-y-auto。usercenter-react/src/features/market-management/pages/market-management-page.tsx:181-230:有界路由根节点、分栏、Tabs 和 TabPane 连续使用h-full、flex-1、min-h-0与受控 overflow。usercenter-react/src/shared/table/data-table.tsx:40-45,168-232:fillHeight以 opt-in 方式把表格面板变成有界 Flex 列,工具栏和分页留在滚动视口之外,数据区域消费剩余高度。usercenter-react/.trellis/spec/frontend/layout-guidelines.md:23-32,74-125:记录了各布局边界的类契约、滚动归属、错误矩阵和禁止使用固定calc(100vh - Npx)的规则。usercenter-react/specs/page-layout.spec.md:5-11:产品级规范要求有界页面使用连续 Flex 高度链,并将 overflow 委托给最小树或数据视口。- Git 提交
ccf068c修复商场管理页面高度适配,1bb14e8将实践整理为 bounded layout 指南,849219a继续补充可伸缩侧栏场景下的表格滚动与 sticky 边界。 - 当前仓库的
src/shared/list-templates/master-detail-list-template.tsx:34-60仍存在calc(100vh - 10.5rem)实现;这是需要结合响应式父级契约进一步验证的现有反例,不能仅凭规则直接判定或修改。
Root cause
已验证:
flex-col和flex-1只负责空间分配,不会自动建立可解析的高度边界。- Flex/Grid 子项默认的
min-height: auto会阻止内容区域收缩;中间层缺少min-h-0时,内容会撑高页面而不是在指定视口内滚动。 h-full依赖祖先提供确定高度;高度链中断时,百分比高度不能可靠地代表剩余视口空间。- 页面、共享
<main>和表格数据区同时拥有纵向 overflow 时,会形成嵌套或竞争滚动条。 calc(100vh - Npx)、JavaScript 测量和重复的标题高度常量容易在工具栏换行、外壳调整、缩放或窄屏布局下失效。
推断:把布局评审固定为“先从外向内检查高度链,再从内向外确认唯一滚动所有者”,比逐个添加高度类或 overflow 类更容易定位缺失环节,也更适合跨组件复用。
Preferred action
- 先区分页面模式:普通内容页继续由应用
<main>滚动;只有需要固定控制区和内部滚动的页面才进入有界模式。 - 从视口向目标滚动区域建立连续高度链:应用根节点建立动态视口边界,中间内容列使用
flex h-full min-h-0 flex-col,有界路由根节点使用flex h-full min-h-0 flex-col overflow-hidden。 - 为所有需要消费剩余高度或继续向下传递高度的 Flex/Grid 中间层添加
min-h-0;不要只修改最终表格容器。 - 标题、筛选、操作栏、Tabs 头部和分页等固定区域使用
shrink-0。剩余内容区域使用min-h-0 flex-1。 - 将纵向滚动交给最小内容视口:通常是表格数据区、树节点区或详情正文。结构层使用
overflow-hidden,实际内容视口使用overflow-auto或overflow-y-auto。 - 共享表格的填高能力保持 opt-in;只有父级已经提供有界
h-full/min-h-0区域时才启用,避免改变普通内容型页面的默认行为。 - 优先使用 Flex 剩余空间,不使用固定
calc(100vh - Npx)、JavaScript 高度测量或跨组件共享的像素常量。 - 在真实浏览器中验证滚动归属:有界页面不增加 body 高度,固定控制区和分页保持可见,只有目标数据区滚动;同时检查窄屏、工具栏换行、loading、empty 和 error 状态。类型检查、lint 和构建不能替代这项验证。
Examples
<div className="h-dvh overflow-hidden">
<div className="flex h-full min-h-0 flex-col">
<main className="min-h-0 flex-1 overflow-y-auto">
<section className="flex h-full min-h-0 flex-col overflow-hidden">
<header className="shrink-0">{header}</header>
<div className="shrink-0">{filtersAndActions}</div>
<div className="min-h-0 flex-1 overflow-hidden">
<DataTable fillHeight {...tableProps} />
</div>
</section>
</main>
</div>
</div>
记忆方式:高度从外向内连续传递,滚动权收敛到最小内容视口。
Boundaries
- 普通详情页、表单页和自然增长的长页面通常应继续由共享
<main>滚动,不要为了统一外观强制启用有界模式。 - 移动端主从区域改为纵向堆叠时,可能更适合自然页面滚动;有界模式可以只在桌面断点启用。
overflow-hidden只有在后代明确拥有滚动视口时才安全,否则会直接裁切内容。- Tabs、Drawer、Spin、Table 和虚拟列表等第三方组件可能插入包装层,需要根据实际 DOM 补齐高度链或沿用组件自己的滚动机制。
- 可交互变宽的分栏可能触发第三方表格的 ResizeObserver 和 sticky 行为;
nativeStickyHeader、固定列实现等属于组件或项目特例,不是连续 Flex 高度链的通用要求。 - 已存在的
calc(100vh - Npx)不应机械替换;需要先确认页面父级是否能提供完整高度链,以及窄屏模式是否依赖自然内容高度。 - 当前证据主要来自
usercenter-react的一次完整修复及后续演进。在另一个项目或独立场景复用并完成浏览器验证前,不提升为全局强制规则。
Failed approaches
- 只在页面根节点增加
flex-col或只在表格增加flex-1:高度链仍可能在中间层中断。 - 只给最终内容区域增加
overflow-auto:默认min-height: auto仍可能让它撑高父级。 - 同时让
<main>、路由根节点和表格数据区滚动:容易出现双滚动条、滚轮焦点切换和分页被挤出视口。 - 通过
calc(100vh - Npx)或 JavaScript 测量补偿标题高度:在标题、操作栏换行或应用外壳变化后容易产生新的固定偏差。
Promotion record
- Not promoted. 当前已有一个项目中的修复、规范和后续演进证据,先保留为中央 candidate;待第二个项目或独立场景验证后,再考虑提升为
patterns/下的前端布局模式或可执行浏览器检查。