Collapsed table borders paint a phantom 3px grid for borderless tables and use border-top-color for every edge
- Dominant language
- Rust
- Stars
- 4.1k
- Forks
- 203
- Avg merge
- 8h 58m
- Merged PRs (30d)
- 112
Description
Tables with `border-collapse: collapse` are painted with a synthesized border grid derived from the first cell's border (`build_table_context` → `draw_table_borders`). Two bugs in that path make most collapsed tables render a thick dark grid that isn't in the document:
## 1. `none`/`hidden` border sides contribute their *computed* width
Stylo keeps the computed `border-*-width` even when the side's `border-style` is `none` — the used width is only zeroed at conversion time (`stylo_taffy::convert::border` does check `style.none_or_hidden()`). The table code reads the raw widths without that check:
- `blitz-dom/src/layout/table.rs` — gap for `BorderCollapse::Collapse` is `max(border_left_width, border_right_width)` × `max(border_top_width, border_bottom_width)` of the first cell, styles never consulted: https://github.com/DioxusLabs/blitz/blob/main/packages/blitz-dom/src/layout/table.rs#L120-L134
- `blitz-paint/src/render/border.rs` `draw_table_borders` — same for the painted width.
Since the initial value of `border-width` is `medium` (3px), **every collapsed table whose first cell has no border at all gets a phantom 3px grid** — gutters between all rows/columns plus a 3px outer border:
```html
plain aplain b
```
renders with a 3px dark grid around and between the cells; Chrome/Firefox/Servo render no borders at all.
## 2. Every grid line is painted with `border-top-color` (and outer edges ignore `none`)
`draw_table_borders` resolves one color — the first cell's `border_top_color` — and paints every horizontal *and* vertical line with it (there's a `// TODO: support different colors for different borders`): https://github.com/DioxusLabs/blitz/blob/main/packages/blitz-paint/src/render/border.rs#L538-L543
An unset `border-top-color` resolves to `currentColor`, so the lines come out near-black on typical pages even when the borders that actually exist are a different color. Real-world case (Sentry's weekly-report email): bar-chart columns separated with `border-right: 10px solid #fff` on a white background — invisible in real clients, but blitz paints 10px near-black bars. The outer-edge checks also only skip `BorderStyle::Hidden`, so a plain borderless table still gets its outer border painted.
## Suggested direction
Within the existing first-cell approximation (no per-edge conflict resolution):
- treat a side as zero-width unless its style is visible (share the `none_or_hidden` semantics of `stylo_taffy::convert::border`), in both layout (gap/outer border) and paint;
- pick width *and* color per axis: vertical lines from the first cell's widest visible left/right side, horizontal lines from the adjacent rows' `border-top`/`border-bottom` (the common `tr { border-bottom: … }` separator pattern) falling back to the first cell's top/bottom;
- outer edges: the wider of the table's own border and the grid line for that axis, with `hidden` on the table side suppressing the edge (CSS 2.2 §17.6.2.1) and ties resolved cell over row over table.
We've implemented this in our fork and it fixes the above cases while keeping the approximation: https://github.com/fifteenlabs/blitz/commit/f531a51621310bf05f75c0cb33bbadaf4013928d — happy to upstream it as a PR if the approach looks right.
Contributor guide
Research direction
Start with blitz-dom/src/layout/table.rs and blitz-paint/src/render/border.rs, especially build_table_context and draw_table_borders, then compare the referenced fork commit. Verify that invisible sides contribute no width, visible edges use the appropriate widths and colors, and collapsed borderless tables no longer paint a grid or outer border.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- computer-graphics, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100