With the popularity of smart phones, there are more and more requirements for mobile web development. The first problem to be solved in mobile web development is adaptation. This article will introduce two common adaptation solutions.

viewport

When doing mobile adaptation, you first need to understand the concept of viewports and how to set viewports with the ViewPort meta tag.

1. Layout ViewPort

  • The CSS layout is calculated using the layout viewport as a reference system.
  • The default layout for mobile browsers is 980px(1024px for Blackberry and Internet Explorer)

2. Visual ViewPort

  • The visual viewport is the part of the page that is currently displayed on the screen

3. Ideal Viewport

  • The size of the ideal viewport depends on the size of the device’s individual pixels

meta

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
Copy the code
  • Width =device-width Sets the width of the layout viewport equal to the width of the device’s individual pixels, i.e. the size of the layout viewport equals the size of the ideal viewport
  • Initial-scale =1 The zoom ratio of the visual port is 1, and the size of the visual port is equal to the size of the ideal viewport

concept

1. Physical Pixels

The physical pixel, also known as the device pixel, is the smallest physical unit of the display device

2. Density independent Pixel

Device-independent pixels, also known as density-independent pixels, are virtual pixels that can be used and controlled by programs

3. The CSS pixels

CSS pixels are also called device-independent pixels, or DIPs for short. Used for layout of web pages.

4. Device Pixel Ratio

Device pixel ratio = physical pixels/device-independent pixels

Example: iPhone6

  1. Physical pixels: 750pt * 1334pt
  2. Device independent pixel: 375pt * 667pt
  3. Device pixel ratio DPR: 2

Adaptation scheme

1. Rem adaptation

Rem concept:

  • The font size of the root element is computed, that is, the font size of the HTML
  • For example: font size of HTML is 75px, 1rem is 75px

Adaptation process:

  1. Add meta tags to viewport
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
Copy the code
  1. Js gets the page width, calculates REM, and sets the FONT size of the HTML
var width = document.documentElement.clientWidth;
var rem = width / 10;
document.documentElement.style.fontSize = rem + 'px';
Copy the code
  1. Write style, calculate REM value according to design draft
  • For example, in a 750px by 1334px design, one area is 100px wide
  • CSS styles:
The demo {width: 1.33333333 rem; / * 1 / (750/10) * 100 * /}Copy the code
  • When you calculate REM, the divisor doesn’t have to be 10, it could be something else.
  • For example: var rem = width /16, width: 2.133333333rem /* 1/(750/16)*100 */
  • When calculating REM, the divisor should not be too large, because some browsers limit the minimum font size and the calculation will be biased.
  • For example, if the design is 375px wide, there is a 100px area, and the phone page is 375px wide, then the width of that area should also be 100px. When divisor is 50, rem = 7.5px, calculation style width = 1/(375/50)100 = 13.33333333 REM, since Chrome forces the minimum font value to be 12px, if the font value is lower than 12px, press 12px and display it as 12px13.33333333=160px, the display is not as expected.

2. Vw adaptation

Viewport units:

  • Vw: short for Viewport’s width. 1vw is equal to 1% of window.innerWidth
  • Vh: similar to vw, short for Viewport’s height. 1vh is equal to 1% of window. InnerHeihgt
  • Vmin: The value of vmin is the smaller value of the current VW and VH
  • Vmax: The value of vmax is the current larger value of VW and VH

Adaptation process:

  1. Add meta tags to viewport
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
Copy the code
  1. Write styles and calculate VW values from the design draft
  • For example, in a 750px by 1334px design, one area is 100px wide
  • CSS styles
The demo {width: 13.33333333; / * (1 / (750 * 1%) * 100) * /}Copy the code

Vw has compatibility issues on some equipment

Lib-flexible adaptation solution

1. Set data-dPR to HTML
  • The apple device is set to window.devicePixelRatio the devicePixelRatio obtained
  • Set this parameter to 1 for other devices
<! -- iphone6/7/8 --> <html data-dpr="2">
...
</html>
<!-- iphone6/7/8 Plus -->
<html data-dpr="3">... </html> <! -- Other devices --> < HTML data-dpr="1">... </html>Copy the code
2. Set the viewport
  • Calculate the scale ratio: var scale = 1 / DPR
  • Insert the ViewPort meta element into the document
<! -- dpr = 1--> <meta name="viewport" content="initial-scale=scale,maximum-scale=scale,minimum-scale=scale,user-scalable=no"> <! -- dpr = 2 (iphone6/7/8) --> <meta name="viewport" content="Initial - scale = 0.5, the maximum - scale = 0.5, the minimum - scale = 0.5, user - scalable = no"> <! -- dpr = 3 (iphone6/7/8 Plus) --> <meta name="viewport" content="Initial - scale = 0.3333333333, the maximum - scale = 0.3333333333, the minimum - scale = 0.3333333333, user - scalable = no">
Copy the code
3. Calculate the FONT size of the HTML
  • Get page width
