探讨移动端布局适配方案

Posted liuxiaodi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了探讨移动端布局适配方案相关的知识,希望对你有一定的参考价值。

一.前提知识

移动端的屏幕尺寸有多种,其中要知道几个知识

物理像素:即设计稿的尺寸

逻辑像素:实体机器的真正像素

下面是我们经常适配的屏幕尺寸

技术图片

 

 

一.rem布局

rem是以根元素字体大小作为参照的布局方式

如下

//以750px设计稿为例,物理像素是375px.设置div宽度为整个容器宽度一半
html{font-size:12px}
div{width:375/2/12 rem}

屏幕的尺寸是不同的,为了保证布局大小一致,我们需要做判断屏幕的宽度,如下例子:

技术图片

 rem布局的缺点是要根据不同的屏幕大小设置不同的根文字大小

 

 

二.vw布局

  • vw1vw 等于 window.innerWidth 1%,相当于是说vw把屏幕宽度分为了100份,1vw=1份
  • vh1vh 等于 window.innerHeight 1%

div设置为容器宽度的一半:div{width:50vw}

div设置为容器高度的一半:div{width:50vh}

div尺寸大小= 逻辑像素大小*(100/逻辑像素宽度) vw.

以750设计稿解释:375px=100vw,1px=100/375 vw,所以有div尺寸大小= 设计稿尺寸大小*(100/设计稿宽度) vw.

vw的缺点是元素尺寸每个都要去计算

 

三.rem+vw布局

vw是动态改变的,而rem做移动端布局正好需要动态改变.所以我们可以把根元素字体大小设置vw.

以750设计稿举例:

1rem=100px=100/375vw=0.266vw.

html{font-size:0.266vw}//等于font-size:100px

div{width:1rem}//width:100px;

 

四.Flexible布局

使用Flexible实现手淘H5页面的终端适配rem自适应布局-移动端自适应必备

用法:1,删除meta标签

       2,元素尺寸转化为rem计算方法:元素尺寸/100 rem,flexbox文件内部会有一系列判断和转换,比如设置宽度为50px,div{50/100 rem}

       3,特殊的是375设计稿,元素尺寸转化为rem计算方法:元素尺寸*2/100 rem

      4,在head中放入flexible,这样能兼容华为手机

 

<script>
        (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(‘将根据已有的meta标签来设置缩放比例‘);
                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) {
                    // ios下,对于2和3的屏,用2倍的方案,其余的用1倍方案
                    if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
                        dpr = 3;
                    } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {
                        dpr = 2;
                    } else {
                        dpr = 1;
                    }
                } else {
                    // 其他设备下,仍旧使用1倍的方案
                    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 > 768) {
                    width = 768 * dpr;
                }
                var rem = width / 7.5;
                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‘] = {}));
    </script>

 

flexible的缺点是对ui框架支持不好

 

以上是关于探讨移动端布局适配方案的主要内容,如果未能解决你的问题,请参考以下文章

移动端适配的问题

移动端高清适配布局开发解决方案

前端移动端适配 - 媒体查询适配方案

PC端移动端页面适配方案

移动端web自适应适配布局解决方案

前端移动端适配 - 媒体查询适配方案