专栏名称: SegmentFault思否
SegmentFault (www.sf.gg)开发者社区,是中国年轻开发者喜爱的极客社区,我们为开发者提供最纯粹的技术交流和分享平台。
目录
相关文章推荐
程序员的那些事  ·  快!快!快!DeepSeek 满血版真是快 ·  2 天前  
OSC开源社区  ·  Bun ... ·  昨天  
程序员小灰  ·  3个令人惊艳的DeepSeek项目,诞生了! ·  2 天前  
程序猿  ·  “未来 3 年内,Python 在 AI ... ·  5 天前  
程序员的那些事  ·  成人玩偶 + ... ·  5 天前  
51好读  ›  专栏  ›  SegmentFault思否

移动端页面自适应解决方案— rem 布局篇

SegmentFault思否  · 公众号  · 程序员  · 2017-12-03 08:00

正文

移动端rem自适应方案

假设设计妹妹给我们的设计稿尺寸为750 * 1340。结合网易、淘宝移动端首页html元素上的font-size属性,html5设计稿尺寸以及前端与设计之间协作流程一般分为下面两种。

一、网易做法

引入:页面开头处引入下面这段代码,用于动态计算font-size

  1. (function(doc, win) {

  2.    var docEl = doc.documentElement,

  3.        isIOS = navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),

  4.        dpr = isIOS ? Math.min(win.devicePixelRatio, 3) : 1,

  5.        dpr = window.top === window.self ? dpr : 1, //被iframe引用时,禁止缩放

  6.        dpr = 1,

  7.        scale = 1 / dpr,

  8.        resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';

  9.    docEl.dataset.dpr = dpr;

  10.    var metaEl = doc.createElement('meta');

  11.    metaEl.name = 'viewport';

  12.    metaEl.content = 'initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale;

  13.    docEl.firstElementChild.appendChild(metaEl);

  14.    var recalc = function() {

  15.        var width = docEl.clientWidth;

  16.         if (width / dpr > 750) {

  17.            width = 750 * dpr;

  18.        }

  19.        // 乘以100,px : rem = 100 : 1

  20.        docEl.style.fontSize = 100 * (width / 750) + 'px';

  21.    };

  22.    recalc()

  23.    if (!doc.addEventListener) return;

  24.    win.addEventListener(resizeEvt, recalc, false);

  25. })(document, window);

使用:

未引入前

  1. body {

  2.    width: 750px;

  3.    height: 640px;

  4. }

引入后:除以100并将px换成rem

  1. body {

  2.    width: 7.5rem;

  3.    height: 6.4rem;

  4. }

换算的依据:

  1. // 乘以100,px : rem = 100 : 1

  2. var recalc = function() {

  3.    var width = docEl.clientWidth;

  4.    if (width / dpr > 750) {

  5.        width = 750 * dpr;

  6.    }

  7.    // 乘以100,px : rem = 100 : 1

  8.    docEl.style.fontSize = 100 * (width / 750) + 'px';

  9. };

二、淘宝做法

引入:页面开头处引入下面这段代码,用于动态计算font-size,或者单独放入一个文件,引入文件也可以

  1. ;

  2. (function(win, lib) {

  3.    var doc = win.document;

  4.    var docEl = doc.documentElement;

  5.    var metaEl = doc.querySelector('meta[name="viewport"]');

  6.    var flexibleEl = doc.querySelector('meta[name="flexible"]');

  7.    var dpr = 0;

  8.    var scale = 0;

  9.    var tid;

  10.    var flexible = lib.flexible || (lib.flexible = {});

  11.     if (metaEl) {

  12.        var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);

  13.        if (match) {

  14.            scale = parseFloat(match[1]);

  15.            dpr = parseInt(1 / scale);

  16.        }

  17.    } else if (flexibleEl) {

  18.        var content = flexibleEl.getAttribute('content');

  19.        if (content) {

  20.            var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);

  21.            var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);

  22.            if (initialDpr) {

  23.                dpr = parseFloat(initialDpr[1]);

  24.                scale = parseFloat((1 / dpr).toFixed(2));

  25.            }

  26.            if (maximumDpr) {

  27.                dpr = parseFloat(maximumDpr[1]);

  28.                scale = parseFloat((1 / dpr).toFixed(2));

  29.            }

  30.        }

  31.    }

  32.    if (!dpr && !scale) {

  33.        var isAndroid = win.navigator.appVersion.match(/android/gi);

  34.        var isIPhone = win.navigator.appVersion.match(/iphone/gi);

  35.        var devicePixelRatio = win.devicePixelRatio;

  36.        if (isIPhone) {

  37.            // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案

  38.             if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {

  39.                dpr = 3;

  40.            } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {

  41.                dpr = 2;

  42.            } else {

  43.                dpr = 1;

  44.            }

  45.        } else {

  46.            // 其他设备下,仍旧使用1倍的方案

  47.            dpr = 1;

  48.        }

  49.        scale = 1 / dpr;

  50.    }

  51.    docEl.setAttribute('data-dpr', dpr);

  52.    if (!metaEl) {

  53.        metaEl = doc.createElement('meta');

  54.        metaEl.setAttribute('name', 'viewport');

  55.        metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

  56.        if (docEl.firstElementChild) {

  57.            docEl.firstElementChild.appendChild(metaEl);

  58.        } else {

  59.            var wrap = doc.createElement('div');

  60.            wrap.appendChild(metaEl);

  61.            doc.write(wrap.innerHTML);

  62.        }

  63.    }

  64.    function refreshRem() {

  65.        var width = docEl.getBoundingClientRect().width;

  66.        // 适配平板

  67.        if (width / dpr > 540) {

  68.            width = 540 * dpr;

  69.        }

  70.        var rem = width / 10;

  71.        docEl.style.fontSize = rem + 'px';

  72.        flexible.rem = win.rem = rem;

  73.    }

  74.    win.addEventListener('resize', function() {

  75.        clearTimeout(tid);

  76.        tid = setTimeout(refreshRem, 300);

  77.    }, false);

  78.    win.addEventListener( 'pageshow', function(e) {

  79.        if (e.persisted) {

  80.            clearTimeout(tid);

  81.            tid = setTimeout(refreshRem, 300);

  82.        }

  83.    }, false);

  84.    if (doc.readyState === 'complete') {

  85.        doc.body.style.fontSize = 12 * dpr + 'px';

  86.    } else {

  87.        doc.addEventListener('DOMContentLoaded', function(e) {

  88.            doc.body.style.fontSize = 12 * dpr + 'px';

  89.        }, false);

  90.    }

  91.    refreshRem();

  92.    flexible.dpr = win.dpr = dpr;

  93.    flexible.refreshRem = refreshRem;

  94.    flexible.rem2px = function(d) {

  95.        var val = parseFloat(d) * this .rem;

  96.        if (typeof d === 'string' && d.match(/rem$/)) {

  97.            val += 'px';

  98.        }

  99.        return val;

  100.    }

  101.    flexible.px2rem = function(d) {

  102.        var val = parseFloat(d) / this.rem;

  103.        if (typeof d === 'string' && d.match(/px$/)) {

  104.            val += 'rem';

  105.        }

  106.        return val;

  107.    }







请到「今天看啥」查看全文