The specific idea of adaptation: equal ratio scaling

Isometric scaling is when a designer creates a set of drawings based on a single size, and a developer creates 100% of the page based on the drawings. The visual scale is exactly the same on different screens. The following picture is an example. Although the screen size is different, the visual effect of the same page is exactly the same, and the page content is equally scaled.The biggest advantage of this approach is that it is simple and controllable. Designers can have absolute control over the display effect of mobile phones with different screen sizes. Test engineers don’t have to worry about missing a certain model and not finding it. Development engineers can also meet any scenario with a set of code. Hello, hello, hello, everyone.

Of course, this “lazy” adaptation is not perfect. Bigger screens are meant to show more content, not bigger text and pictures. On the flip side, if the text image looks reasonably presentable on the IPhone12 Max Pro, it will look like an ant on the IPhone 6s.

In the next part, I will introduce specific schemes of proportional scaling adaptation: 1. Dynamic REM scheme; 2. 2. Vw adaptation scheme.

Front knowledge

Before introducing mobile adaptation, it is important to understand the following basic concepts (terms) :

Physical Pixel

Physical pixel, also known as device pixel, is the tiniest physical component in the display device. Each pixel can be set to its own color and brightness depending on the operating system. It’s the tiny distance between the pixels on these devices that tricks us into seeing images.

Density independent Pixel

Device-independent pixels are also called density-independent pixels, or logical pixels. It can be thought of as a point in a computer coordinate system that represents a virtual pixel (such as a CSS pixel) that can be used by a program and then converted into a physical pixel by the relevant system.

The density of the screen

Screen density is the number of pixels that exist on the surface of a device, usually measured in pixels per inch (PPI).

Device Pixel Ratio

DevicePixelRatio (DPR) is the ratio of device pixels to CSS pixels when the default zoom is 100%. Its value can be calculated by the following formula:

Device pixel ratio = physical pixels/device-independent pixels

In JavaScript, you can get the DPR of the current device using window.devicepixelRatio. In the CSS, media query can be performed using -webkit-device-pixel-ratio, -webkit-min-device-pixel-ratio, or -webkit-max-device-pixel-ratio. For devices with different DPR, Do some style adaptation (for webKit-kernel browsers and WebViews only).

In earlier mobile devices, there was no concept of DPR. With the development of technology, the screen density of mobile devices is getting higher and higher. Starting with the iphone4, apple introduced the so-called retina display. It is called a retina screen because the PPI(screen pixel density) is so high that the human retina cannot distinguish pixels on the screen. The iphone4 has doubled the resolution, but the screen size has not changed, which means there are twice as many pixels on the same size screen, so DPR = 2.

Therefore, we can feel that in the mobile era screen adaptation in addition to Layout, but also take into account the picture adaptation, because it directly affects the page display quality.

Meta tags

There are many types of
tags, but the focus here is on the Viewport meta tag, which tells the browser how to properly render the Web page, and you need to tell it how big the window is. To develop a mobile page, we need to set the meta tag as follows:

The ratio and maximum ratio of web pages are set to 100%.

Rem unit is used for mobile adaptation

What is REM?

The W3C website describes REM as “font size of the root Element”.

In other words, when we specify a 2rem font size for an element, we say that the font size of the element is twice the size of the root element. If the HTML font size is 12px, then the 2rem font size is 24px. Once we set the font size of the root element for each screen, other elements that already use REM units will show their size accordingly.

Principle of REM scheme

The rem scheme basically divides each different screen into the same number of blocks, so that the same element occupies the same proportion of space on different screens. For example, if our design is 750px wide and we divide the page into 10 sections, THEN REM =75px. If one div is 75px wide, it will be exactly 1rem. That is, divide the 750px screen into 10 sections, one of which is the width of the div. All you need to do is make sure that the div takes up a portion of the bottom width of each screen. So the only thing we need to do is figure out how wide the next screen is on different screens, how many px is one rem on different devices? It’s very easy to calculate, the document. The body. Can calculate clientWidth / 10. Rem = Screen width (clientWidth) Screen REM \ FRAc {width}{rem} = Rem design text width = screen REM screen width (clientWidth) It is clear from this formula, the core idea is to divide different screens into the same number of copies, in the design of a copy, It should be on all screens.

  1. The viewport configuration

<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;" >

Set scale to fixed 1 times the viewport size. You can also scale the viewport according to the value of DPR, as follows:

/ / below is based on equipment DPR set viewport var DPR = window. DevicePixelRatio | | 1 var scale = 1 / DPR viewport. The setAttribute (" content ", "width=device-width" + ",initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no" )Copy the code
  1. To set the REM reference value, the core code is as follows
/ / set 1 rem = logic (device independent pixel) / 10 pixels function setRemUnit () {var rem = document. DocumentElement. ClientWidth / / / 375/10 = 10 37.5 docel.style.fontsize = rem + 'px'} 7setRemUnit()Copy the code

