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.
  • inretinaScreen on my phone,dprfor2 (iPhone 8)or3 (iPhone 8 Plus).cssWriting in the1pxThe width is mapped to a physical pixel2pxor3pxWidth.
  • Such as:iPhone6thedprfor2, the physical pixel is750 (X-axis), its logical pixel is375. In other words,1 logical pixelIn theThe x axisandyDirection, need2 physical pixelsTo display, that is:dpr=2Is 1CSSPixel byFour physical pixelsComposition.

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 7And the following devices are required to passhackCode 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 nowhackOnce in a while.
  • For old projects, it is recommended to adoptThe transform + pseudo-classes.
  • New items can be setviewportthescaleValue, this method is compatible.
  • postcss-write-svgEasy to use, only suitable for straight lines, rounded corners recommendedThe transform + pseudo-classesThe 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