移动端rem响应式布局的例子

由于移动端特殊性,本文讲的是如何使用rem实现自适应,或叫rem响应式布局,通过使用一个脚本就可以rem自适应,不用再为各种设备宽度不同而烦恼如何实现自适应的问题。

rem是相对于根元素<html>,这样就意味着,我们只需要在根元素确定一个px字号,则可以来算出元素的宽高。1rem=16px(浏览器html的像素,可以设定这个基准值),假如浏览器的html设为64px,则下面的元素则1rem=64px来运算。

实现方法:

通过JS来调整html的字体大小,而在页面中的制作稿则统一使用rem这个单位来制作。关键代码如下:
;(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 > 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'] = {}));
从上面的代码,主要是改变了dpx和document的font-size大小。大小为docEl.getBoundingClientRect().width / 10 + 'px';

假设我们的设计稿宽是640的,则html的字体大小则被设为64px.则相当于1rem=64px。

假如一个元素的宽是160px,在平时,我们可以采用百分比可以做到自适应,假如使用响应式的话,可能需要设置多个,比如在320px,输出80px,而在640px输出160px等。

而采用以上rem的方法,则只需要输出2.5rem就能实现统一,如下表格:

 

设备宽度

320px

360px

414px

640px

 

Html字体大小

32px

36px

41.4px

64px

 

实际输出

1rem

1rem

1rem

1rem

 

设计稿缩放大小

80px

90px

103.5px

160px

 

实际输出

2.5rem

2.5rem

2.5rem

2.5rem

以上的2.5rem是怎么得出的呢?

160/64(1rem的基数为64px)=2.5rem;按照官方的说法(750px举例)

Flexible会将视觉稿分成100份(主要为了以后能更好的兼容vh和vw),而每一份被称为一个单位a。同时1rem单位被认定为10a。针对我们这份视觉稿可以计算出:
1a   = 7.5px
1rem = 75px

 那么我们这个示例的稿子就分成了10a,也就是整个宽度为10rem,<html>对应的font-size为75px:

这样一来,对于视觉稿上的元素尺寸换算,只需要原始的px值除以rem基准值即可。例如此例视觉稿中的图片,其尺寸是176px * 176px,转换成为2.346667rem * 2.346667rem。

另外大漠还写了一篇详细的文章:使用Flexible实现手淘H5页面的终端适配 里面介绍了一个如何快速转换rem为px的几种方法,感兴趣的童鞋可以去看看。

也可以看这篇文章:Sass函数功能——rem转px

另外在使用这个来处理自适应的另一个坑就是css sprite,作者的建议是使用svg,或者icon font.或者base64等其他方案。

另外就是在dpr=2时,小图片可能会出现模糊,建议以最大的图片来切图。

字体建议使用px

在作者的观点中,是建议描述性的字体使用px,如果有slogan之类大于48px的,可以使用rem,由于使用rem在iPhone5和iPhone6中字体不同,可能出现13px和15px,点阵字体。

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

如此一来,就决定了在制作H5的页面中,rem并不适合用到段落文本上。所以在Flexible整个适配方案中,考虑文本还是使用px作为单位。只不过使用[data-dpr]属性来区分不同dpr下的文本字号大小。
div {
    width: 1rem;
    height: 0.4rem;
    font-size: 12px; // 默认写上dpr为1的fontSize
}
[data-dpr="2"] div {
    font-size: 24px;
}
[data-dpr="3"] div {
    font-size: 36px;
}

 为了能更好的利于开发,在实际开发中,我们可以定制一个font-dpr()这样的Sass混合宏:

@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;
    }
}

 有了这样的混合宏之后,在开发中可以直接这样使用:
@include font-dpr(16px);

 当然这只是针对于描述性的文本,比如说段落文本。但有的时候文本的字号也需要分场景的,比如在项目中有一个slogan,业务方希望这个slogan能根据不同的终端适配。针对这样的场景,完全可以使用rem给slogan做计量单位。

时间: 2024-09-27 08:03:41

移动端rem响应式布局的例子的相关文章

css-H5移动端上5张图片正方形响应式布局怎么实现?

