Recently, the company was preparing a set of mobile development templates, so I built a project with VUE-Cli4. The templates involved mobile adaptation, which I had been ignorant of before. Generally, the width of the mobile design is 750px, and since it can scroll down indefinitely, the height is dynamic, so we have to make this one design consistent across different screen widths. Specifically we talk about the page adaptation needs to solve the problem.

1. Element adaptation

Let’s say we have a logo 75px wide in the design. So how big should the logo be in proportion to each phone screen? Let’s do the math:

  • On a 375px phone, the result would be 375/750 * 75 = 37.5px
  • On a phone with 360px pixels, the result should be 360/750 * 75 = 36px
  • On a 320px phone, the result should be 320/750 * 75 = 32px

What does this algorithm mean? 375/750, the original 1px on the 750px design is 0.5px when converted to 375px, the original 75px logo on the screen is 37.5px. This is our manual calculation and then write dead PX, but there are so many screens, we can not calculate every one of them, this is certainly not scientific. So there are now two relatively common solutions to the problem. Dynamic calculation of element size in vw and dynamic calculation in REM

  • Vw: viewport width. 1VW is 1% of the viewport width relative to the viewport width. 100VW is the width of the device
  • Rem: relative to the root element of HTML font size of the unit First let’s end the rem unit layout, rem layout is very simple, and its basic principle is according to the different resolution of the screen, the size of the modified roots type dynamic, so use all of the rem unit elements along with screen size scaling, so as to achieve the effect of the adaptive. Take our logo for example: the width of our design was 750px, so on the 375px screen all the dimensions were directly divided by 2. Now I will implement the adaptation like this:
