<布局>REM方案(移动端)

rem方案是阿里为兼容几乎所有移动端页面,而想出来的。
阿里的方案具体可看githup:https://github.com/amfe/lib-flexible

基础

>> css单位: rem;

此单位会相对于html的font-size值进行倍数计算; 例如

<html>
    <style>
        html{
            font-size: 20px;
        }
        div{
            width:10rem; // 宽为 200px
            height:10rem; // 高为 200px
        }
    </style>
    <div></div>
</html>
>> html标签 <meta name="viewport" content="">

设置它提供了关于可视窗口大小的设置。仅由移动设备使用。
<meta name="viewport">.

属性 描述
width 正整数,或文字 device-width 定义视口的像素宽度
initial-scale 0~10之间的正数 定义可视窗口的缩放比例
maximum-scale 0~10之间的正数 定义可视窗口的最大缩放比例,IOS10无视此设置
minimum-scale 0~10之间的正数 定义可视窗口的最小缩放比例,IOS10无视此设置
user-scalable yes 或者 no no用户无法放大缩小页,默认yes。IOS10强制yes
>> dpr

设备独立像素也称为密度无关像素,可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用的虚拟像素(比如说CSS像素),然后由相关系统转换为物理像素。

  • CSS像素

CSS像素是一个抽像的单位,主要使用在浏览器上,用来精确度量Web页面上的内容。一般情况之下,CSS像素称为与设备无关的像素(device-independent pixel),简称DIPs。

  • 屏幕密度

屏幕密度是指一个设备表面上存在的像素数量,它通常以每英寸有多少像素来计算(PPI)。

  • 设备像素比(device pixel ratio)

设备像素比简称为dpr,其定义了物理像素和设备独立像素的对应关系。它的值可以按下面的公式计算得到:

设备像素比 = 物理像素 / 设备独立像素

简单说:
以前在CSS 中的1px × 1px的大小,设备用1×1个像素点显示,dpr也就是1。
后来出了苹果出了视网膜屏幕,CSS 中的1px × 1px的大小,将像素点数量翻倍
2 × 2个像素点显示 ,dpr就是2. 下图.

image.png

具体实施

html中写入<meta name="viewport" >, 很重要整个方案都依赖它.

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
注意 <meta name="flexible" content="initial-dpr=2" > 设置了这个值,会强制设置dpr. 不建议设置

在<head>中写JS

var width = document.documentElement.clientWidth; // 获取宽度
var fontSize = width; // 这样1rem 就是页面的宽度.  建议除100 后面改。
document.documentElement.style.fontSize = fontSize + 'px';

写css 假设页面设计稿的宽度是 750px, 里面有一个 30px的div

<style>
    div{
        width:0.04rem;
        height:0.04rem;
        background: red;
    }
</style>
<div></div>

现在在750px手机中显示为30px大小的div,其他宽度的手机进行按比例自动缩小.
问题:值很小的时候 比如1px 要转换为0.001333333333rem,浏览器可能会忽略过小值,所以要改一下将html的font-size缩小10(也利于将来转换为vw方案)

注意 如果你缩小100倍,你可能会发现页面混乱了,因为pc中页面的字体会有最小限制,比如谷歌不允许小于12px。所以html的font-size成了12px所以布局乱了。 但是手机没有这个限制
//JS中
width = document.documentElement.clientWidth; // 获取宽度
fontSize = width / 10; 
document.documentElement.style.fontSize = fontSize + 'px';
//CSS中
<style>
    div{
        width:0.4rem; // 因为html字体缩小,所以这里相应增大
        height:0.4rem;
        background: red;
    }
</style>
//用SCSS预编译,写个函数.    手动写这些值太麻烦 用SCSS函数去改
@function rem($n){
    @return $n * 10rem / 750;  // 750是你设计图的宽度,如果设计图是300就写300.
}

字体不推荐用rem,用px, 例如将body设置为font-size:14px;
按现在的写法,大多数情况也都能应对,各个手机兼容也没什么大问题。

但是如果要解决1px问题(设计师要物理像素的一像素点宽度,而不是css的1px),就要在费周章了。
阿里方案的解决方法: 如果是dpr为2的屏幕,写1px,用<meta name="viewport" content="initial-scale=0.5">,来缩小为原来的0.5倍,这样就是1像素宽度了。 兼容性较好的方法。

