NEW 261463
Line height rounding compounds in element height
https://bugs.webkit.org/show_bug.cgi?id=261463
Summary Line height rounding compounds in element height
Matias Szylkowski
Reported 2023-09-12 09:00:46 PDT
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. https://codepen.io/mszylkowski/pen/xxmgdXb 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)
Attachments
rendering in Safari, firefox, chrome (197.12 KB, image/png)
2023-09-14 01:44 PDT, Karl Dubost
no flags
testcase (803 bytes, text/html)
2023-09-14 01:45 PDT, Karl Dubost
no flags
Karl Dubost
Comment 1 2023-09-14 01:44:33 PDT
Created attachment 467678 [details] rendering in Safari, firefox, chrome
Karl Dubost
Comment 2 2023-09-14 01:45:17 PDT
Created attachment 467679 [details] testcase
Karl Dubost
Comment 3 2023-09-14 01:46:53 PDT
Safari: 90px Firefox: 99px Chrome: 98.90625px
Radar WebKit Bug Importer
Comment 4 2023-09-19 09:01:14 PDT
Ahmad Saleem
Comment 5 2023-10-31 14:32:26 PDT
I think Alan was looking into going 'fractional' route for IFC in bug 261212 and I added all possible 'fractional' related issues as 'See Also' in it.
Note You need to log in before you can comment on or make changes to this bug.