20260913-0331-doc-table-layout Fix squeezed table rendering and widen the doc column
- status: completed
- createdAt: 2026-09-13 03:31
- relatedTask: 20260913-0329-doc-table-layout
Context
章节标题:“Context”- What the published pages actually look like. In the product package index the
eight-column 产品家族(配电) table renders every CJK cell one character per line
(
38/路高/边:...), the row grows to several screens tall, and no horizontal scrollbar appears. The same shape repeats anywhere a table has more than about four columns. - Scale. 40+ Markdown files carry tables of 6-13 columns; the widest is
bizplan/product/control/P09-control-protocol-evaluation.md(13 columns), and the longest single table row in the corpus is 1436 source characters. This is the dominant content form inbizplan/research/andbizplan/product/, so the defect affects most of the site. - Root cause (verified in the installed theme).
node_modules/vitepress/dist/client/theme-default/styles/components/vp-doc.css:166sets.vp-doc table { display: block; border-collapse: collapse; margin: 20px 0; overflow-x: auto }. Adisplay: blocktable is a block box constrained to the content column; the table structure it still generates is an anonymous table box laid out inside that width. Auto table layout therefore distributes the available 784 px across all columns, shrinking each toward its min-content width — which for CJK is one character, since CJK breaks between any two characters. The table never becomes wider than the block, sooverflow-x: autonever fires. Latin-heavy sites do not hit this because an English word's min-content width is the whole word. - Aggravating factor.
node_modules/vitepress/dist/client/theme-default/components/VPDoc.vue:186caps the doc column at 784 px with a 1104 px container when there is no sidebar (this project setssidebar: false). A 9-column specification table has roughly 85 px per column to work with. - Why CSS alone cannot fix it. Restoring
display: tableremoves the scroll container along with the squeeze, and the table then overflows the page. The table needs a wrapper element to scroll inside, and VitePress does not emit one.markdown.html: falseinconfig.mtsescapes HTML in the source; it does not affect HTML emitted by a renderer rule, so a markdown-it rule is safe here.
Proposal
章节标题:“Proposal”A. Recommended: scroll wrapper + column floor + wider doc column
章节标题:“A. Recommended: scroll wrapper + column floor + wider doc column”A1 — Emit a scroll wrapper (.vitepress/config.mts). Add a markdown.config hook
that overrides the table_open / table_close renderer rules to wrap every table in
<div class="vp-table">. Five lines, no dependency.
A2 — Table CSS (.vitepress/theme/custom.css).
| Rule | Effect |
|---|---|
.vp-doc .vp-table { overflow-x: auto } |
the wrapper is the scroll container |
.vp-doc .vp-table > table { display: table; width: 100%; margin: 0 } |
real table layout; narrow tables still fill the column |
.vp-doc .vp-table th, .vp-doc .vp-table td { min-width: 6.5em } |
a column can no longer collapse below a readable CJK width; when the sum exceeds the column, the table overflows and the wrapper scrolls |
.vp-doc .vp-table td { font-variant-numeric: tabular-nums } |
current/voltage figures line up across rows |
The exact min-width is tuned against screenshots, not fixed in advance; 6.5em at the
theme's 14 px table font is ~91 px of text plus 32 px padding.
A3 — Doc column width (.vitepress/theme/custom.css). With no sidebar, raise the
no-sidebar caps at >=1280 px from 1104/784 to 1360/1104 and raise
--vp-layout-max-width so the nav bar stays aligned. Prose then runs to ~68 CJK
characters per line — wider than now, still inside a comfortable measure — and a
9-column table gets 1104 px before it needs to scroll. VPDoc.vue styles are Vue-scoped,
so the override needs !important; that is a VitePress-upgrade tripwire and is
commented as such.
B. Alternative: A1 + A2 only, doc column untouched
章节标题:“B. Alternative: A1 + A2 only, doc column untouched”Fixes the reported defect with zero layout risk, but every table with more than about six columns scrolls, including many that would fit at 1104 px. Cheapest option.
C. Rejected: full-bleed tables
章节标题:“C. Rejected: full-bleed tables”Keep prose at 784 px and let tables break out to the viewport with negative margins.
Gives the best of both, but the math has to account for the outline aside, the
container centring and three breakpoints, and it collides with the mermaid scroll
container already in custom.css. Disproportionate fragility for the gain.
D. Rejected: rewrite the wide tables
章节标题:“D. Rejected: rewrite the wide tables”Splitting 13-column tables into several narrower ones is a content change across 40+ files, loses the side-by-side comparison those tables exist for, and does not fix the renderer for any table added later.
Scope
章节标题:“Scope”| File | Change |
|---|---|
.vitepress/config.mts |
markdown.config hook wrapping tables in <div class="vp-table"> |
.vitepress/theme/custom.css |
table scroll/min-width/numeral rules; no-sidebar width overrides (A only) |
docs/changelog.md |
record the change |
No Markdown content changes; no new dependency.
Verification
章节标题:“Verification”- Screenshot the current state of
/bizplan/product/,/bizplan/product/control/P09-control-protocol-evaluationand/bizplan/research/pdm-vendor-product-benchmarkat 1440 px and 1920 px viewport widths, for a before/after pair. -> verify: baseline captured. - Apply the change, reload, re-screenshot the same three pages. -> verify: no cell wraps per character; wide tables scroll inside their own box; the page itself does not scroll horizontally.
- Check one prose-heavy page (
/bizplan/BUSINESS-PLAN) at both widths. -> verify: line length still reads comfortably after A3. bun run docs:build. -> verify: build succeeds.git diff --check. -> verify: clean.- Report the screenshots before deploying.
Screenshots run in a sibling zenika/alpine-chrome container on --network host
(station itself uses host networking, so the dev server on :5199 is reachable that
way; the usual --network traefik cannot see it).
Open Items
章节标题:“Open Items”min-widthon a table cell is "undefined" in CSS 2.1 and merely honoured in practice by current browsers. If Chromium ignores it, the fallback iswidth: max-contenton the table, which is correct but makes prose-heavy cells very wide; it would then be paired with amax-widthon the wrapper's table.- Whether to also make the first column sticky on wide tables is deliberately not in this scope; it is the obvious follow-up if scrolling 13 columns proves annoying.
Annotations
章节标题:“Annotations”- 2026-09-14 01:30 owner: approved together with the documentation-standard plan. Option A implemented (table wrapper in
config.mts, table and width rules incustom.css); screenshots recorded in task 20260913-0329. Completed 2026-09-14 03:15.