在<head>中写JS

   //获取 已设置的<mate name="viewport">
   var vp = document.querySelector('meta[name="viewport"]');
   // devicePixelRatio 可以获取设备的dpr值 没有则写1
   var dpr = window.devicePixelRatio || 1;
   var style = document.getElementsByTagName("style")[0];
   var width = document.documentElement.clientWidth;
   // 后面会进行缩放dpr倍 所以要字体放大dpr倍
   var fontSize = width * dpr / 10;
   // 屏幕大 fontSize也会大  你可以设置个阈值,让大屏幕时布局按照小屏幕显示.  
   // 56代表,在屏幕大小,大于560px的屏幕, 布局按照560px的效果显示. 你可以更改
   fontSize =fontSize > dpr*56 ? dpr*56 : fontSize;
   document.documentElement.style.fontSize = fontSize + 'px';
   //为实现 1像素线   缩放为相应dpr
   vp.content = `initial-scale=${ 1 / dpr }, maximum-scale=${ 1 / dpr }, minimum-scale=${ 1 / dpr }, user-scalable=no`;
   if(style){
       // 给body设置相应的初始字体大小
       style.innerHTML += `body{
           font-size:${ dpr * 14 }px;
       }`;
   } else {
       document.getElementsByTagName("head")[0].innerHTML += `<style>
           body{
               font-size:${ dpr * 14 }px;
           }
       </style>`;
   };

CSS

布局还是使用 rem实现。
@function rem($n){
    @return $n * 10rem / 750;  // 750是你设计图的宽度,如果设计图是300就写300.
}
要使用1像素细线,直接写1px。

下面是我用iPhone6plus的效果,绿色边框是不使用此方案直接1px的效果,红色边框是此方案写1px实现1像素线的效果。


6FFF244660C4F1FC5C35265C172294E5.png
适应下pc端

因为pc可能获取到dpr,但是<mate name="viewport">对PC是无效的所以进行下判断

    //是PC返回 true 否则 false;
    function IsPC() {
        var userAgentInfo = navigator.userAgent;
        var Agents = ["Android", "iPhone",
                    "SymbianOS", "Windows Phone",
                    "iPad", "iPod"];
        for (var v = 0; v < Agents.length; v++) {
            if (userAgentInfo.indexOf(Agents[v]) > 0) {
                return false;
            }
        }
        return true;
    }

    //获取 已设置的<mate name="viewport">
    var vp = document.querySelector('meta[name="viewport"]');
    // devicePixelRatio 可以获取设备的dpr值 没有则写1
    var dpr = window.devicePixelRatio || 1;
    //进行判断pc 手机
    if( IsPC() ){
        dpr = 1;
    }
    var style = document.getElementsByTagName("style")[0];
    var width = document.documentElement.clientWidth;
    // 后面会进行缩放dpr倍 所以要字体放大dpr倍
    var fontSize = width * dpr / 10;
    // 屏幕大 fontSize也会大  你可以设置个阈值,让大屏幕时布局按照小屏幕显示.  
    // 56代表,在屏幕大小,大于560px的屏幕, 布局按照560px的效果显示. 你可以更改
    fontSize =fontSize > dpr*56 ? dpr*56 : fontSize;
    document.documentElement.style.fontSize = fontSize + 'px';
    //为实现 1像素线   缩放为相应dpr
    vp.content = `initial-scale=${ 1 / dpr }, maximum-scale=${ 1 / dpr }, minimum-scale=${ 1 / dpr }, user-scalable=no`;
    if(style){
        // 给body设置相应的初始字体大小
        style.innerHTML += `body{
            font-size:${ dpr * 14 }px;
        }`;
    } else {
        document.getElementsByTagName("head")[0].innerHTML += `<style>
            body{
                font-size:${ dpr * 14 }px;
            }
        </style>`;
    };

写了一个<a href="https://weblzf.github.io/practice/newsRem/">Demo</a> . Githup<a href="https://github.com/weblzf/practice/tree/master/newsRem">代码地址</a>
有任何错误请指出!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容