1px borders sometimes not rendering
- Dominant language
- Rust
- Stars
- 4.1k
- Forks
- 203
- Avg merge
- 8h 58m
- Merged PRs (30d)
- 112
Description
I ran into situations where borders set to 1px sometimes don't render at all.
Example:
```css
.var-panel {
border: 1px solid #ff0000;
border-top-width: 0;
border-radius: 8px;
background: #212121;
overflow: hidden;
padding-bottom: 4px;
margin-bottom: 24px;
outline: none;
}
```
| Expected: red outline on the left, bottom and right side — top missing | Actual: the whole outline is gone, all four sides |
|---|---|
| |
|
After some digging (with the help of AI), I found and verified two independent problems behind this:
**1. blitz: divide-by-zero → NaN erases the whole outline**
[`start_angle()`](https://github.com/DioxusLabs/blitz/blob/main/packages/blitz-paint/src/kurbo_css/css_box.rs#L616) in `kurbo_css/css_box.rs` computes each rounded corner's arc split from the ratio of the two adjacent border widths. If one width is zero the expression yields `inf / inf` = NaN. Corner arcs are shared between adjacent edges, and a box's four edge shapes are batched into a single fill command — so one zero-width side poisons the *whole* border outline (vello drops NaN segments silently).
The fix here could be a simple check for width like this:
```diff
fn start_angle(bt_width: f64, br_width: f64, radii: Vec2) -> f64 {
+ match (bt_width, br_width) {
+ (0.0, 0.0) => return FRAC_PI_4, // both zero: treat as uniform
+ (0.0, _) => return FRAC_PI_2, // horizontal split
+ (_, 0.0) => return 0.0, // vertical split
+ _ => {}
+ }
+
// slope of the border intersection split
let w = bt_width / br_width;
let x = radii.y / (w * radii.x);
```
**2. taffy: layout rounding zeroes device-pixel-snapped border widths at fractional scales**
blitz calls taffy's [`taffy::round_layout`](https://github.com/DioxusLabs/blitz/blob/main/packages/blitz-dom/src/resolve.rs#L394) and hands the result straight to the painter. So whatever that rounding does to border widths is what gets painted.
With fractional scaling (e.g. 1.25) a `1px` border arrives in taffy as `0.8` CSS px (DPI-aware CSS engines snap lengths to whole device pixels).
[`round_layout`](https://github.com/DioxusLabs/taffy/blob/main/src/compute/mod.rs#L219) then rounds each box edge to a whole *CSS* pixel independently, and the two edges of such a border can land on the same number:
```
left edge: 63.6 -> 64
edge + 0.8: 64.4 -> 64
rounded border width: 0
```
I let AI write a fix, which fixes the issue, but I don't fully understand it
and performance could be worse than now — that's why no PR, patch attached.
[round_layout_with_grid.patch](https://github.com/user-attachments/files/31863757/round_layout_with_grid.patch)
On the blitz side we could then pass the scale to use for rounding:
```rust
taffy::round_layout_with_grid(self, root_element_id, self.viewport.scale());
```
Contributor guide
Research direction
Reproduce the border case, then inspect start_angle() in packages/blitz-paint/src/kurbo_css/css_box.rs and round_layout in packages/blitz-dom/src/resolve.rs, along with taffy's src/compute/mod.rs. Check both zero-width corners and fractional-scale rounding, using the attached patch as context. Done means 1px borders remain visible in both cases without introducing NaN geometry.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- css, rust
- Domain
- computer-graphics, frontend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100