What is a pixel?
A pixel is the smallest unit of screen display. On a 1080p screen, it has 1920 * 1080 pixels, which means that there are 1920 pixels on the horizontal side and 1080 pixels on the vertical side. A pixel is a unit color block, which is a mixture of rGBA’s four channels. For a 12 megapixel camera lens, it has 12 million light sensing units, and the maximum image resolution it can output is about 3000 x 4000.
So does the pixel itself have a size? How big is a pixel?
Yes, the smaller a pixel is, the more pixels are needed on a screen of the same size, and the denser the pixels are. If there are 435 pixels in an inch, then it has a DPI/PPI of 435. The 15-inch Macbook Pro has a resolution of 2880 x 1,800. The 15-inch screen is 15 inches diagonally (15.4 inches) and 13 inches horizontally (13 inches), so the PPI is 2880/13 = 220. The denser the pixels, the higher the PPI (pixel per inch), the finer and sharper the screen looks.
On Mac/Windows, you can set the resolution of the screen display. By default, the Mac has half the device resolution and its DPR = 2, which means that the length and width are 2 pixels to 1 pixel, so 2880 physical pixels really only represent 1440 logical pixels:
So our question is, how do I draw a 0.5px edge on the HD screen? 0.5px is equivalent to 1px of the hd screen’s physical pixels. The goal is to make it look a little thinner on the HD screen and have a little better effect, such as thinner dividing lines.
We’ve already talked about this in The 1px Solution for Retina again, so let’s get this straight again.
Theoretically, the minimum unit of px is 1, but there are a few exceptions, and high definition displays are one of them. The HD screen can indeed draw 0.5px, and the contrast effect is as follows:
If we set 0.5px directly, it will behave differently in different browsers, using the following code:
<html>
<head>
<meta charset="utf-8">
<style>
.hr {
width: 300px;
background-color: # 000;
}
.hr.half-px {
height: 0.5 px.;
}
.hr.one-px {
height: 1px;
}
</style>
</head>
<body>
<p>0.5 px.</p>
<div class="hr half-px"></div>
<p>1px</p>
<div class="hr one-px"></div>
</body>
</html>Copy the code
The test results on different browsers on the PC are as follows:
Chrome rounded off 0.5px to 1px, whereas Firefox/Safari can draw edges of half a pixel, and Chrome will treat edges less than 0.5px as 0, whereas Firefox will treat edges less than 0.55px as 1px. Safari treats no less than 0.75px as 1px, and further viewing IOS on the phone, Chrome will draw an edge of 0.5px, while Android (5.0) native browsers won’t. So going straight to 0.5px will vary a lot from browser to browser, and we’ll see that different browsers on different systems do different things with the decimal point px. So if we set it to decimals of px including width and height, it’s actually not very reliable, because it varies from browser to browser.
The second method you can think of is scaling. Can you set 1px and then scale 0.5?
<style>
.hr.scale-half {
height: 1px;
transform: scaleY(0.5);
}
</style>
<p>1 px + scaleY (0.5)</p>
<div class="hr scale-half"></div>Copy the code
The effect is shown in the figure below:
We found that Both Chrome and Safari went virtual, and only Firefox was perfectly realistic and fine-grained, with the same effect as if we had set it to 0.5px. So using Transform: Scale will cause Chrome to become virtual, and the thickness will barely change. But if you add transform-origin: 50% 100% :
.hr.scale-half {
height: 1px;
transform: scaleY(0.5);
transform-origin: 50% 100%;
}Copy the code
It’s perfect. Here’s what Chrome looks like:
In addition to this method, we also thought of using REM for scaling when doing mobile, but in fact the REM scaling will still be converted to px, so it is the same as using 0.5px directly.
What else is there to do? You can also use the linear gradient, as shown in the following code:
<style>
.hr.gradient {
height: 1px;
background: linear-gradient(0deg, #fff, #000);
}
</style>
<p>linear-gradient(0deg, #fff, #000)</p>
<div class="hr gradient"></div>Copy the code
Linear gradient(0deg, # FFF, #000) The gradient is from bottom to top, from white # FFF to black #000, and is linear. On a HD screen, a 1px logical pixel represents a 2px physical pixel. Because of the linear gradient, the first pixel can only be # FFF and the remaining pixel can only be #000. The logical analysis is perfect, but the actual effect is as follows:
We found that this method was not perfect on all browsers, the effect was all virtual, and still a little short of the perfect 0.5px. The effect is similar to that of Scale 0.5, which is made thinner by blurring the lines.
There is another method, using BoxShadow, as shown in the following code:
<style>
.hr.boxshadow {
height: 1px;
background: none;
box-shadow: 0 0.5 px. 0 # 000;
}
</style>
<p>Box-shadow: 0 0.5px 0 #000</p>
<div class="hr boxshadow"></div>Copy the code
Set the second parameter of box-shadow to 0.5px, which means that the vertical offset of the shadow is 0.5px. The effect is as follows:
This method works perfectly in Both Chrome and Firefox, but Safari doesn’t support boxshadow sizes smaller than 1px, so it doesn’t show up at all.
You can also use SVG, using attributes like stroke in SVG to make 1px a physical pixel instead of 1px on the HD screen. The following code looks like this:
<style>
.hr.svg {
background: none;
height: 1px;
background: url("data:image/svg+xml; utf-8,
");
}
</style>
<p>svg</p>
<div class="hr svg"></div>Copy the code
Set the background to an SVG file. The SVG copy looks like this:
<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='1px'>
<line x1='0' y1='0' x2='100%' y2='0' stroke='# 000'></line>
</svg>Copy the code
The default strok-width =”1″ is 1px of the physical pixel, equivalent to 0.5px of the HD screen. You can also use the SVG rect element to draw a line. In Chrome and Safari it looks like this:
This solution is also perfect, but it dies in Firefox because firefox background-image only supports named colors in SVG, such as “black”, “red”, etc. If you change the #000 in the SVG of the above code to black, it will be displayed, but this is not flexible. Otherwise, we would have to convert SVG to Base64. Let’s convert SVG content to Base64 (find some online tools). For comparison:
.hr.svg {
background: url("data:image/svg+xml; utf-8,
");
background: url("data:image/svg+xml; base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMDAlJyBoZWlnaHQ9JzFweCc+PGxpbmUgeDE9JzAnIHkxPScwJ yB4Mj0nMTAwJScgeTI9JzAnIHN0cm9rZT0nIzAwMCc+PC9saW5lPjwvc3ZnPg==");
}Copy the code
This will also work perfectly in Firefox.
In fact, the demand of 0.5px should be more common in mobile terminals. Compare the performance of the above five methods in IOS and Android, as shown in the figure below:
On IOS, Safari and Chrome work the same, with the 0.5px set working best, while Android’s box-shadow works best (try 5 and 7), and SVG/Transform works perfectly on both IOS and Android devices. Readers can go to this page and see what works best on your device.
Combined with the above, we preliminarily draw the following conclusions:
Another advantage of using SVG over such methods as box-shadow is that you can draw arbitrary shapes, such as quadrilateral and rounded corners, with the help of SVG elements.
Finally, there is a universal way to control the viewport, which is usually set to 1 in the shift development:
<meta name="viewport" content="width=device-width,initial-sacle=1">Copy the code
Width =device-width specifies the width of the viewport window to the width of the device, which is usually the physical width. The default zoom ratio is 1. For example, the iPhone 6 portrait width is 750px, its DPR is 2, and 2px is 1px, so the viewport width becomes 375px. In this case, the 0.5px edge uses the method we discussed above.
But you can change the scale to 0.5:
<meta name="viewport" content="Width = device - width, initial - sacle = 0.5">Copy the code
In this case, the viewport width will be the original 750px, so 1px will still be 1px, and it will be fine, but this also means that the UI will have to be double the size of the image, and the units of the whole aspect will be double the size.
On devices with DPR = 3, such as the iPhone X and some Android phones, you need to set scale to 0.333333, which is a triple draw.
So, after discussing some concepts of pixels and viewports, In this paper, we introduce and compare several methods to draw 0.5px on the HD screen. We can directly set the border to 0.5px, set the vertical offset of the box-shadow to 0.5px, use the linear gradient, and use the transform: ScaleY (0.5) method, using SVG method. It turns out that transfrom Scale /SVG is the most compatible and effective method. SVG can support complex graphics, so if viewport is 1, you can use Transform /SVG to draw 0.5px, and if viewport is not 1, you can use Transform /SVG to draw 0.5px. So I can just draw 1px.