Fractional DPR Border-Width Content Shifts

#384781869 Filed 2024-12-18 Status: Accepted P3 / S3 CL: 7619377

Problem

Content shifts when border-width changes at fractional DPR

At fractional devicePixelRatio (e.g. 1.5x on a 4K display at 150% scaling, or any browser zoom like 90%/110%), changing an element's border-width from 1px to 2px and compensating with margin-bottom: -1px causes the sibling element to visually shift. This is Chrome-specific -- Firefox does not exhibit this behavior.

Root Cause: Asymmetric Precision

Borders used floor(), margins did not

ConvertBorderWidth() stored border widths as int using floor(), while margins were stored as LayoutUnit (fractional, 1/64px precision). This asymmetry meant that at fractional zoom, borders and margins could never cancel out exactly.

The Math at 1.5x Zoom

border 1px border 2px margin -1px delta + margin shift
Old Chrome (floor to int) floor(1.5) = 1 floor(3.0) = 3 -1.5 (3 - 1) + (-1.5) = 0.5 0.5px SHIFT
Firefox (float) 1.5 3.0 -1.5 (3.0 - 1.5) + (-1.5) = 0.0 No shift
Fixed Chrome (float) 1.5 3.0 -1.5 (3.0 - 1.5) + (-1.5) = 0.0 No shift

The floor() loses 0.5px on the 1px border. The margin keeps its fractional value. The mismatch produces a visible 0.5 device-pixel shift -- enough to move text by one pixel row on screen.

Interactive Demo

Toggle the border state and observe whether the green sibling shifts. Use the CSS zoom slider to simulate fractional DPR (the bug only appears at non-integer zoom). Your current devicePixelRatio is:

Element (border-bottom: 1px)
Sibling (should not shift)
--

Reproduction

<style>
  body { margin: 0 }
  #element {
    height: 100px;
    border-bottom: 1px solid blue;
  }
  #element:hover {
    border-bottom: 2px solid blue;
    margin-bottom: -1px;
  }
  #sibling {
    width: 100px;
    height: 100px;
  }
</style>
<div id="element">Box with hover border</div>
<div id="sibling">hello<br>world</div>

View at 150% OS scaling or any fractional browser zoom (90%, 110%, etc.). On hover, the sibling shifts in Chrome but not in Firefox.

Fix

CL 7619377

Store border-width as float instead of int

Changed type_name: "int" to type_name: "float" for all four border-*-width properties in css_properties.json5. Updated ConvertBorderWidth() to return float, removing the floor() truncation. Borders now preserve the same fractional precision as margins through layout, so they cancel out exactly at any zoom level.

Is This Actually a Bug?

Yes -- the floor() created a Chrome-specific asymmetry

Comment #16 on the issue asks whether this is a real bug or expected behavior. The answer: it is a genuine Chrome-specific bug.

The reporter confirmed (Comment #10, #12) that at 1.5x DPR the 1px-to-2px border change with -1px margin compensation shifts in Chrome but not in Firefox. This is not about general sub-pixel snapping differences (Comment #9's edge case with 0.1px values). The root cause is that Chrome's ConvertBorderWidth() used floor() to truncate to int, while margins kept fractional precision via LayoutUnit. Firefox stores both as float, so they cancel exactly.

With the fix, Chrome matches Firefox behavior: integer CSS border/margin values that mathematically cancel out will also cancel in layout at any zoom level.

Test Matrix

Click to run the automated test across multiple simulated DPR values: