The story background

Recently, during the development of mobile terminal project, the product proposed a requirement of “custom page”. At the beginning, DevTools did smoothly, but when I submitted to the test environment and accessed the page using a different real machine, I found a serious problem: It’s amazing that android’s high magnification screen displays custom page component spacing much larger than iPhone’s (component spacing controlled by JS code style), while internal component styling doesn’t differ much between the two (component internal styling controlled by CSS code). Start climbing the pit.

The style adaptation scheme of our mobile terminal project uses lib-flexible scheme, so the lib-flexible attribute method px2REM is used when JS is used to control the style style. Therefore, the following processing methods are used to deal with the spacing between components:

Const {margin: {top = 0, right = 0, bottom = 0, left = 0}} = data // left = right; // Top and bottom represent margins, Use margin - * or [top] | bottom (top | suction bottom layout) set const _px2rem = (pxValue) = > {const DPR = window. The lib. Flexible. The DPRreturn window.lib.flexible.px2rem(pxValue / 1 * dpr)
}
this.style['padding-left'] = `${_px2rem(left)}rem`
this.style['padding-right'] = `${_px2rem(right)}rem`
if (this.fixed) {
  if (this.fixed.type === 'top') {
    this.style.top = `${_px2rem(top)}rem`
  } else {
    this.style.bottom = `${_px2rem(bottom)}rem`
  }
} else {
  this.style['margin-top'] = `${_px2rem(top)}rem`
  this.style['margin-bottom'] = `${_px2rem(bottom)}rem`
}
Copy the code

Those of you familiar with lib-flexible can see the problem at a glance:

    const dpr = window.lib.flexible.dpr
    return window.lib.flexible.px2rem(pxValue / 1 * dpr)
Copy the code

The lib-flexible source code contains a section to retrieve and set window.lib.flexible. DPR:

