跳转到内容

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
  • 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 in bizplan/research/ and bizplan/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:166 sets .vp-doc table { display: block; border-collapse: collapse; margin: 20px 0; overflow-x: auto }. A display: block table 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, so overflow-x: auto never 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:186 caps the doc column at 784 px with a 1104 px container when there is no sidebar (this project sets sidebar: false). A 9-column specification table has roughly 85 px per column to work with.
  • Why CSS alone cannot fix it. Restoring display: table removes 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: false in config.mts escapes HTML in the source; it does not affect HTML emitted by a renderer rule, so a markdown-it rule is safe here.
章节标题:“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.

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.

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.

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.

  1. Screenshot the current state of /bizplan/product/, /bizplan/product/control/P09-control-protocol-evaluation and /bizplan/research/pdm-vendor-product-benchmark at 1440 px and 1920 px viewport widths, for a before/after pair. -> verify: baseline captured.
  2. 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.
  3. Check one prose-heavy page (/bizplan/BUSINESS-PLAN) at both widths. -> verify: line length still reads comfortably after A3.
  4. bun run docs:build. -> verify: build succeeds.
  5. git diff --check. -> verify: clean.
  6. 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).

  • min-width on a table cell is "undefined" in CSS 2.1 and merely honoured in practice by current browsers. If Chromium ignores it, the fallback is width: max-content on the table, which is correct but makes prose-heavy cells very wide; it would then be paired with a max-width on 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.
  • 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 in custom.css); screenshots recorded in task 20260913-0329. Completed 2026-09-14 03:15.