preface
In the mobile end Web development, if the border is set as 1 pixel in the UI design draft and border:1px appears in the front end during the development process, the test will find that 1px is relatively thick in the Retina display model, which is the classic 1px pixel problem on the mobile end.
The reasons causing
- Device pixel ratio:
dpr=window.devicePixelRatio
, which is the ratio of physical pixels to logical pixels of the device. - in
retina
Screen on my phone,dpr
for2 (iPhone 8)
or3 (iPhone 8 Plus)
.css
Writing in the1px
The width is mapped to a physical pixel2px
or3px
Width. - Such as:
iPhone6
thedpr
for2
, the physical pixel is750 (X-axis)
, its logical pixel is375
. In other words,1 logical pixel
In theThe x axis
andy
Direction, need2 physical pixels
To display, that is:dpr=2
Is 1CSS
Pixel byFour physical pixels
Composition.
The solution
1. 0.5 px.
plan
In IOS8+, apple series already support 0.5px, can be handled with media query.
/* this is CSS mode */. Border {border: 1px solid #999} @media screen and (-webkit-min-device-pixel-ratio: 2) { .border { border: */ @media screen and (-webkit-min-device-pixel-ratio); / / @media screen and (-webkit-min-device-pixel-ratio) 3) {. Border {border: 0.333333px solid #999}}Copy the code
On IOS7 and below and other systems like Android, 0.5px will be displayed as 0px. Then we need to figure out how to do it, and in fact find hacks.
The solution is to check with JavaScript if the browser can handle a border of 0.5px, and if so, add a class to the HTML tag element.
if (window.devicePixelRatio && devicePixelRatio >= 2) { var testElem = document.createElement('div'); testElem.style.border = '.5px solid transparent'; document.body.appendChild(testElem); if (testElem.offsetHeight == 1) { document.querySelector('html').classList.add('hairlines'); } document.body.removeChild(testElem); $(document).ready(function() {})Copy the code
Then, extremely thin border styles are easy:
div { border: 1px solid #bbb; }. Hairlines div {border-width: 0.5px; }Copy the code
At WWDC 2014, Ted O ‘Connor spoke about “Retinahairlines” : what developers should do with just 1 physical pixel borders on retina displays.
They mentioned that iOS 8 and OS X Yosemite will soon support a 0.5px border:
- Advantages: Simple, doesn’t require much code.
- disadvantages: Not compatible with Android devices,
iOS 7
And the following devices are required to passhack
Code compatibility.
2. The pseudo class +transform
Principle: Remove the border of the original element, then use :before or :after to redo the border and reduce the scale of the transform by half. The original element is positioned relative to the original element, and the new border is positioned absolutely.
Border-1px,.border-bottom-1px,.border-top-1px,.border-left-1px,.border-right-1px {position: relative; } /* Line color black */. Border-1px ::after,.border-bottom-1px::after,.border-top-1px::after,.border-left-1px::after, .border-right-1px::after { background-color: #000; } /* border-bottom-1px::after {content: ""; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; transform-origin: 0 0; } /* border-top-1px::after {content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 1px; transform-origin: 0 0; } /* border-left-1px::after {content: ""; position: absolute; left: 0; top: 0; width: 1px; height: 100%; transform-origin: 0 0; } /* Border-right-1px ::after {content: ""; box-sizing: border-box; position: absolute; right: 0; top: 0; width: 1px; height: 100%; transform-origin: 0 0; } /* border a pixel */.border-1px::after {content: ""; box-sizing: border-box; position: absolute; left: 0; top: 0; width: 100%; height: 100%; border: 1px solid gray; @media (-webkit-min-device-pixel-ratio: webkit-min-device-pixel-ratio: 2) {. Border-bottom-1px ::after,. Border-top-1px ::after {transform: scaleY(0.5); }. Border-left-1px ::after,.border-right-1px::after {transform: scaleX(0.5); } .border-1px::after { width: 200%; height: 200%; The transform: scale (0.5); transform-origin: 0 0; } /* Device pixel ratio */ @media (-webkit-min-device-pixel-ratio: 3) {.border-bottom-1px::after,.border-top-1px::after {transform: scaleY(0.333); }. Border-left-1px ::after,.border-right-1px::after {transform: scaleX(0.333); } .border-1px::after { width: 300%; height: 300%; The transform: scale (0.333); transform-origin: 0 0; <input type="button"> <input type="button"> <input type="button"Copy the code
Advantages: Supports rounded corners in all scenarios (border-radius is required for both pseudo-classes and ontology classes). Disadvantages: Also a lot of code and may require multiple layers of nesting for elements that already use pseudo-classes (such as Clearfix).
3. viewport + rem
By setting the rem reference value of the corresponding viewport, this method can write 1px as easily as before. Set meta when devicePixelRatio=2:
<meta name="viewport" content="width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
Copy the code
Set meta when devicePixelRatio=3:
< meta name = "viewport" content = "width = device - width, initial - scale = 0.3333333333333333, the maximum - scale = 0.3333333333333333, Minimum - scale = 0.3333333333333333, user - scalable = no ">Copy the code
Example verification:
<! DOCTYPE HTML > < HTML lang="en"> <head> <title> mobile 1px </title> <meta http-equiv=" content-type "Content ="text/ HTML; charset=UTF-8" /> <meta name="viewport" id="WebViewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <style> html { font-size: 11px; } body { padding: 1rem; } * { padding: 0; margin: 0; } .item { padding: 1rem; border-bottom: 1px solid gray; The font - size: 1.2 rem; } </style> <script> var viewport = document.querySelector("meta[name=viewport]"); var dpr = window.devicePixelRatio || 1; var scale = 1 / dpr; Viewport viewport.setAttribute("content", + "width=device-width," + "initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no" ); var docEl = document.documentElement; var fontsize = 10 * (docEl.clientWidth / 320) + "px"; docEl.style.fontSize = fontsize; </script> </head> <body> <div class="item">border-bottom: 1px solid gray; </div> <div class="item">border-bottom: 1px solid gray; </div> </body> </html>Copy the code
Advantages: All scenarios can be satisfied, one set of code, can be compatible with all basic layouts. Disadvantages: the old project modification cost is too large, only applicable to the new project.
4. border-image
First of all, prepare a border-image that meets your requirements. Usually, the page design draft of the mobile terminal is doubled in size. For example, in order to adapt to iPhone Retina, the resolution of the design draft is 750*1334, and the image is cut out in two times size, so that it will not be blurred and very clear on the mobile terminal. Similarly, when using border-image, make the border physical 1px as follows:
Style Settings:
.border-image-1px {
border-width: 0 0 1px 0;
border-image: url(linenew.png) 0 0 2 0 stretch;
}
Copy the code
Above, the border is set at the bottom of the border, so the image is 2px high, the top 1px color is transparent, and the bottom 1px color is the visual border color. If you need a border at both the bottom and top of the border, use the following border-image,
Style Settings:
.border-image-1px {
border-width: 1px 0;
border-image: url(linenew.png) 2 0 stretch;
}
Copy the code
So far, we’ve been able to display a 1px border on the iPhone. However, we found that this method did not display the border on the non-retina screen, so we used Media Query to make some compatibility with the following styles:
.border-image-1px {
border-bottom: 1px solid #666;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
.border-image-1px {
border-bottom: none;
border-width: 0 0 1px 0;
border-image: url(../img/linenew.png) 0 0 2 0 stretch;
}
}
Copy the code
- Advantages: Can set a single, multiple borders, no performance bottlenecks
- Disadvantages: Modify color trouble, need to replace the picture; Rounded corners require special treatment and the edges can be blurred
5. background-image
Background-image is the same as border-image. You should first prepare an image that meets your requirements:
This example is to prepare the border at the bottom
Style Settings:
.background-image-1px { background: url(.. /img/line.png) repeat-x left bottom; background-size: 100% 1px; }Copy the code
- Advantages: Can set a single, multiple borders, no performance bottlenecks.
- Disadvantages: Modify color trouble, need to replace the picture; Rounded corners require special treatment and the edges can be blurred.
6. postcss-write-svg
Using the border-image will always cost you to adjust the image every time. For these reasons, we can help with the PostCSS plugin postCSS-write-SVG. If you already have PostCSS in your project, just install the plugin in your project. Then use it in your code:
@svg 1px-border {
height: 2px;
@rect {
fill: var(--color, black);
width: 100%;
height: 50%;
}
}
.example {
border: 1px solid transparent;
border-image: svg(1px-border param(--color #00b1ff)) 2 2 stretch;
}
Copy the code
PostCSS will automatically compile your CSS for you:
.example { border: 1px solid transparent; border-image: url("data:image/svg+xml; charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='2px'%3E%3Crect fill='%2300b1ff' width='100%25' height='50%25'/%3E%3C/svg%3E") 2 2 stretch; }Copy the code
This solution is simple and easy to use, which is what I need. At present, it can basically meet the requirements I need. In the latest adaptation scheme, I also use this plug-in to deal with the problem of 1px border.
conclusion
0.5 px.
For nowhack
Once in a while.- For old projects, it is recommended to adopt
The transform + pseudo-classes
. - New items can be set
viewport
thescale
Value, this method is compatible. postcss-write-svg
Easy to use, only suitable for straight lines, rounded corners recommendedThe transform + pseudo-classes
The implementation.
Related recommendations:
Mobile 1PX solution
7 Ways to fix the 1px border on the Mobile Retina Screen
Summary of 1px border solution
Adaptive layout scheme