if(! dpr && ! scale) { var isAndroid = win.navigator.appVersion.match(/android/gi); var isIPhone = win.navigator.appVersion.match(/iphone/gi); var devicePixelRatio = win.devicePixelRatio;if(isIPhone) {// On iOS, use 2x for screens 2 and 3, and 1x for the restif(devicePixelRatio >= 3 && (! dpr || dpr >= 3)) { dpr = 3; }else if(devicePixelRatio >= 2 && (! dpr || dpr >= 2)){ dpr = 2; }else{ dpr = 1; }}else{// For other devices, still use 1 times DPR = 1; } scale = 1 / dpr; }Copy the code

Apparently, Lib-Flexible took all our Android high-power phones as // other devices and still used the 1x solution. Modification scheme is very simple, is in the judgment of mobile phone models, the android device also can be combined with: if (isIPhone | | isAndroid) {… }, the above “magic phenomenon” immediately “back to normal”.

As I have been developing Java Web projects for a long time before, I seldom touch the development of mobile projects. Although I have been developing mobile projects for a long time now, THERE are still a lot of things I don’t know about mobile projects, such as the pit of Lib-Flexible, which is unforgettable after I stepped on it.

Therefore, I made up my mind to understand the implementation of lib-flexible and the adaptation of mobile terminal, which is a mysterious and mysterious power to me. Therefore, I read a lot of excellent articles and related materials about mobile terminal adaptation on the Internet. After a lot of effort, I finally understand the basic idea of mobile terminal adaptation and the realization principle of various solutions. Here I am especially grateful to @Conardli for his article about mobile terminal adaptation. It opened the door to a new world of “mobile adaptation”.

This article complements and expands on what you need to know about mobile adaptation in more detail to delve into the fundamentals of “mobile adaptation” and try to make sense of concepts that seem unrelated but have a lot of connections.

Article content text is more, please read patiently, maybe you have a different harvest and wonderful discovery, I hope this article can help you!

A,”

We generally use inches to describe the physical size of a screen, such as 17 inches for a computer monitor, 6.3 inches for a mobile phone display, etc. Note that this size refers to the diagonal length of the screen



1 inch = 2.54 cm

Ii. Resolution

Resolution is usually divided into display resolution and image resolution

  1. Display resolution (screen resolution) is the precision of the image on the screen, which refers to how many pixels the display can display
  2. Image resolution is the number of pixels per inch.

    ppi(pixels per inch) anddpiDots per inch are the two units we most commonly use to describe resolution; Actually,ppianddpiThere’s a lot of mixing going on. But there are differences in the fields they use. Technically speaking, pixels exist only in computer displays, and dots only in printing or printing.

    Let’s talk about pixels in the display world.

2.1 pixels

A pixel is a small square that has both position and color. Electronic screens (cell phones, computers) are made up of squares that have a specific position and color.


2.2 Physical Pixels

  1. Physical pixels are equivalent to device pixels (dp:device pixelAs the name suggests, a display screen is made up of physical pixels. By controlling the color of each pixel, the screen displays a different image. The physical pixels on the screen are fixed from the day it leaves the factorypt
  2. Among them, we usually say monitor resolution, actually refers to the desktop set resolution, not the physical resolution of the monitor

2.3 Device independent pixels

At the beginning of the emergence of smart phones, the screen density of mobile devices was very low. For example, the resolution of iPhone3 was 320×480. On the screen of iPhone3, the content we saw was “real”, 1px = 1px, and the screen of iPhone3 could only display one 320px element at most. But if you look closely, you will find that there are many tiny glowing dots on the screen of iPhone3, also known as “graininess”. These glowing dots are the actual pixel physics units we mentioned above, also known as physical pixels. As technology evolves, so do screens. Soon, higher-resolution screens were born, and jobs unveiled the iPhone4 on June 8, 2010, which had 640 by 960 resolution, exactly double the iPhone3’s. However, iPhone4 and iPhone3 are the same size, both 3.5 inches, so in the case of the same physical size, how did iPhone4 manage to use twice the resolution of this 3.5 inch screen?






iPhone4
Retina Display



iPhone4
2x2



DIP
DP



iPhone X
375x812
iPhone X

2.3 Device Pixel Ratio (DPR)

Device Pixel Ratio (DPR) is the ratio of physical pixels to individual pixels on the device.

On the Web, the browser provides us with window.devicePixelRatio to help us get the DPR. In the CSS, you can use media to query min-device-Pixel-ratio to distinguish DPR:

@media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2){ }
Copy the code

In fact, device pixel ratio didn’t exist until Apple introduced retina screens, because until then, mobile devices used physical pixels directly for display. Next, Android uses other technical solutions to achieve screens with a DPR greater than 1, but the principle is similar. Because Android has so many screen sizes and a wide range of resolutions, unlike Apple, which only has its own set of devices and sizes. Therefore, to ensure the display effect of various devices, Android divides devices into several sections according to their pixel density:

Of course, all Android devices may not strictly follow the above resolution, each type may correspond to several different resolutions, so each Android phone can determine its OWN DPR based on a given range and thus have a similar display. Of course, only similar, due to the differences in size and resolution of each device, device independent pixel will not be completely equal, so various Android devices still can not be completely equal in display.

2.4 CSS Pixels (PX)

CSS pixels are virtual pixels that can be understood as “intuitive” pixels, abstract units used by CSS and JS. All lengths in the browser are in CSS pixels, and CSS pixels are in px units.

In the CSS specification, units of length can be divided into two categories: absolute and relative. A PX is a relative unit, as opposed to a device pixel.

  1. On the same device, the physical pixel represented by each CSS pixel can be changed (i.e. the relativity of CSS pixels in the first aspect);
  2. The physical pixel represented by each CSS pixel can vary from device to device (the second aspect of CSS pixel relativity);

In the previous section, we learned that in mobile browsers, as well as some desktop browsers, the Window object has a devicePixelRatio property, which is officially defined as the ratio of device physical pixels to device independent pixels, so we can get a formula: DPR is dp divided by dips.

  1. dp(Device Pixels) : Physical pixels of a device.
  2. dips(device-independent Pixels) : Device independent pixels,Dips = CSS Pixel/scale

So without scaling, one CSS pixel is equal to one device-independent pixel.

CSS pixels are visually easy to resize. Zooming in on a browser page, for example, is a changed CSS pixel. When zoomed in twice, one CSS pixel will cover two device-independent pixels horizontally or vertically. For example, if the width of the page is 100px, when the page is doubled in size, it will occupy 200 device pixels instead of 100. If scaled down, the opposite is true, occupying only 50 device-independent pixels.


  1. Device independent pixels (dark blue background), CSS pixels (translucent background).
  2. The image on the left shows multiple CSS pixels covered by a single device pixel when the user zoomed out.
  3. The image on the right shows a SINGLE CSS pixel covering multiple device-independent pixels when the user zoomed in.

Whether CSS pixels are scaled down or enlarged, the number of pixels remains the same, say 100px. It is still 100px, but the device-independent pixels it occupies have changed (the volume has changed, the visual size has changed).

Third, the viewport

Viewport can be called “window” or “Viewport” in Chinese, and it represents the Viewport of the user’s web page.

In the reconstruction or development of web pages on mobile devices, the first thing to understand is the viewport on mobile devices. Only by understanding the concept of viewport and making clear the use of meta tags related to viewport can we better adapt our web pages to or respond to mobile devices of different resolutions.

3.1 three viewport

PPK has A tale of two Viewports — Part One, A tale of two Viewports — Part Two, Meta ViewPort. According to PPK, there are three viewports on mobile devices.

First, browsers on mobile devices think they must be able to make all web sites display correctly, even those not designed for mobile devices. However, if you use the viewport area of the browser as the viewport, because the screen of mobile devices is not very wide, so those websites designed for desktop browser display on mobile devices will inevitably be crowded because of the mobile device viewport is too narrow, and even the layout will be messed up.

If the browser’s viewport area is set to a viewPort on mobile devices, some websites will display poorly because the viewPort is too narrow, so these browsers decide to set the viewPort to a wider value by default, such as 980px. That way, even websites designed for the desktop will work on mobile browsers. PPK calls this browser’s default viewport a Layout ViewPort. Layout viewport width can be through the document. The documentElement. ClientWidth to obtain.

However, a Layout viewPort is larger than the width of the browser viewport, so we need a viewport to represent the size of the browser viewport. PPK calls this viewport a Visual ViewPort. The width of the Visual ViewPort can be obtained with window.innerWidth.

George Cummins explains the basic concept on Stack Overflow:

Think of a Layout ViewPort as a large image that doesn’t change size or shape. Now imagine that you have a smaller frame through which you can see the big picture. The small frame is made of opaque material through which you can only see part of the larger image, called a Visual ViewPort. You can zoom out and see the whole image by holding the frame, or you can zoom in and see parts of it. You can also rotate the orientation of the frame, but the size and shape of the layout viewPort will never change.

ps: visual viewporThe width of t refers to the width of the browser’s viewable area

We now have two viewPorts: Layout ViewPort and Visual ViewPort.

But browsers don’t think that’s enough, because more and more websites are individually designed for mobile devices and must have a viewport that works perfectly for mobile devices. A perfect fit is:

  1. First, users do not need to zoom and horizontal scroll bar can normally view all the content of the site;
  2. The size of the text displayed is appropriate, such as a paragraph14pxText of any size should not be too small to read on a high-density screen, ideally this one14pxThe size of the text displayed on the screen is almost the same regardless of density or resolution. Of course, not just text, but other elements like images.

PPK calls this viewport the Ideal ViewPort, the third viewport — the ideal viewport for mobile devices. Ideal ViewPort is available through window.screen.width.

There is no fixed size for the Ideal ViewPort, different devices have different Ideal Viewports.

ideal viewport
px
100%

The significance of Deal ViewPort is that websites designed for the Ideal ViewPort can be presented to users at any screen resolution without manual scaling or horizontal scrollbars.

3.2 Some details about layout ViewPort

  1. CSS layouts, especially the percentage width, are relative tolayout viewportThe width calculated (that is, the adaptive width of the top-level HTML element of the page (orwidth: 100%)layout viewportWidth), it is better thanvisual viewportMuch more wide
  2. layout viewportandvisual viewportAre measured by CSS pixels, butvisual viewportThe size changes with the zoom (if you zoom in, there will be fewer CSS pixels on the screen), andlayout viewportThe size will remain the same. (Otherwise, your pages will continue to be backstreamed and recalculated in percentage terms, which we don’t want to see)
  3. Most mobile browsers will initially display the entire page on one screen (in full zoom mode), which means they will use it by defaultlayout viewportSize so that it can completely cover the screen in full zoom mode, thereforelayout viewportandvisual viewportOf the same size
  4. layout viewportIs equal to the width and height of the content displayed on the screen in Maximum zoom mode. When the user zooms in and out,layout viewportThe dimensions remain the same
  5. Android webKit kernel and IE minimum viewport size is320pxSo when you givelayout viewportSet is less than320The browser automatically resets toideal viewportThe width of the
  6. layout viewportThe maximum width of is10000px
  7. layout viewportThe minimum width of theideal viewportOne tenth of the width of

3.3 Meta Viewport

The
element represents any metadata that can’t be represented by one of the other HTML meta-related elements. It tells the browser how to parse the page. We can use the
element’s viewport to help us set viewports, zoom, and so on to make it look better on mobile.

3.3.1 instruction

A
element can control the viewport by setting its name to viewport and then setting different directives for its content.

Each pair of key-value pairs is an instruction, and the Meta Viewport has six sets of instructions:

  1. widthSet the width of the Layout ViewPort to a positive integer, or keyworddevice-width
  2. initial-scale, sets the initial zoom value of the page to a decimal greater than 0
  3. minimum-scale, allows the user to scale to a minimum value greater than 0 decimal
  4. maximum-scale, allows the user to scale to a value greater than 0 decimal
  5. heightTo set uplayout viewportHeight, has this property, but no one seems to support it
  6. user-scalable, whether the user is allowed to zoom, the value isyesorno

These attributes can be used together, individually, or in combination, separated by commas.

3.3.2 and the Ideal Viewport have to say

Layout ViewPort can be set to ideal ViewPort by setting width=device-width (note that on iPhone and iPad both portrait and landscape, Device-width specifies the ideal Viewport width in portrait mode.

Initial-scale =1 can also change the current layout viewPort to ideal Viewport.

And to figure that out, first you have to figure out what the scaling is relative to, because the scaling here is 1, which means it’s not scaled, but it achieves the Ideal Viewport, so there’s only one answer, the scaling is relative to the Ideal Viewport, When you scale the Ideal ViewPort 100%, that’s 1, you get the Ideal ViewPort. As it turns out, it is:



initial-scale=1
viewport
ideal viewport
ideal viewport

But if thewidthinitial-scale=1At the same time, and there are conflicts?

Width =400 set the layout ViewPort width to 400px and initial-scale=1 set the Layout viewPort width to the ideal Viewport width (not necessarily 400px). So which command should the browser obey?

layour viewportThe width value specified by width andideal viewportWidth value passes through (initial-scaleA multiple of the specified value) the maximum width value after scaling!

For example, if the Ideal ViewPort is 320 and width=400 and initial-scale=1, the Layout ViewPort is 400px (400 > 320/1). When width=400 and initial-scale=0.5, the Layout ViewPort takes 640px (320/0.5 > 400 and 320/0.5 = 640) as its width.

In iPhoneX, the ideal Viewport width and device-width are 375px and initial-scale = 0.5, the visual ViewPort width is 375/0.5 = 750. So the visual ViewPort (window.innerWidth) is 750px, And layout viewport (document. DocumentElement. ClientWidth) will take 375 px and a maximum of 750 px, 750 px as width values.

And finally, to summarize, to set the current viewport width to the ideal Viewport width, you can either set width=device-width or initial-scale=1, but there’s a small flaw in both, The ideal ViewPort width is the same for iPhone, iPad and Internet Explorer. Initial-scale =1; width=device-width; IE =device-width;

3.3.3 Default values for scaling and initial-scale

As mentioned earlier, scaling is relative to the Ideal ViewPort, the larger the scale value, the smaller the width of the current viewPort, and vice versa.

For example, in iphone4, the ideal viewport is 320px. If we set the ideal viewport to initial-scale=2, the viewport will be 160px. But changing 1px to 2px does not change 320px to 640px. Instead, 1px becomes the same length as 2px without changing the actual width, so doubling the size of 1px takes 160px to fill a width that used to be 320px. Therefore, we can derive a formula:

visual viewportWidth =ideal viewportWidth/current scale value

Current scale value =ideal viewportWidth /visual viewportThe width of the

Now the default value for initial-scale, if I don’t write this property, what’s the default value?

Obviously not 1, because when initial-scale = 1, the layout viewPort width is set to the ideal ViewPort width, but the default layout viewPort width is 980px. 1024px, 800px and so on, none of these values are the width of the Ideal Viewport to begin with, so the default for initial-scale is definitely not 1. There seems to be no way to get the initial-scale default on Android devices, or it doesn’t have a default at all. It’s only going to work if you write it out. We’ll leave it there, but we’ll focus on the initial-scale default on iPhone and iPad.

Based on our tests, we can draw one conclusion on the iPhone and iPad:

On the iPhone and iPad, whatever you giveviewportIf you do not specify a default zoom value, the iPhone and iPad will automatically calculate this zoom value so that the current page does not have a horizontal scroll bar (orviewportThe width is the width of the screen).

3.4 Viewport summary

First of all, if you don’t set the Meta ViewPort tag, the default browser width on mobile devices is 800px, 980px, 1024px, etc., which is larger than the screen width. The width unit px is the CSS px, which is not the same as the actual pixels on the screen.

Second, every mobile device browser has an ideal width. The ideal width refers to the CSS width, regardless of the physical width of the device. In CSS, this width is equal to the width represented by 100%. We can use the meta tag to set the viewport width to the desired width. If we don’t know what the desired width of the device is, we can use the device-width special value. And initial-scale=1 also sets the viewport width to the desired width. So, we can use
to get an ideal viewport.

Fourth, mobile terminal adaptation

Although we can use device-independent pixels to ensure that each device looks similar on different phones, this does not guarantee that they will look exactly the same, and we need a solution to make the design work better

4.1 flexible solutions

Flexible solution is an early open source mobile terminal adaptation solution of Ali. After referring to Flexible, we uniformly use REM layout on the page.

The core code is very simple:

// set 1rem = viewWidth / 10
function setRemUnit () {
    var rem = docEl.clientWidth / 10
    docEl.style.fontSize = rem + 'px'
}
setRemUnit();
Copy the code

In the above code, the FONT size of the HTML node is set to 1/10 of the page clientWidth(layout viewport), which means that 1rem is equal to 1/10 of the page layout viewport, which means that the REST of the REM is calculated in proportion to the page.

Rem is calculated relative to the font size of the HTML node.

We by setting up the document. The documentElement. Style. FontSize can unify the entire page layout standards.

Take iPhone6 as an example: the layout viewport is 375px, so 1REM = 37.5px. At this point, the WIDTH of a UI element given is 75px (device-independent pixels), so we only need to set it to 75/37.5 = 2rem. Of course, the calculation of each layout is tedious, and we can use PostCSS’s PX2REM plug-in to help us with this process.

Let’s take a closer look at the lib-flexible source code and see that there is a paragraph that sets viewPort:

var metaEL= doc.querySelector('meta[name="viewport"]');
var dpr = window.devicePixelRatio;
var scale = 1 / dpr
metaEl.setAttribute('content'.'width=device-width, initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
Copy the code

The code is pretty straightforward, but do you know why it’s there? With everything we’ve learned about pixels and viewports, do you understand how this code works?

Let’s take a step closer look at why this code is written this way:

Mobile browsers will display the full page content on the screen by default in full zoom mode if we don’t set
The layout ViewPort is the same size as the Visual ViewPort (980px, 1024px, etc.). The default behavior varies from browser to browser.




The width=device-width directive makes the layout viewPort equal to the ideal ViewPort width, but as we mentioned earlier, If both width= XXX and initial-scale=xx appear in the viewPort setting, the browser will use the maximum value as the width of the Layout ViewPort.

Let’s go back to the 3.3.3 summary on scaling and Default Values for Initial-scale. Once again, we’ll find a formula:

Visual ViewPort width = Ideal ViewPort width/current zoom value

This means that if we set initial-scale to a decimal less than 1 on a device with a DPR greater than 1, the visual ViewPort width will be larger (compared to the Ideal ViewPort width), A layout viewPort takes the maximum value between the device-width and visual ViewPort values as its width.

The width of the visual ViewPort is the same as the width of the Layout ViewPort. The width of the visual ViewPort is the same as the width of the Layout viewPort. “, which explains why we can see the entire page without horizontal scrollbars.

Is that it? If you use a real phone to access the page, you will find that the page has been adapted to different DPR devices, that is, we wrote 80px and 160px “correctly” reflected on the display screen of the real phone, for example, we wrote 80px on the android phone with a DPR of 1, and 160px on the iPhone6. On the iPhoneX, it’s 240px (which we won’t discuss until we know it’s scaled up by rem), but the main point is that the elements displayed on the screen are all about the same size.

It means that we have achieved the goal of screen adaptation! We’ve done it! But if we consider the following question, we’ll see that it doesn’t end there:

When we develop the mobile terminal page, we will generally revert to the size of the design draft of iPhone6 (that is, the width of the design draft is 750px), and the PX in 750PX corresponds to the device pixel, namely the physical pixel, but the PX in our code (whether CSS or JS) controls THE CSS pixel, namely the logical pixel.

In other words, the maximum width of block elements in our code can only be 375px (iPhone6, for example), otherwise a horizontal scroll bar will appear if the width is larger than 375px (iPhone6 has 375 pixels), which scared me to try it out and found that the page still works on different DPR devices. The width is full, and there is no horizontal scroll bar! Why is that? It doesn’t make any sense in theory.

Considering that one CSS pixel is equal to one device-independent pixel and DPR = DP/DIps without scaling, we finally know the answer:

In fact, the initial-scale set to less than 1 decimal also has another function, which is to reduce the scale relationship between CSS pixels and DIPS. That is, after the reduction operation, one device independent pixel corresponds to multiple CSS pixels, so the reaction on physical pixels is also scaled down by N times. Finally, the goal and effect of “expanding viewport so that 1 physical pixel equals 1 CSS pixel” is achieved. (According to: DIPS = CSS pixel/scale, DPR = DP/DIps)

4.2 VH and VW scheme

Vh and VW schemes divide the visual viewport width window.innerWidth and visual viewport height window.innerHeight into 100 portions

  • vw(Viewport's width):1vwEqual to 1% of the visual viewport
  • vh(Viewport's height) :1vh1% of the height of the visual viewport
  • vmin : vwvhThe smaller value of
  • vmaxSelection:vwvhThe maximum value of

If the visual viewport is 375px, 1vw = 3.75px, and the UI is given an element 75px wide (device-independent pixels), we just need to set it to 75/3.75 = 20vw.

We don’t have to do this by ourselves, we can use the postCSS-px-to-viewPort plugin for PostCSS. When writing code, we only need to write px units according to the design drawing given by the UI.

Of course, no solution is perfect, and VW also has certain defects:

  • pxConverted tovwIt may not be completely divisible, so there is a certain pixel difference;
  • When used in containersvw.marginusingpxIt is easy to cause the overall width to exceed100vw, thus affecting the layout effect. Of course, we can also avoid, such as usingpaddingInstead ofmarginAnd combined with thecalc()Function use etc…

5. Safety zone

After the release of the iPhoneX, many manufacturers released phones with edge screens.

There are just three changes to the appearance of the phones: corners, bangs and Home indicators. To accommodate these phones, the concept of a safe zone was born: a safe zone is a viewable window area that is not subject to the above three effects. To ensure that the page looks good, we must limit the page to a safe range, but not affect the overall effect

5.1 the viewport – fit

Viewport-fit is an attribute created specifically for the iPhoneX that restricts how web pages can be displayed in secure areas.

Contain: visual window completely contains the content of the web page

Cover: The content of the web page completely covers the visual window

The default setting is auto and contain.

5.2 env, constant

We need to properly place the top and bottom within the security zone. In iOS11, two new CSS functions, env and constant, are used to set the distance between the security zone and the boundary. There can be four constants inside a function:

  • safe-area-inset-left: Distance between the security zone and the left boundary
  • safe-area-inset-right: Distance between the security zone and the right boundary
  • safe-area-inset-top: Distance between the security zone and the top boundary
  • safe-area-inset-bottom: Distance between the security zone and the bottom boundary

Note: We must specify viweport-fit to use these two functions:

<meta name="viewport" content="viewport-fit=cover">
Copy the code

Constant works on iOS < 11.2, env works on iOS >= 11.2, which means we tend to set them both, limiting pages to safe zones:

body {
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}
Copy the code

6. Frequently asked Questions

At the beginning of this article, we mentioned some common problems in the process of mobile terminal development, such as 1PX problem, UI perfect fit for all sizes of screens, hd screen picture blur and other style adaptation problems.

We can use lib-flexible or VW or VH solutions to solve the problem of “UI is perfect for screens of all sizes”.

Here we mainly explain the 1PX problem and the “hd screen picture display blurred” problem.

6.1 1 px

To accommodate screens, we write code that uses device-independent pixels to lay out the page.

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.

Solution:

  1. Media query using device pixel ratio zoom, set decimal pixels;

Advantages: simple, easy to understand disadvantages: poor compatibility, IOS8+ is currently supported, in IOS7 and below, Android is display 0px.

  • IOS8+ already supports px values with decimals,media queryThe correspondingdevicePixelRatioThere is a query value-webkit-min-device-pixel-ratio;
.border { border: 1px solid #999 }@media screen and (-webkit-min-device-pixel-ratio: 2) {. Border {border: 0.5px solid#999 }} @media screen and (-webkit-min-device-pixel-ratio: 3) {. Border {border: 0.333333px solid#999 }
}
Copy the code
  1. border-imageplan

Cons: Need to make pictures, rounded corners may appear blurred

.border-image-1px {
    border-width: 1px 0px;
    -webkit-border-image: url("border.png") 2 0 stretch;
    border-image: url("border.png") 2 0 stretch;
}
Copy the code
  • border-width: Specifies the width of the border. You can set four values: top, right, bottom, and leftborder-width: top right bottom left;
  • border-imageDistance from the top of the picture2pxCropping border picture as top border, bottom border2pxCropped as the bottom border. Cropped images 0 pixels from left and right are displayed in a stretch mode without borders.
  1. background-imageplan
.border_1px{
        @media only screen and (-webkit-min-device-pixel-ratio:2){
            .border_1px{
                background: url(../img/1pxline.png) repeat-x left bottom;
                background-size: 100% 1px;
            }
        }
Copy the code

Cons: Need to make pictures, rounded corners may appear blurred

  1. box-shadowplan

    Shadow can also be achieved, the advantage is that there is no rounded corner problem, the disadvantage is that the color is not good control
Div {-webkit-box-shadow: 0 1px 1px 1px rgba(0, 0, 0, 0.5); }Copy the code
  • box-shadowAttribute usage:box-shadow: h-shadow v-shadow [blur] [spread] [color] [inset]
  • The parameters respectively represent: horizontal shadow position, vertical shadow position, blur distance, shadow size, shadow color, change external shadow to internal shadow, the last four are optional;
  • Why is the shadow size set to negative in this example? Set to-1pxTo make the shadow size slightly smallerdivElement size so that the shadows on the left and right sides are not exposed, so that only the bottom side is shaded. To achieve the effect of a secant line (unilateral border).
  1. viewport + rem

Set the zoom so that CSS pixels are equal to real physical pixels. For example, when the device pixel ratio is 3 and we scale the page 1/3, 1px is equal to one real screen pixel.

const scale = 1 / window.devicePixelRatio;
    const viewport = document.querySelector('meta[name="viewport"]');
    if(! viewport) { viewport = document.createElement('meta');
        viewport.setAttribute('name'.'viewport');
        window.document.head.appendChild(viewport);
    }
    viewport.setAttribute('content'.'width=device-width,user-scalable=no,initial-scale=' + scale + ',maximum-scale=' + scale + ',minimum-scale=' + scale);
Copy the code

In fact, the above scheme is an earlier oneflexibleThe scheme adopted.

  1. Pseudo-classes +transformplan
.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 method can be used for various scenarios. If rounded corners are needed, just add border-radius to the pseudo-class

  1. svg

The above border-image and background-image can simulate 1px borders, but they are bitmaps and need to be imported externally. With postCSs-write-svg we can create a 1px border for SVG directly using border-image and background-image:

@svg border_1px { 
  height: 2px; 
  @rect { 
    fill: var(--color, black); 
    width: 100%; 
    height: 50%; 
    } 
  } 
.example { border: 1px solid transparent; border-image: svg(border_1px param(--color #00b1ff)) 2 2 stretch; }
Copy the code

The compiled:

.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

6.2 Image blur problem

6.2.1 Possible causes

Most of the images we use are bitmaps (PNG, JPG…) A bitmap is made up of individual pixels, each with a specific position and color value:

In theory, each pixel of the bitmap should be rendered using one physical pixel on the screen for optimal display.

On a screen with DPR > 1, a pixel of the bitmap may be rendered by multiple physical pixels. However, these physical pixels cannot be accurately assigned to the color of the corresponding bitmap pixel, and can only be approximated, so the same image will be blurred on a screen with DPR > 1:

6.2.2 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.

For example, display a double graph (@2x) on a screen with DPR =2 and a triple graph (@3x) on a screen with DPR =3.

  1. Media queries
.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

Only for background images

  1. image-set
.avatar {
    background-image: -webkit-image-set( "conardLi_1x.png" 1x, "conardLi_2x.png" 2x );
}
Copy the code

Only for background images

  1. Srcset useimgOf the labelsrcsetProperty, the browser will automatically match the best display image based on pixel density:
<img src="conardLi_1x.png"
     srcset=" conardLi_2x.png 2x, conardLi_3x.png 3x">
Copy the code
  1. Using SVG

    SVGThe full name is scalable vector graph (Scalable Vector Graphics). Instead of pixel-based bitmaps,SVGIs the shape description of the image, so it is essentially a text file, small volume, and no matter how many times the distortion.
<img src="conardLi.svg">

<img src="data:image/svg+xml; base64,[data]">

.avatar {
  background: url(conardLi.svg);
}
Copy the code

reference

  • Juejin. Cn/post / 684490…
  • www.quirksmode.org/mobile/meta…
  • www.quirksmode.org/mobile/view…
  • www.quirksmode.org/mobile/view…
  • www.cnblogs.com/zaoa/p/8630…
  • www.jianshu.com/p/31f890763…
  • www.jianshu.com/p/297da675e…
  • Blog.csdn.net/hjc256/arti…
  • www.cnblogs.com/webxu201807…
  • www.jianshu.com/p/7c5fdf90c…