[csswg-drafts] [css-backgrounds] Add a 'hairline' border-width value (#3720)

tabatkins has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-backgrounds] Add a 'hairline' border-width value ==
People regularly ask for the ability to size things in device pixels (#3715 is the latest). This is virtually *always* intended for the use-case of sizing borders, to create "hairline" borders or separators.  

Since adding an actual device pixel unit is out of the question, we should still address this use-case directly, and add a `hairline` keyword to 'border-width', representing "the thinnest width that the UA believes is recognizable, snapped to the nearest whole number of device pixels". *Right now*, that'll be 1 device pixel, but if screens get significantly higher-res, it'll probably resolve to whatever number of device pixels gives you a value between 1/3 and 1/2 of a CSS px.

--------

## Why can't we add a device pixel unit, so you could just say `border-width: 1dp`?

Because device pixels are unpredictable in size. If you try to size anything bigger than a hairline with device pixels, the size will, today, vary by more than 300%, as there are devices that have 1dp==1px, and devices with 3dp=1px, and I think some devices are pushing higher than that. As display technology gets better,  this gulf will continue to grow, as there will likely *always* be 1dp==1px devices in use.

We already know from past experience that authors can't generally handle units with an unpredictable "sliding scale" ratio; some browsers used to have `in` and `px` decoupled, so that `in` was as close to an actual inch as the browser could get, and `px` was a device pixel. The end result was authors that used the `in` (or `cm`/`mm`) to size their pages would often get broken pages on devices whose in-px ratio was different. And that was a ratio that could differ whose min and max could differ by, at most, 50%!  (Handling an unpredictable ratio is a fundamentally very difficult problem! We have better, less fragile layout tools to help with that these days, but it's still virtually guaranteed to result in problems if we expose this.

Plus, the notion of a "device pixel" is screen-specific; when printing, the analogue to "device pixel" is the "dot", the smallest drop of ink that can be placed at a particular location. Printers not only have much *smaller* dots than screens have pixels, and in a larger range (consumer printers can vary from 300dpi to more than 1000dpi), they also vary based on color; black-and-white dpi is often much higher than color dpi. Sizing *anything* based on "device pixels" will either be *wildly unpredictable* on printers, or else it'll be a "virtual device pixel" that doesn't correspond to anything physical anyway.

And all this isn't even getting into screens that simply more exotic than the "rectilinear grid of hardware pixels" design that this sort of feature assumes. Some screens layer their pixels in a non-square grid. Some have *differently-sized* pixels, layered in separate rectilinear grids. Some have different grids for each subpixel color.  All in all, the notion of a "device pixel" as something you can naively size things in is already nonsensical for many output devices, and the situation is likely to only get worse as time goes on.

## Why not a device-pixel rounding function?

In #3715 @florian and I talk about a function that rounds a length to the nearest number of device pixels, as a compromise that delivers many of the benefits of device-pixel sizing without as many of the downsides. On further consideration, I don't think we want this either.

For the case of hairline borders, a device-rounding function achieves basically the same thing as a 'hairline' value, just in a slightly more complicated way. Users have to know to write `border-width: dp-round(.5px)` or what-have-you, rather than `border-width: hairline;`.  The only theoretical benefit of `dp-round()` over `hairline` is that it lets you distinguish between whether you *really* want .33px or .5px, when that distinction might matter for visibility, but in practice that's a wash anyway, since a 3x screen will still probably choose .33px over .67px if you say `dp-round(.5px)`, and a 2x screen will still use .5px if you say `dp-round(.33px)`, and many devices will end up still choosing 1px anyway, so the theoretical gain in precision is lost in practice. In a theoretical future with super high-res screens, it might become relevant; we can revisit the question at that point. ^_^

For *any other case*, rounding to the device pixel doesn't do anything meaningful *unless you're also rounding the position*. Otherwise it's possible that the box is exactly 200dp tall, but it's offset 150.2dp from the top of the screen, so it's still fuzzy. And unless we offer position-rounding as some sort of separate property switch, you have to instead use dp-round() on your *ancestors*, too, all the way up to the root. (And depending on how you're being laid out, that still might not be enough; flexbox alignment has no way to force a rounding on the gap between flex items, for example.)

So, dp-round() is overkill complexity for hairlines, and doesn't do anything useful for most non-hairline cases.

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/3720 using your GitHub account

Received on Monday, 11 March 2019 20:00:06 UTC