Lib – flexible principle

Flexible scheme is a mobile terminal adaptation scheme summarized by Handout after years of exploration and actual combat. It uses REM for layout adaptation. The solution is to dynamically rewrite meta tags using JS. Lib-flexible will automatically add a
tag to the HTML head and automatically set the HTML font size to the screen width divided by 10, i.e. 1rem equals the font size of the HTML root node. If the width of the design is 750px, then 1rem should equal 75px. If the width of an element is 150px, the CSS defines the width of the element as width: 2rem. The code looks something like this:

var metaEl = doc.createElement('meta');
var scale = isRetina ? 0.5:1;
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
if (docEl.firstElementChild) {
    document.documentElement.firstElementChild.appendChild(metaEl);
} else {
    var wrap = doc.createElement('div');
    wrap.appendChild(metaEl);
    documen.write(wrap.innerHTML);
}
Copy the code

What is DPR for in Lib-flexible?

To solve the “extreme 1px” problem. Let me show you this picture again:

On Retina screens, one CSS pixel actually corresponds to four physical pixels (DPR =2). When we draw a 1px line on the screen, the Retina screen is actually 2 physical pixels wide. To achieve “extreme 1px”, we want to draw a thin line 1 physical pixel wide on the Retina screen.

The principle is actually very simple, for the device with DPR =2, set the REM value to twice the normal value, use 1px to represent the “extreme line”, and then shrink the page by 2 times, so that the 1px line becomes “0.5px”, which is actually 1 physical pixel.

Similarly, for devices with DPR =n, set the REM value to n times normal and scale the page n times.

Lib-flexible is now available in two versions, master and 2.0. In the master version, regex is used to determine the system type (IOS/ Android), but DPR is only used for IOS. For Android phones, DPR is set to 1. There are actually a lot of problems with using REM with DPR scaling. The most obvious example is the confusion of DPR of Android phones. For example, a certain mobile phone of VIVO even has the situation that DPR is a decimal number (as we introduced above, the DPR of one CSS pixel corresponds to the number of physical pixels, obviously it is impossible to have the situation of decimal places). So using zoom to achieve “extreme 1px” compatibility is not very good.

The practice of some teams is to report the models with problems in DPR setting and collect them into a whitelist, and then individually adapt the models with problems in lib-flexible according to the whitelist. However, this small team with average workload does not have the energy to do so…

So we can see that version 2.0 has abandoned this practice.

// Detect 0.px supports docEl = document.documentElement; if (dpr >= 2) { var fakeBody = document.createElement('body') var testElement = document.createElement('div') testElement.style.border = '.5px solid transparent' fakeBody.appendChild(testElement) docEl.appendChild(fakeBody) if (testElement.offsetHeight === 1) { docEl.classList.add('hairlines') } docEl.removeChild(fakeBody) }Copy the code

As you can see, this version tested the device. If the device supports 0.5px writing, Hirlines div {border-width: 0.5px} is used to add a hairlines class to the HTML element.

Lib – flexible source code

Other solutions to 1px problems

Just set it to 0.5px

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. So you need JavaScript to check if the browser can handle a 0.5px border, and if so, add a class to the HTML tag element. That’s the idea behind Lib-Flexible version 2.

Zoom using CSS pseudo-elements ::after + transfrom

Why pseudo-elements? Because the pseudo-element ::after or ::before is independent of the current element, it can be scaled independently without affecting the element’s own scaling. A more detailed approach is to increase the media query at the same time for different DPR devices, zoom in different proportions.

