设计稿的100%还原-「REM」引发的思考

更新前言】很欣慰在看以前写的文章时能发现错误,说明自己进步了,此次更新主要是重构了文章,删去了错误的部分,更新了最近开发时遇到的问题和心得,希望以后还能有新的想法注入。如果看官有想法和建议,欢迎评论哦~
18-01-12 更新

* 适配问题的深坑 - 逻辑像素被改变

  下文从重构时提到过一些,某耀手机具有切换“显示模式”的功能,它会主动改变手机的逻辑像素。当逻辑像素被改变时,由 rem 转换出来的 逻辑像素单位在页面上展示的效果就会发生变化。
  例如:原本设置 .btn { width: 28rem; } ,大约占用手机屏幕90%的宽度效果,当显示模式设置为‘大’,即手机逻辑像素改变后,28rem 显示出占据手机屏幕约110%的现象,严重影响视觉。
【处理】在css中,有两个不常见又很好用的单位,vwvh;它表示占用视口宽度/高度的百分比,1vw表示1%视口宽度,1vh表示1%视口高度。

  有人会问:为什么不直接用百分比?很好的问题,回答这个问题前,要先了解一个概念:视口.
什么是「视口」?   即移动前端经常会提到的一个概念:viewport; 指的是浏览器显示页面内容的屏幕区域。针对移动端开发非常方便。
  移动端视口宽度和视口高度,就是说手机屏幕上显示内容的区域大小,根据视口大小比例设置宽高,能先保证在竖屏下按钮永远显示一种效果。对于横屏,引入media query即可,也可以用js动态修改,会比较麻烦点。
那为什么不用流式布局的百分比?  原因很简单,百分比是相对单位,相对的是父元素的大小,如果父元素不是body,就会受父元素的大小影响,通常情况下,我们大部分都采用的是rem设置大小,如果父元素是rem设置的单位,百分比就只能按照父元素的这个rem来计算长度,依旧不能解决逻辑像素被改变时的显示问题。

--------------孤独的根号3-----------------

* 什么是 rem,为什么用 rem

REM(font size of the root element),是指相对于根元素的字体大小的单位,是个相对单位,如果不设置根元素的字体大小,则会默认以根元素的16px的大小计算值。
 说到rem,百分九十的面试官会问,rem和em区别是什么?EM(font size of the element),是指相对于父元素的字体大小单位,也是个相对单位。他们之间很类似,但为什么 em 就是火不起来?一段好的程序,讲究的是易于维护,找到元素的大小之后还要去找父元素大小才能理解真正大小,不太方便。
 REM 是css3提出的,它实现了 类似 less / sass 中变量的功能,大大提高了可维护性,实现UI稿百分百的还原效果

* 基础案例

 搞移动端开发的小伙伴,最头疼的事情就是适配问题, 但又不得不硬着头皮去解,改了一版又一版。其实能rem帮我们解决很多适配问题。 基础的用法:
javascript代码

<button class="btn">Rem等比例缩放</button>    

css代码

html { font-size: 16px; }
.btn {
  width: 8rem;
/*   height: 2rem; */   
  line-height: 2rem;  
  border-radius: 0.25rem;
  background-color: #0a90d3;
  border-color: #0a90d3;
  color: white;
}

效果展示

基础案例

理解分析
  根元素设置字体大小为16px; 那么,根据rem规则,width就为 8 * 16 = 128px;圆角就为0.25 * 16 = 4px;
当我们修改如下时

html { font-size: 20px; }

可以得到以下效果,整个按钮被等比例放大了:


根元素设置为20px

 到这里你就基本理解rem怎么使用了,但这么用,还远远不够,我们继续深入探索,如何深度还原UI稿上的效果?我们知道,UI稿的字体大小和边距等参数都是是在1080 * 1920上拟定出来的, 那我们如何计算成我们要的大小呢?
  解决这个问题之前,我们要先理解 逻辑像素物理像素

* 物理像素[设备像素] & 逻辑像素[CSS像素]

物理像素

  物理像素,又称 设备像素,在同一个设备上,他的物理像素是固定的,设备厂商出厂是就设置好了,即,一个设备的分辨率是固定的。

逻辑像素

 又称css像素,viewport中的一个小方格。我们在写css代码的时候,用的就是css像素。

像素比

物理像素和逻辑像素的比例。当比例为 1:1 时,表示1个物理像素显示一个css像素;当比例为 2:1 时,表示使用4个物理像素显示1个逻辑像素。

