Mobile page adaptive solution -- rem layout

Keywords: less Attribute Mobile Mac

If the UI gives us a design size of 750 * 1340.

Combined with the dynamic font size attribute, design draft size and collaboration process between the front end and design on the html element of the home page of Netease and Taobao mobile terminal, they are generally divided into the following two types:

1. Netease practice:

Introduce:

The following code is introduced at the beginning of the page to calculate font size dynamically or to put it into a file separately. You can also import a file.

(function(doc, win) {
    var docEl = doc.documentElement,
        isIOS = navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
        dpr = isIOS ? Math.min(win.devicePixelRatio, 3) : 1,
        dpr = window.top === window.self ? dpr : 1, //Disable scaling when referenced by iframe
        dpr = 1,
        scale = 1 / dpr,
        resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
    docEl.dataset.dpr = dpr;
    var metaEl = doc.createElement('meta');
    metaEl.name = 'viewport';
    metaEl.content = 'initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale;
    docEl.firstElementChild.appendChild(metaEl);
    var recalc = function() {
        var width = docEl.clientWidth;
        if (width / dpr > 750) {
            width = 750 * dpr;
        }
        // Multiply by 100, PX: REM = 100: 1
        docEl.style.fontSize = 100 * (width / 750) + 'px';
    };
    recalc()
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
})(document, window);

Use:

Before introduction:

body{
   width: 750px;
   height: 640px;
}

After introduction: divide by 100 and change px to rem

body{
   widtn: 7.5rem;
   height: 6.4rem;
}

Conversion basis:

var recalc = function(){
    var width = docEl.clientWidth;
    if(width/dpr >750){
        width = 750*dpr;
    }
    // Multiply by 100, px:rem = 100:1
    docEl.style.fontsize = 100*(width/750) +"px";
}

 

2. Taobao practices (recommended practices, especially app embedded pages)

Introduce:

The following code is introduced at the beginning of the page to calculate font size dynamically or to put it into a file separately. You can also import a file.

;
(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) {
        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) {
            // Under iOS, for 2 and 3 screens, use 2-fold scheme, and for the rest, use 1-fold scheme
            if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
                dpr = 3;
            } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {
                dpr = 2;
            } else {
                dpr = 1;
            }
        } else {
            // Under other equipment, the scheme of 1 times is still used
            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;
        // Adapter plate
        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'] = {}));

Use: (in case of less)

Before introduction:

body{
   width: 750px;
   height: 640px;
}

After introduction:

@font-size-base: 75;
boay{
   width: 750rem/@font-size-base;
   height: 640rem/@font-size-base;
}

Conversion basis:

function refreshRem(){
   var width = docEl.getBoundingClientRect().width;
    // Adapter plate
   if( width / dpr > 540){
       width = 540 * dpr;
   }
    var  rem = width / 10;
    docEl.style.fontSize = rem + 'px';
    flexible.rem = win.rem = rem;
}

Note: the premise of the above is to use less. If you don't use less, you need to calculate it manually, which can also be converted to PX: REM = 100: 1.

Use: (without less)

Before introduction:

body{
   width: 750px;
   height: 640px;
}

After introduction: divide by 100 and change px to rem

body{
   widtn: 7.5rem;
   height: 6.4rem;
}

Conversion basis:

If you want to convert to PX: REM = 100: 1, you can modify the refreshRem function above:

function refreshRem() {
    var width = docEl.getBoundingClientRect().width
    // Adapter plate
    if (width / dpr > 750) {
      width = 750 * dpr
    }
    var rem = 100 * (width / 750)       // Compared with less, changes have been made here 
    docEl.style.fontSize = rem + 'px'
    flexible.rem = win.rem = rem;
}

Please refer to: Thinking about front-end design draft and workflow from font size of Netease and Taobao Well written!

 

Posted by RobOgden on Fri, 27 Dec 2019 09:04:11 -0800