htmlcssgoogle-chromeelectronresolution

css border: 1px appear as 0.667px or 1px depending on the computer / display resolution (?)


This is weird. I am testing the same web application (Chrome embedded in Electron) and I have two exact copies in 2 computers, both windows 10, one with a 1080p display and the other with a 4K display (this should be irrelevant, I guess it is EDIT: now I'm start thinking this is the problem).

However, when I run the application in both sites I see a difference I cannot explain and I don't know how to fix, apart from not using the border parameter.

The problem is that by using border: 1px solid #000 in a circle or square, in one computer it computes as 1px, and in the other as 0.667px.

Why on earth is this happening?

EDIT: I can see that this happens to any border that I try. And I can see that if I put 2px, then it computes as 2px, but anything in 1px computes as 0.667px in the 4K-computer

EDIT2: The same with em, an em of 0.2 computes as 2px, and of 0.1 computes as 0.667px. From 0.132 and 0.133 em it jumps from 0.667 to 1.333 px computed, it is impossible to get 1px (!!)

computer1_img computer2_img

Left -> the lines are not aligned since the squares with the border don't add 2px but 0.667x2 (computer 1)

Right -> the lines are aligned since the border computes as 2px (computer 2)

And below you can see the Chrome developed console info

computer1_css computer2_css


Solution

  • I'm struggling to find any definitive information on this but I am fairly confident about why this happens.

    A 4K screen has such a high pixel density that Chromium is scaling the elements on the page up so that they do not look tiny on the 4K screen. In this case it appears to be using a scaling factor of 1.5. This is clear from your screenshots: both the text and boxes appear about 1.5x larger on the 4K screen.

    So why does the 1px border not scale up to 1.5px too? Because it wouldn't look crisp. There seems to be an assumption that when you specify a 1px border, what you really want is the smallest border supported by the screen, so you still get 1px on a 4K screen, and thus it still looks sharp.

    Chromium scales for high DPI transparently, so that in the web inspector you still see the original CSS values. So although your 10px font-size is now really being rendered as 15px, it still shows as 10px in the inspector. To show you that the border has not been scaled up, the 1px is divided by 1.5, giving 0.667px.

    This behaviour strikes me as sensible, but as a side effect it messes up your positioning. Here are a couple of possible workarounds:

    1. Add a 1px border to all the boxes, making the border the same colour as the box where no black border is desired. This will ensure they all line up.
    2. Use box-sizing: border-box so that the specified width and height of the boxes includes the border. The default value (content-box) adds the border outside of the specified box size, which is why you currently have an alignment problem.