[csswg-drafts] [css-values-4] Flawed definition of the pixel unit (#5221)

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

== [css-values-4] Flawed definition of the pixel unit ==
I assume not a lot of people have taken math, but there is a logical flaw in the mathematical definition of the pixel unit in [css-values-4](https://drafts.csswg.org/css-values-4/#absolute-length). I found many vague and circular definitions in the specs, but I find this one rather serious and didn't want to leave it unmentioned. It seems it hasn't changed since CSS2, and so has been in the spec for years. I'll try to be a non-mathematical as possible in deriving the pixel unit. But I'll use some basic mathematical notation to describe the flaws, since sentences are inherently unclear to describe mathematical relations.

---

For continuous media the spec defines (or rather recommends) the pixel unit to be

> the whole number of device pixels that best approximates the reference pixel.

Good, so the question remains, what is this "reference pixel"? The reference pixel is defined as

> the visual angle of one pixel on a device with a pixel density of 96dpi and a distance from the reader of an arm’s length.

This is wrong. The first hint is to notice that an angle is not a length.

According to [Wikipedia](https://en.wikipedia.org/wiki/Visual_angle) the visual angle `V` (deg) is related to the linear size `S` (in) and the viewing distance `D` (in) by

> V = 2 arctan(S / (2D))

![diagram](https://upload.wikimedia.org/wikipedia/commons/7/79/EyeOpticsV400y.svg)

You don't need to know where the formula is coming from. All you need to understand is the meaning and units of the variables.

The reference pixel can **not** be the visual angle, since it's a length instead of an angle. What's it then? Well it can't be the viewing distance for pretty obvious reasons. So what variable is left? Yes, the linear size `S`. The reference pixel is the linear size for a specific given viewing angle and viewing distance. Mathematically, one could define the reference pixel RP as follows

> RP = ⌊2D * tan(V / 2)⌋

where `⌊⌋` is just the notation to round to the nearest integer.

If you can follow the math at all, you'll see this definition is what works with the rest of the spec and not the previous one.

___

Now you might ask, what's values are used for `D` and `V`? The spec mixed up the definition of the reference pixel with the derivation of the correct values of `D` and `V`. I'll try to motivate where the correct values come from.

Historically there were a lot of 96 DPI screens for which 1px was defined as one device pixel. But since screen DPIs increased rapidly, we wanted to make the pixel unit DPI-dependent otherwise 1px would get increasingly smaller as the DPIs grew (see the nice pictures in the spec). Hence the formula above. But to not break formatting on old 96 DPI screens, we needed to keep the now DPI-relative pixel unit the same size as before on 96 DPI screens. This the constraint needed to be able to determine the correct `D` and `V`, much like defining a polynomial by knowing the y-intercept.

By the formula, a linear size of `S = 1/96 in` (size of 1 device pixel on a 96 dpi screen) at the viewing distance `D = 28 in` (arm's length) corresponds to the viewing angle of `V = 0.0213 deg`.

These values `V = 0.0213 deg` and `D = 28 in` allow the pixel unit to work for 96 DPI screens as expected while being defined by a DPI-relative formula.

-----

TLDR;

I hope the above was clear to most people. Below is again a concrete list of what fixes I'd suggest. I'm happy to provide a concrete PR for this, if a fix is desired.

1. The definition of the reference pixel should be fixed!

The spec should also contain a clearer motivation for the choice of the `V` and `D` values.

2. The "recommendation" to define the pixel unit as the closest integer to the reference pixel should be a definition instead. As long as it's only a recommendation, the pixel unit is strictly speaking not defined by the spec. This is worrying, since UAs could define it to be _anything_ while still being spec compliant.

For the UA to still be able to actually change the value of the pixel unit, the viewing distance of `D = 0.28 in` (arm's length) should be made a recommendation instead of a requirement. This would make sense, since a phone isn't held at the same distance as a TV. This is probably already what UAs do, just nobody notices that this is spec in-compliant.

3. A logical flaw in the historical note should be fixed.

> Note: This definition of the pixel unit and the physical units differs from previous versions of CSS. In particular, in previous versions of CSS the pixel unit and the physical units were not related by a fixed ratio: the physical units were always tied to their physical measurements while the pixel unit would vary to most closely match the reference pixel. *(This change was made because too much existing content relies on the assumption of 96dpi, and breaking that assumption broke the content.)*

The reason the pixel unit and physical units were coupled has nothing to do with breaking the pixel unit on 96 DPI screens. Instead, it would break all non-96 DPI screens, since the now DPI-relative pixel unit adapts but the physical units don't. The physical units could still be independent from the pixel unit. But I assume the change was made, since people expected the physical units to have a fixed ratio to the pixel unit, and if the pixel unit is DPI-relative, so must the physical.

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

Received on Tuesday, 16 June 2020 18:43:58 UTC