html { font-size: calc(100vw / 750); }. Logo {width: 75rem // this equals 75 * 100vw/750 = 75 * 375/750 = 37.5px}Copy the code

Where 100vw is deviceWidth, that is, 375px pixel phone or 360px pixel phone. In this way, the size of the root font font can be dynamically modified under different device widths, so as to dynamically change the size of each element. So as long as this is the case, we can directly according to the design element case? No, because the minimum font size on mobile is 8px. So 100vw/750 is not possible because you end up with a font of 0.5px, which is against the minimum font on the mobile end, so the result above is

.logo {
    width: 75rem // 75*8 = 600px
}
Copy the code

So we’re going to take this

Font-size: calc(100vw /7.5); font-size: calc(100vw /7.5); @media screen and (min-width: 320px) {font-size: 64px; } @media screen and (max-width: 540px) { font-size: 108px; }. Logo {width:.75rem // this is 75px}Copy the code

Of course, with optimization, we added a minimum and maximum width limit so that we didn’t have a problem with the larger screen

Body {max-width: 540px; max-width: 540px; min-width: 320px; }Copy the code

And the same thing with vw is equal to 1px

DeviceWidth = 320, logo = 75/320 * 100 = 23.4375 VW deviceWidth = 375, Font = 75/375 * 100 = 20vw deviceWidth = 414, font = 75/414 * 100 = 18.115942vwCopy the code

So what this formula is saying is 1vw is 1% of the page so 75/320 is how much of the page, times 100 is a percentage. Of course, you can just write functions in terms of SCSS

$vw_base: 750; 
@function vw($px) {@return ($px / 750) * 100vw;
}
.logo {
    width: vw(75px);
}
Copy the code

Second, about the 1px question you talked about

What is a 1px problem? Steve jobs first introduced the concept of Retina Display at the launch of iPhone4. In the Retina Display used by iPhone4, 2×2 pixels are used as one pixel, which makes the screen look more refined, but the size of elements does not change. Since then, high-resolution devices, one more logical pixel. The differences between the logical pixels on these devices are not huge, but they are still a little different, which is why mobile pages need to be adapted. Since logical pixels are made from physical pixels, they have a pixel ratio, device pixel ratio (DPR) = physical pixels/device-independent pixels. If iPhone 6, 7, and 8 have a DPR of 2, a single pixel on the device is 4 physical pixels, so 1px on the CSS takes up 2 physical pixels on the screen, and 0.5px is the smallest unit that can be displayed. That’s the 1px problem.

1px problem solution

Solution 1: Use CSS3 scaleY(0.5) to solve

/* border */.b-border {position: relative; } .b-border:before { content:' ';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: #d9d9d9;- its - transform: scaleY (0.5); The transform: scaleY (0.5); -webkit-transform-origin: 0 0; transform-origin: 0 0; } /* top border */.t-border {position: relative; } .t-border:before { content:' ';
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 1px;
  background: #d9d9d9;- its - transform: scaleY (0.5); The transform: scaleY (0.5); -webkit-transform-origin: 0 0; transform-origin: 0 0; } /* right border */.r-border {position: relative; } .r-border:before { content:' ';
  position: absolute;
  right: 0;
  bottom: 0;
  width: 1px;
  height: 100%;
  background: #d9d9d9;- its - transform: scaleX (0.5); The transform: scaleX (0.5); -webkit-transform-origin: 0 0; transform-origin: 0 0; } /* left border */.l-border {position: relative; } .l-border:before { content:' ';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 1px;
  height: 100%;
  background: #d9d9d9;- its - transform: scaleX (0.5); The transform: scaleX (0.5); -webkit-transform-origin: 0 0; transform-origin: 0 0; } /* Four edges */.setBorderAll {position: relative; &:after { content:' '; position: absolute; top: 0; left: 0; width: 200%; height: 200%; The transform: scale (0.5); transform-origin: left top; box-sizing: border-box; border: 1px solid#e5e5e5;border-radius: 4px; }}Copy the code

Principle: First enlarge the length and width of the pseudo-element by 2 times, then set a border, with the top left corner as the center, zoom to 0.5 times the original. At this point we can pull out the solution and call it as a common style, plus media queries for compatibility processing.

/* Four edges */.setBorderall (@border_clolor,@border_radius: 5px) {position: relative; &:after { content:' '; position: absolute; top: 0; left: 0; The transform: scale (0.5); transform-origin: left top; box-sizing: border-box; border: 1px solid @border_clolor; @media (-webkit-min-device-pixel-ratio: 1.5){width: 150%; height: 150%; The transform: scale (0.66666); border-radius: cacl(# {@ border_radius} * 1.5);} @media (-webkit-min-device-pixel-ratio: 2){ width: 200%; height: 200%; The transform: scale (0.5); border-radius: cacl(#{@border_radius} * 2);} @media (-webkit-min-device-pixel-ratio: 3){ width: 300%; height: 300%; The transform: scale (0.33333); border-radius: cacl(#{@border_radius} * 3);}}}Copy the code
Copy the code

Solution 2: Page scaling solves the problem

The idea is to make the entire page smaller by a factor of DPR and enlarge the root font by a factor of DPR. In this way, although the page is smaller, because the whole page uses REM unit, when the root font is enlarged by DPR times, the whole is enlarged, and the overall style looks the same.

For a phone with DPR =2, 1px will have 2×2 physical pixels to render, but when scaled it will actually render in 1×1 units, as shown below:

/ / get the screen width, DPR value var deviceWidth = document. The documentElement. ClientWidth, DPR = window. DevicePixelRatio | | 1; // Set the root font size to be DPR times larger // Because deviceWidth when the page is DPR times smaller, Itself to obtain the value of the DPR times / / so there is no need to be multiplied by the DPR for the document. The documentElement. Style. FontSize = deviceWidth +'px'; / / Settings page zoom document. The DPR times getElementsByName ('viewport')[0]
    .setAttribute('content'.'width=device-width; initial-scale=' + 1/dpr)
Copy the code

Finally, I recommend a few articles to you. In fact, I also read the following articles to sum up. In fact, the adaptation problem is far more than that. References and recommendations:

  • Here’s what you need to know about mobile adaptation
  • Mobile H5 solution – page adaptation
  • An H5 template out of the box