.border-1px:after { content: ''; position: absolute; box-sizing: border-box; top: 0; left: 0; width: 200%; height: 200%; border: 1px solid #000; border-radius: 4px; - its - transform: scale (0.5); The transform: scale (0.5); -webkit-transform-origin: top left; }Copy the code

Both the Vant component library and Ant-Design-Mobile use this approach.

postcss-write-svg

PostCSS plugin postCSS-write-SVG to help us. 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

Pros and cons of REM

disadvantages

  • It doesn’t work well on weird DPR devices, such as some of Huawei’s high-end models with rem layouts.
  • There are two ways to set the root font size. One is media query. Advantages: No additional USE of JS to change the font of HTML. The other is js to dynamically change the HTML font, advantages: continuous; Disadvantages: not as good as directly writing media query experience;
  • Css3 calC not supported requires a lot of dense @media hacks;
  • Using iframe references can also cause problems;
  • I think the most important thing is that it’s not VW. Why do you say so? Because we’ve been using hacks to simulate VW features with REM, which is CSS native support.

advantages

  • With REM you can set the maximum width of the page; with VW you can’t. The advantage of limiting the maximum width is that mobile pages on very wide screens, such as PCS and pads, have a similar experience to those on phones, without making elements too wide and distorted. This is how a mobile page would look on a PC using lib-flexible, which limits the maximum width to 540px * DPR: maximum width, and unrestricted: unrestricted maximum width.

About the vw

GitHub at Lib-Flexible has announced that it will stop using the REM scheme because it has found a new and better global reference unit: VW. What is VW?

1vw = 1% of window width

  • For PC: This viewable area iswindow.innerWidth/window.innerHeightThe size of is simply illustrated as follows
  • For mobile: this viewable areadocument.documentElement.getBoundingClientRect().width/document.documentElement.getBoundingClientRect().height(width set in viewPort of the mate tag)

Vw is relative to the viewport width, so 10VW is 10% of the viewport width. If you change the width of the browser window, the size of the element responds to the change. This unit seems to be tailor-made for us. First of all, it’s essentially a percentage unit; Second, it is a global unit that is directly related to screen width.

If the design is 750px wide, 100vw = 750px, 1vw = 7.5px. Then we can directly convert the px value on the design drawing into the corresponding VW value. If you don’t want to do it yourself, you can use the PostCSS plugin postCSs-px-to-viewport, which allows you to write px directly in your code.

{ loader: 'postcss-loader', options: { plugins: ()=>[ require('autoprefixer')({ browsers: ['last 5 versions']}), require('postcss-px-to-viewport')({viewportWidth: 375, // viewportHeight: 1334, // Viewport height (number) unitPrecision: 3, // Set the reserved decimal number (number) viewportUnit: 'vw', // Set the unit to be converted (string) selectorBlackList: ['.ignore', '.hairlines'], // Class name (array) minPixelValue: 1, // Set the minimum pixel value (number) to replace mediaQuery: False // Allow conversion px (true/false)})]}Copy the code

What about VW support in mobile browsers? According to thecaniuse.com:

Both iOS 8+ and Android 4.4+ support VW, while current mobile apps typically support iOS 9+ and Android 5+. So, in practice, using VW units is perfectly feasible. This is also the reason why the mobile Taobao team officially turned to VW unit adaptation in early 19th.

Vw and Rem work together

  • You can dynamically change the size of the root element by giving it vw units that change with the viewport.
  • Limit the maximum and minimum font size for the root element, along with the body plus the maximum and minimum widths.
@media screen and (max-width: 320px) {
      html {
          font-size: 64px;
      }
}
@media screen and (min-width: 540px) {
        html {
            font-size: 108px;
        }
 }
html {
  font-size: 20vw;
}
.box {
    max-width: 540px;
    min-width: 320px;
}

Copy the code

This scheme is suitable for scenarios where there are many visual graphic components, or where there is a certain relative dependence of component positions. And you can set the maximum and minimum width. Jingdong (m.jd.com/) mobile terminal is using this adaptation scheme.

Px + percentage fit

It is not necessary to use relative length units on mobile devices, traditional responsive layouts are still a good choice, especially in news, community and other readable scenes where using PX units directly can create a better experience. The PX scheme allows larger screen phones to display more content, which is more in line with people’s reading habits. Ctrip (m.ctrip.com/html5/), Tencent News (www.qq.com/), Zhihu (www.zhihu.com/) and others have adopted this approach

Rethinking mobile adaptation

1 mobile adaptation is rem or VW?

Not all scenes are suitable for REM or VW adaptation.

  • The essence of VW and REM adaptation is equal scale scaling, which makes the page have the effect similar to vector picture scaling under different screen sizes, and ensures the size scaling proportion and position between page elements.
  • The adaptation scheme of proportional scaling is suitable for mobile terminal pages where there are many types of visual components and visual design is strongly dependent on the relative relationship of element position. Basically, most pages can be adapted with two schemes.
  • However, if there is a lot of text content, we want to guide users to immerse themselves in more content rather than larger content. Such equal scale scaling scheme does not meet the requirements. I recommend using PX combined with Flex and other layout methods for adaptation.

Rem should be ditched, isn’t vw fragrant?

Vw fit is not a panacea and is best used in conjunction with REM

  • The rem solution became popular in the first place because browser support for Viewport Units was not good at the time (IOS 8+, Android 4.4+ see Caniuse for ViewPort Units). In contrast, REM is much better (IOS 4.1+, Android 2.1+ see Caniuse). Therefore, for VW, it is not easy for the front end to say love you under the environment at that time.
  • With the innovation of front-end technology, the most important is the contribution of major browser manufacturers, except Opera Mini full version and IE low version, other browsers have basically supported VW.
  • The page adapted by VW has a good effect, but its layout is realized by viewport unit, and it automatically scales depending on viewport size. Whether the viewport is too large or too small, it also loses the limitation of maximum and minimum width as the viewport is too large or too small.

References:

  • Understand mobile adaptation
  • Talk about REM versus VW — REM
  • Use Flexible to achieve terminal adaptation of H5 page