问题描述 H5移动端上5张图片正方形响应式布局怎么实现? 如上图,注意1图宽度与2图的高度不等 1,3和2,4分别一样宽高.纯CSS或组JS也行,请大大给下代码谢谢啦 解决方案 简单实现响应式布局实现响应式布局 解决方案二: android 用 FrameLayout 就行了 解决方案三: @media screen and (max-width: 600px) { /*当屏幕尺寸小于600px时,应用下面的CSS样式*/ .class { background: #ccc; } } 本人工作中

求助webapp响应式布局

问题描述 求助webapp响应式布局 请问我如果想用rem来移动端全部布局可以吗?全部代替百分比? 另外不同设备默认的font-size不同 是否只要在html根标签中申明font-size=100% 然后全局使用rem即可?或者还有什么办法? 解决方案 html设置好一个参考值,用rem就行http://www.w3cplus.com/css3/define-font-size-with-css3-rem

什么是响应式布局、响应式布局该如何设计

文章简介:今天就和大家来讲讲响应式布局这件小事,包含什么是响应式布局.响应式布局的优点和缺点以及响应式布局该怎么设计(通过CSS3 Media Query实现响应布局). 讲到响应式布局,相信大家都有一定的了解,响应式布局是今年很流行的一个设计理念,随着移动互联网的盛行,为解决如今各式各样的浏览器分辨率以及不同移动设备的显示效果,设计师提出了响应式布局的设计方案.今天就和大家来讲讲响应式布局这件小事,包含什么是响应式布局.响应式布局的优点和缺点以及响应式布局该怎么设计(通过CSS3 Media

响应式布局该怎么设计?CSS3 Media Query实现响应布局

文章简介:响应式布局的小事就这么多,如你有好的补充意见或不同的见解,可以联系我,我们一起探讨这件小事-- 讲到响应式布局, 相信大家都有一定的了解,响应式布局是今年很流行的一个设计理念,随着移动互联网的盛行,为解决如今各式各样的浏览器分辨率以及不同移动设备的显示效果, 设计师提出了响应式布局的设计方案.今天就和大家来讲讲响应式布局这件小事,包含什么是响应式布局.响应式布局的优点和缺点以及响应式布局该怎么设计(通 过CSS3 Media Query实现响应布局). 一.什么是响应式布局? 响应式布

响应式布局在邮件中的实现

2010年, Ethan Marcotte 提出了响应式布局--一个网站兼容多个终端的概念.而响应式邮件,则是一 封邮件兼容多个终端. 根据ExtactTarget在2012年针对各个年龄段希望接受营销信息的方式调查表明 ,电子邮件是客户愿意接受营销信息的主要方式. 电子邮件营销中, 电子邮件内容是非常重要的一环 .由于人们习惯的浏览式阅读模式,一封设计优秀.有品牌识别度的邮件比一封纯文字邮件更能引起客户的关 注.从ReturnPath最近的调查[i]中又可以看出,人们已经逐渐习惯在移动端进行邮

浅谈html5 响应式布局

 一.什么是响应式布局?       响应式布局是Ethan Marcotte在2010年5月份提出的一个概念,简而言之,就是一个网站能够兼容多个终端--而不是为每个终端做一个特定的版本.       这个概念是为解决移动互联网浏览而诞生的.响应式布局可以为不同终端的用户提供更加舒适的界面和更好的用户体验,而且随着目前大屏幕移动设备的普及,用大势所趋来形容也不为过.  随着越来越多的设计师采用这个技术,我们不仅看到很多的创新,还看到了一些成形的模式. 二.响应式布局有哪些优点和缺点?   优点:

响应式布局该怎么设计

     讲到响应式布局, 相信大家都有一定的了解,响应式布局是今年很流行的一个设计理念,随着移动互联网的盛行,为解决如今各式各样的浏览器分辨率以及不同移动设备的显示效果, 设计师提出了响应式布局的设计方案.今天就和大家来讲讲响应式布局这件小事,包含什么是响应式布局.响应式布局的优点和缺点以及响应式布局该怎么设计(通 过CSS3 Media Query实现响应布局). 一.什么是响应式布局? 响应式布局是Ethan Marcotte在2010年5月份提出的一个概念,简而言之,就是一个网站能够兼容

响应式布局这件小事 设计师如何实现响应布局

讲到响应式布局, 相信大家都有一定的了解,响应式布局是今年很流行的一个设计理念,随着移动互联网的盛行,为解决如今各式各样的浏览器分辨率以及不同移动设备的显示效果, 设计师提出了响应式布局的设计方案.今天就和大家来讲讲响应式布局这件小事,包含什么是响应式布局.响应式布局的优点和缺点以及响应式布局该怎么设计(通 过CSS3 Media Query实现响应布局). 一.什么是响应式布局? 响应式布局是Ethan Marcotte在2010年5月份提出的一个概念,简而言之,就是一个网站能够兼容多个终端-

《jQuery Mobile快速入门》—— 2.6 带有媒体查询的响应式布局

2.6 带有媒体查询的响应式布局 jQuery Mobile快速入门 要使用jQuery Mobile来创建响应式设计,建议使用CSS3 Media Queries1.例如,如果你打算为一个特定设备的朝向增强布局,你可以使用媒体查询来检测设备的朝向,然后根据需要应用你的 CSS修改. 在某些情况下,jQuery Mobile将会为你创建响应式设计.下面将讲解jQuery Mobile的响应式设计如何良好地应用于竖屏(portrait)模式和横屏(landscape)模式中的表单字段.例如,在竖屏