[Webkit-unassigned] [Bug 261463] New: Line height rounding compounds in element height

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Tue Sep 12 09:00:46 PDT 2023


            Bug ID: 261463
           Summary: Line height rounding compounds in element height
           Product: WebKit
           Version: Safari 16
          Hardware: Mac (Intel)
                OS: macOS 13
            Status: NEW
          Severity: Normal
          Priority: P2
         Component: Text
          Assignee: webkit-unassigned at lists.webkit.org
          Reporter: mszylkowski at google.com
                CC: mmaxfield at apple.com

On multiline text elements with a non-integer line height, the line-height flooring compounds the errors onto the element height. For instance, if `line-height: 9.9px` for a text with 10 lines, the height of the element will be `90px` in Safari (tested in 16 and 17-TP) whereas other browsers (tested in Chrome and Firefox) compute the element height as `99px`. This is reflected in the rendering of each line of text, that in Safari renders each line on the `floor(lineHeight) * lineNumber` pixel (note how the flooring happens before multiplying), whereas on other browsers the lines render on the `round(lineHeight * lineNumber)` pixel (where it computes the correct Y value without rounding/flooring the lineHeight).

This has a lot of repercussions in Safari only:
- `line-height` cannot animate smoothly in Safari.
- Websites cannot rely on `line-height` to control the size of their text elements in Safari.
  - Eg: If I want a text element to span 100px vertically with 8 lines of text, I can't use `line-height: 12.5px` in Safari. The element would be `12px * 8 = 96px` height.

The ways of fixing this (for web developers) are very cumbersome and less performant:
- Setting the font-size and line-height of the text element to a large multiple of the desired size (so Safari has a higher precision), and using transforms to scale it down.
- Manually calculate the Y positions of each line of text, and set the line-height per line in a separate container to achieve that (eg: to span 25px in two lines, use `<div style="line-height="12px">Hello</div><div style="line-height="13px">World</div>`).
- Setting the line-height to an integer and use `transform: scaleY()` to compensate.
- Use images to draw text accurately.


Below is a minimal demo. 


Setup: Height of box should theoretically be 24.9*10=249

Safari (16 and 17-TP): Computed height is { clientHeight: 240, boundingClientRect.height: 240 }
Firefox: Computed height is { clientHeight: 249, boundingClientRect.height: 249 }
Chrome: Computed height is { clientHeight: 249, boundingClientRect.height: 248.984375 }

Note: this might be a good candidate for improving the interop of Webkit: https://webkit.org/blog/13706/interop-2023/

Found a few similar/related bugs:
- https://bugs.webkit.org/show_bug.cgi?id=225695 (maybe this is a regression?)
- https://bugs.webkit.org/show_bug.cgi?id=216601 (the computed value was fixed)

You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20230912/6fded22d/attachment.htm>

More information about the webkit-unassigned mailing list