逻辑像素和物理像素差异:(1px逻辑像素 != 1px物理像素

 移动端Web App开发的小伙伴肯定有类似的遭遇,UI设计师给我们的UI稿上,字号动不动就是36px;甚至是60px;这要真是写到代码中,页面直接爆炸,别说页面美感了,连显示都是问题。为什么会有这问题呢?
 看了上面的定义,或许你就明白了。没错,UI稿上的36px,60px,其实是物理像素,是相对于设备分辨率下的字号,而我们要在css中填写的字号,是css像素,是相对于逻辑像素下的字号,不是同一个概念。

 在Iphone 4中,物理像素是640px * 960px;而逻辑像素是 320px * 480px;因此,这里大概需要4个物理像素来显示一个css像素的内容。只看宽度就是两个物理像素。这也是为什么很多初级前端开发工程师直接使用 UI稿/2法 也能实现基本效果的原因。

点题: UI稿上要求设置边框为1px,但是我们设置border: 1px solid #eee;了之后,UI又说我们边款太粗了。有没有很想一巴掌扇死他的冲动?其实,我们设置的1px是css像素,而UI稿上指的是设备像素,原来真的比要求的粗。

* 自动化检测屏幕并设置 [根元素]

  理解完 逻辑像素和物理像素后,我们可以如下实现动态检测并监听屏幕变化并实现自动化适配:

// rem布局的核心代码。 此例默认UI稿按 1080 * 1920 提供
(function(win, doc){
    var docEl = doc.documentElement,
        resizeEvt = 'oritationchange' in window ? 'oritationchange' : 'resize',
        recalc = function(){
            var clientWidth = docEl.clientWidth;
            if (!clientWidth) return;
            if (clientWidth < 550) {
                docEl.style.fontSize = 100 * (clientWidth / 1080) + 'px';
            } else {
                docEl.style.fontSize = 100 * (clientWidth / 1920) + 'px';
        }
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    doc.addEventListener('DomContentLoaded', recalc, false);
})(window, document)

分析doc.addEventListener('DomContentLoaded', recalc, false); 触发在网页被载入时,计算一次根元素的长度大小,win.addEventListener(resizeEvt, recalc, false); 触发在浏览器窗口被改变时如拉动,横竖屏切换等操作时,重新计算一次根元素的长度大小。
为什么设置 clientWidth < 550用来甄别手机处于横竖屏什么状态。 以前我设置的是640,因为我看过一篇文章提到640px(逻辑像素)是最大安全宽度。但其实也有个问题,这是这个值宽度保证不会超过了没问题,但是当横竖屏切换时,高度就变成了宽度,有些手机的高度比640小,因此误判成手机处在竖屏状态,那么适当缩小改成550还是比较合适的。我出问题的手机是最新某耀手机,能设置 "显示模式" 为‘大’,竖屏逻辑像素只有605。

* 适配问题的处理 - 媒体查询

 在基础案例中,我们已经能实现根据根元素做字号、宽高的自适应,但是这种情况也并不一定能完全符合预期。

  把手机做横竖屏切换后,rem能根据手机横竖屏做出动态响应是没错,但是又有一个问题来了,如果我们想在横屏时实现不同的效果呢?比如,竖屏时底部按钮占满宽度,横屏时底部按钮只占一般宽度?
这时,我们需要引入媒体查询@media,如下案例:

@media screen and (min-width: 550px){
    btn {
        width: 16rem;
        height: 3rem;
    }
}

注意: 设置@media的时候,最好将其放置在css的最底部,用来覆盖其他样式

到这里,我们基本就能实现绝大部分设备的适配问题。


发现】关于利用 rem 实现适配的典型案例,大家可以看看手机某宝的代码,你可能不会相信,手机淘宝的首页 不是用Native App实现的,而是用Web App实现的,应该是考虑到方便升级更新等问题吧。

# 简单建议:

1、meta:viewport,设置initial-scale为 1;
2、选择合适的rem比例,要方便转换,也要有实际意义
3、页面整体布局采用 REM布局方式,图片采用流体布局并设置max-width,特殊效果采用响应式布局媒体查询。特殊效果采用弹性布局flex实现简易一些。

# 后语

  本文是作者在开发时遇到问题的心得体会,如果有不对的地方,欢迎你的指正,我们一起成长。

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

推荐阅读更多精彩内容