var width = document.documentElement.getBoundingClientRect().width
Copy the code
  • Calculate the rem
var rem =  width / 10
Copy the code
  • Sets the font size for HTML
document.documentElement.style.fontSize = rem + 'px';
Copy the code

Example:

The design draft

  • The design is 750px by 1334px
  • One area is 750px wide and 120px high, with a background image with text centered vertically up and down, and a font size of 28px

style

[data-dpr="1"] .demo{
	font-size: 14px;
}
[data-dpr="2"] .demo{
	font-size: 28px;
}
[data-dpr="3"] .demo{
	font-size: 42px;
}
.demo{
	width: 10rem; / * 750 / (750/10) * /
	height: 1.6 rem; / * 120 / (750/10) * /
	line-height: 1.6 rem;
	text-align: center;
	vertical-align: middle;
	background: # 000 url('./img/[email protected]') no-repeat;
	background-size: cover;
	color: #fff;
}
[data-dpr="3"] .demo{
	background-image: url('./img/[email protected]');
}
Copy the code
  • In practice, you can use Sass, LESS, and PostCSS to automatically convert REM
  • PostCSS plugin: PostCSS-px2REM-dPR

Lib – flexible source code

; (function(win, lib) {
    var doc = win.document;
    var docEl = doc.documentElement;
    var metaEl = doc.querySelector('meta[name="viewport"]');
    var flexibleEl = doc.querySelector('meta[name="flexible"]');
    var dpr = 0;
    var scale = 0;
    var tid;
    var flexible = lib.flexible || (lib.flexible = {});

    if (metaEl) {
        console.warn('Scaling will be set based on existing meta tags');
        var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
        if (match) {
            scale = parseFloat(match[1]);
            dpr = parseInt(1/ scale); }}else if (flexibleEl) {
        var content = flexibleEl.getAttribute('content');
        if (content) {
            var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
            var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
            if (initialDpr) {
                dpr = parseFloat(initialDpr[1]);
                scale = parseFloat((1 / dpr).toFixed(2));
            }
            if (maximumDpr) {
                dpr = parseFloat(maximumDpr[1]);
                scale = parseFloat((1 / dpr).toFixed(2)); }}}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 2 and 3 screens, and 1x for the rest
            if (devicePixelRatio >= 3&& (! dpr || dpr >=3)) {
                dpr = 3;
            } else if (devicePixelRatio >= 2&& (! dpr || dpr >=2)){
                dpr = 2;
            } else {
                dpr = 1; }}else {
            // For other devices, use the same 1 times scheme
            dpr = 1;
        }
        scale = 1 / dpr;
    }

    docEl.setAttribute('data-dpr', dpr);
    if(! metaEl) { metaEl = doc.createElement('meta');
        metaEl.setAttribute('name'.'viewport');
        metaEl.setAttribute('content'.'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
        if (docEl.firstElementChild) {
            docEl.firstElementChild.appendChild(metaEl);
        } else {
            var wrap = doc.createElement('div'); wrap.appendChild(metaEl); doc.write(wrap.innerHTML); }}function refreshRem(){
        var width = docEl.getBoundingClientRect().width;
        if (width / dpr > 540) {
            width = 540 * dpr;
        }
        var rem = width / 10;
        docEl.style.fontSize = rem + 'px';
        flexible.rem = win.rem = rem;
    }

    win.addEventListener('resize'.function() {
        clearTimeout(tid);
        tid = setTimeout(refreshRem, 300);
    }, false);
    win.addEventListener('pageshow'.function(e) {
        if (e.persisted) {
            clearTimeout(tid);
            tid = setTimeout(refreshRem, 300); }},false);

    if (doc.readyState === 'complete') {
        doc.body.style.fontSize = 12 * dpr + 'px';
    } else {
        doc.addEventListener('DOMContentLoaded'.function(e) {
            doc.body.style.fontSize = 12 * dpr + 'px';
        }, false);
    }


    refreshRem();

    flexible.dpr = win.dpr = dpr;
    flexible.refreshRem = refreshRem;
    flexible.rem2px = function(d) {
        var val = parseFloat(d) * this.rem;
        if (typeof d === 'string' && d.match(/rem$/)) {
            val += 'px';
        }
        return val;
    }
    flexible.px2rem = function(d) {
        var val = parseFloat(d) / this.rem;
        if (typeof d === 'string' && d.match(/px$/)) {
            val += 'rem';
        }
        return val;
    }

})(window.window['lib'] | | (window['lib'] = {}));
Copy the code