Since we start with
for basic adaptation, this will result in different sizes for each layout viewport, For example, the iphone6 is 375 x 667 and the iphone6 plus is 414 x 736. And at the time of the layout of our CSS is a fixed size, resulting in different, the effect will be shown on the mobile, although we can use the equipment to ensure all equipments in different independent pixel effect similar to displayed on the phone, but it does not guarantee that they show completely consistent, we need a plan to make the design draft to get more perfect fit.

The essence of adaptation is proportional scaling.

Viewport adaptation

Change the size of the layout viewport with the meta tag. The size of the layout viewport is determined by the size of the design drawing, so that each model of the layout viewport size. For example, the current design is 375px,

<meta name="viewport" content="width=375"/>
Copy the code

This method is the simplest, but not very compatible line, generally will not be used in development.

Rem adaptation

Em and REM

  • Em: Base on the font size of the latest element.
<div class="box1">
  <div class="box2">box2</div>
</div>

<style>
 .box1{
    font-size:10px;
 }
 .box2{
    font-size:20px;
    width:10em;
 }
</style>
Copy the code

The width of box2 is 200px. If box2 does not set font size, it will be 100px based on the font size of box1.

  • Rem: Based on the font size of the root element
html{
   font-size:10px
}
Copy the code

This element can only be an HTML element.

Rem adaptation implementation

  • First, js dynamically retrieves the size of the layout viewport and sets a reasonable font size for the HTML elements.
const htmlwidth=document.documentElement.clientWidth || document.body.clientWidth; / / layout viewport size using const htmlDom = document. The getElementByTagName (' HTML ') [0]; const rem = 20; htmlDom.style.fontSize=htmlwith/rem+'px';Copy the code

Why do you do that? Before VW and VH came out, CSS did not know the width of the layout viewport, so it could not adapt each element according to the scale. The code above obtained the width of the layout viewport by changing the direction of JS. Regardless of the device, the width of the layout viewport is 20REM.

  • Then calculate a ratio of each width attribute to the layout viewport based on the design diagram to calculate the width on different devices. For example, there is a box on the design whose width is200pxThe overall size of the design drawing is375px, then:
width: (200/375)*20rem;
Copy the code

CSS itself does not support the above calculation. You can use less to calculate. For details, refer to LESS.

Vw and vh

This approach is the same as rem’s idea of matching each element by percentage based on the width of the layout viewport. However, for VW, 100VW is the width of the layout viewport. It is not necessary to obtain the width of the layout viewport through JS, we just need to calculate the overall size of the design drawing and the ratio of width of each element. For example, if the width of a box on the design drawing is 200px and the overall size of the design drawing is 375px, then:

width: (200/375)*20vh 
Copy the code

Postcss-px-to-viewport: postcss-px-to-viewport: postcss-px-to-viewport: postcss-px-to-viewport

1 px problem

On screens with a device pixel ratio greater than 1, the 1px we write is actually rendered by multiple physical pixels, which makes 1px look thick on some screens.

.border_1px:before{ content: ''; position: absolute; top: 0; height: 1px; width: 100%; background-color: #000; transform-origin: 50% 0%; } @media only screen and (-webkit-min-device-pixel-ratio:2){. Border_1px :before{transform: scaleY(0.5); }} @media only screen and (-webkit-min-device-pixel-ratio:3){. Border_1px :before{transform: scaleY(0.33); }}Copy the code

This approach can be applied to a variety of scenarios, although there are various implementations.

Graphics adapter

A bitmap pixel is the smallest unit of an image. When a bitmap pixel corresponds to a physical pixel, the image can be displayed perfectly and clearly. When a bitmap pixel occupies more than one physical pixel, the image is distorted. When a bitmap pixel occupies less than one physical pixel, the image is sharpened.

Now we have a box div with 300px width and 300px height, and an image that fills the entire div. We have an existing image that is 300 x 300(bitmap pixels), as shown in the following code:

<div>
   <img src="src">
</div>

<style>
  div{
     width:300px;
     height:300px;
  }
  img{
     width:100%;
     height:100%;
  }
</style>
Copy the code

When the device pixel ratio is 1, the picture can be displayed normally; But when the device has a pixel ratio of 2, it gets distorted. Why is that? When the device pixel ratio is 2, the actual physical pixel is 600px, and the bitmap of the image is 300 * 300 and covers the entire div, resulting in one bitmap pixel occupying two physical pixels.

The solution

In order to ensure image quality, we should render one image pixel with one screen pixel as much as possible, so we need to display images with different resolutions for different DPR screens.

Using the srcset attribute of the IMG tag, the browser automatically matches the best display image based on pixel density:

<img src="assets_1x.png"
     srcset="assets_2x.png 2x, assets_3x.png 3x">
Copy the code

If it is a background image, you can:

.avatar{ background-image: url(conardLi_1x.png); } @media only screen and (-webkit-min-device-pixel-ratio:2){ .avatar{ background-image: url(conardLi_2x.png); } } @media only screen and (-webkit-min-device-pixel-ratio:3){ .avatar{ background-image: url(conardLi_3x.png); }}Copy the code

At this point, you might be thinking that if I only used the largest bitmap pixels in the image, there would be no distortion, but that would consume resources and increase bandwidth. Not in a good way.