首页 > 代码库 > 移动端自适应布局方案尝试

移动端自适应布局方案尝试

问题

刚开始接触移动端H5页面的时候最困扰的几个问题是:

  1. 6或6p上明明是1px的边框怎么就成了2px或3px辣么粗!
  2. 图片,div等如何等比自适应设计图

后来慢慢知道了第一点是由于retina屏幕下设备像素比的问题造成,第二点知道了单位rem。

 

目的

不想因为使用rem而一一去计算设计稿的尺寸,设计稿750的尺寸的标注可以直接在sass中使用;字体不使用rem缩放,原因是:

显然,我们在iPhone3G和iPhone4的Retina屏下面,希望看到的文本字号是相同的。也就是说,我们不希望文本在Retina屏幕下变小,另外,我们希望在大屏手机上看到更多文本,以及,现在绝大多数的字体文件都自带一些点阵尺寸,通常是16px和24px,所以我们不希望出现13px和15px这样的奇葩尺寸。

还一个目的是,在页面没有设置viewport的时候动态设置,并且不让页面有一个“闪现”的过程(也就是刚加载没设置的状态到设置的状态);页面动态变化时,尺寸相应变化;

 

尝试

在写H5页面的时候,尽可能少的去写meta标签,我会这样做:

<head>    <title>viewport test</title>    <meta charset="utf-8">    <link rel="stylesheet" href="http://www.mamicode.com/style/style.css"></head>

就这样简单,然后实现的代码当然是放在head里。因为并没有写viewport,所以得判断加上

if (!metaEl) {    metaEl = doc.createElement(‘meta‘);    metaEl.setAttribute(‘name‘, ‘viewport‘);    metaEl.setAttribute(‘content‘, ‘width=device-width,initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no‘);    if (docEl.firstElementChild) {        docEl.firstElementChild.appendChild(metaEl);    } else {        var wrap = doc.createElement(‘div‘);        wrap.appendChild(metaEl);        doc.write(wrap.innerHTML);    }}

然后根据页面的devicePixelRatio缩放

var scale = parseFloat((1 / dpr).toFixed(2));if (dpr != 1) {    metaEl.setAttribute(‘content‘, ‘width=device-width,initial-scale=‘+ scale +‘, maximum-scale=‘+ scale +‘, minimum-scale=‘+ scale +‘, user-scalable=no‘);}

设置根字体大小

// document widthfunction setDocumentFontSize () {    var width = docEl.getBoundingClientRect().width;    docEl.style.fontSize = width / 10 + ‘px‘;}setDocumentFontSize();

页面resize监听

var timer;win.addEventListener(‘resize‘, function() {    clearTimeout(timer);    timer = setTimeout(function () {        setDocumentFontSize();    }, 300);}, false);

为了字体不使用rem,需要为documentElement设置data-dpr属性

// document data-dpr set font-size pxvar dpr = window.devicePixelRatio;if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {                    dpr = 3;} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){    dpr = 2;} else {    dpr = 1;}docEl.setAttribute(‘data-dpr‘, dpr);

 

sass相关设置

完全根据设计稿尺寸写

// baseFontSize $baseFontSize: 75;@function px2rem($px){    @return $px/$baseFontSize * 1rem;}@function px2rem2($px){    @return px2rem($px*2);}

字体大小变化

// 字体大小计算@mixin font-dpr($font-size){    font-size: $font-size;    [data-dpr="2"] & {        font-size: $font-size * 2;    }    [data-dpr="3"] & {        font-size: $font-size * 3;    }}

 

例如:一个简单样式的设置

.test {    @include font-dpr(10px);    width: px2rem2(300);    margin: 0 auto;    border:1px #dcdcdc solid;}img {    display: block;    width: px2rem2(355);    margin: 0 auto;}

效果示例:

技术分享

可以从图中看出,6p的dpr为3,字体相应为30px,页面缩放了3倍,正式我所想要的。

 

页面demo源码

<!DOCTYPE html><html><head>    <title>viewport test</title>    <meta charset="utf-8">    <link rel="stylesheet" href="http://www.mamicode.com/style/style.css">    <script>    ;(function (win) {        var doc = win.document;        var docEl = doc.documentElement;        var metaEl = doc.querySelector(‘meta[name="viewport"]‘);        if (!metaEl) {            metaEl = doc.createElement(‘meta‘);            metaEl.setAttribute(‘name‘, ‘viewport‘);            metaEl.setAttribute(‘content‘, ‘width=device-width,initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no‘);            if (docEl.firstElementChild) {                docEl.firstElementChild.appendChild(metaEl);            } else {                var wrap = doc.createElement(‘div‘);                wrap.appendChild(metaEl);                doc.write(wrap.innerHTML);            }        }        // document data-dpr set font-size px        var dpr = window.devicePixelRatio;        if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {                            dpr = 3;        } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){            dpr = 2;        } else {            dpr = 1;        }        docEl.setAttribute(‘data-dpr‘, dpr);        var scale = parseFloat((1 / dpr).toFixed(2));        if (dpr != 1) {            metaEl.setAttribute(‘content‘, ‘width=device-width,initial-scale=‘+ scale +‘, maximum-scale=‘+ scale +‘, minimum-scale=‘+ scale +‘, user-scalable=no‘);        }        // document width        function setDocumentFontSize () {            var width = docEl.getBoundingClientRect().width;            docEl.style.fontSize = width / 10 + ‘px‘;        }        setDocumentFontSize();        var timer;        win.addEventListener(‘resize‘, function() {            clearTimeout(timer);            timer = setTimeout(function () {                setDocumentFontSize();            }, 300);        }, false);    })(window);    </script></head><body>        <div class="test">        显然,我们在iPhone3G和iPhone4的Retina屏下面,希望看到的文本字号是相同的。也就是说,我们不希望文本在Retina屏幕下变小,另外,我们希望在大屏手机上看到更多文本,以及,现在绝大多数的字体文件都自带一些点阵尺寸,通常是16px和24px,所以我们不希望出现13px和15px这样的奇葩尺寸。    </div>    <img src="https://camo.githubusercontent.com/3bd9e24ee11cee86e81dc49c0e5722e9f55e7297/687474703a2f2f7777772e773363706c75732e636f6d2f73697465732f64656661756c742f66696c65732f626c6f67732f323031352f313531312f72656d2d392e6a7067" ></body></html>

 

欢迎关注我的博客:http://ymblog.net

 

移动端自适应布局方案尝试