简单粗暴的移动端适配方案 - REM

0. 前言

手机市场日渐丰富的同时,给我们前端开发人员带来的网页内容自适应屏幕尺寸进行显示的问题也日渐凸显出来。原本可能通过百分比/媒体查询等简单手段就可以常见的适配问题,但是对于页面有复杂结构或者视觉上有特殊要求的,就需要通过其他手段来解决了。

以上图“纪念碑谷”效果为例: 当你的页面素材都是单独的图片资源时,你完全可以通过百分比计算出每个动态小人的大小/位置/动画距离等信息;但是当所有的小图都被拼接成一张大的雪碧图时,当时我就眉头一皱,事情没有这么简单,元芳不知道你怎么看。

1. 老版常规做法

1.1 viewport缩放

以最小的Iphone4/5的宽度(320px)为基准,还原视觉稿。

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0 />

然后对不同屏幕分辨率的手机进行简单粗暴的等比例缩放设置。 例如:iphone8(375px)initial-scale = 375 / 320 = 1.18

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.18 />

据说早期天猫首页就是这么干的,有一定工作年限的开发者应该有了解。initial-scale越来越大,页面内容也就被拉伸也越厉害,导致页面内容会变得模糊,这个方法已经被摒弃了。

1.2 固定宽度进行留白

早期有部分网站把页面固定死宽度,但是多余的宽度进行居中留白。这对于前端开发就开心了,什么适配都不用管,外部宽度就是牛逼的320px。典型的墨守成规、因循守旧、故步自封、抱残守缺做法,放在现在各种“大屏手机”上,用户量恐怕要分分钟损失80%。

1.3 响应式布局

通过媒体查询根据不同的屏幕分辨率来进行适配,响应式的问题在于:

  • 屏幕分辨率分区间:区间内无法进行区分,无法实现100%兼容,一般是用主流分辨率来进行划分;
  • 额外的工作量:响应式布局的工作都是需要开发者去实现的,带来了额外的开放量;
  • 不适合功能复杂的页面:响应式一般适合用于资讯类页面,功能复杂的网站对于页面的整体排版和样式要求较高(特别是对比PC和H5);

对比三种做法我们会发现只有响应式布局可以解决我们的问题,但是又给我们带来了额外的复杂度和维护难度。那有没有什么方式可以一键解决我们的问题呢?

2. rem

在W3C官网上是这样描述rem的——“font size of the root element” 。

换句话说,当我们指定一个元素的font-size为2rem的时候,也就说这个元素的字体大小为根元素<html>字体大小的两倍,如果html的font-size为12px,那么这个2rem的元素font-size就是24px。同理当该元素为3rem时,那么其实际font-size就是36px

html {font-size: 12px;}h1 { font-size: 2rem; } /* 2 × 12px = 24px */p { font-size: 1.5rem;} /* 1.5 × 12px = 18px */div {width: 20rem;} /* 20 * 12px = 240px*/
html {font-size: 16px;}h1 { font-size: 2rem; } /* 2 × 16px = 32px */p { font-size: 1.5rem;} /* 1.5 × 16px = 24px */div {width: 20rem;} /* 20 * 16px = 320px*/

看到这里你应该就会发现,只要我们根据不同屏幕设定好根元素<html>的font-size,其他已经使用了rem单位的元素就会自适应显示相应的尺寸了。

对比em和rem:

单位

定义

特点

em

font size of the root element

以根元素字体大小为基准

rem

font size of the element

以父元素字体大小为基准

虽然em带来了模块化的好处,但是由于 em 是相对于父元素的倍数,所以你可能在许多层嵌套的 em 中找不到一个固定值,rem 就是可以随时拿来用的一个固定参考值。关于二者的对比就不在这里展开了,感兴趣的同学可以参考这篇文章 rem-vs-em。

3. rem计算

细心的同学就会发现了,我们使用rem单位事先需要做的一件事情就是设置根元素<html>的font-size,通常有两种做法。

3.1 JS计算

通过JavaScript读取屏幕宽度,然后根据宽度计算出对应的尺寸并设置根元素的font-size。

const oHtml = document.getElementsByTagName('html')[0]const width = oHtml.clientWidth;// 320px的屏幕基准像素为12pxoHtml.style.fontSize = 12 * (width / 320) + "px";

这样iphone8(375px)下html的font-size 就是14.0625px,iphone8p下font-size就是15.525px。

如果在iphone8(375px)下设置元素font-size为 1.7066rem, 效果跟设置其font-size为 24px 是一样的(24 / 14.0625 = 1.7066)。

上面的示例是个很简单的例子,感兴趣的同学可以在自己的页面上试一下或者开发者工具下打开 淘宝触屏版,使用rem设置元素的样式,并通过开发者工具切换模拟机型观察页面效果。

使用JS来获取屏幕宽度的好处在于可以100%适配所有的机型宽度,因为其<html>元素的基准尺寸是直接算出来的。既然是JS代码,为了避免造成因为动态设置<html>元素的font-size而造成页面抖动,一般这部分代码我们放在header底部去加载,并内联到html文档里面。

更加详细的实现,感兴趣的同学可以看这片文章:Rem自适应js-优化flexible.js。

3.2 媒体查询

既然只是为了根据屏幕宽度来设置<html>元素的字体大小,那我们完全也可以通过css3媒体查询来完成这部分工作。

@media screen and (min-width: 375px){    html {        font-size: 14.0625px;   
    }}@media screen and (min-width: 360px){    html {        font-size: 13.5px;
    }}@media screen and (min-width: 320px){    html {        font-size: 12px;
    }}html {    font-size: 16px;
}

像苏宁易购等网站就是这么做的:

4. rem存在的问题

rem作为一种简单粗暴解决不同屏幕下视图的区别的一种方案,它可以解决本文出现的问题以及绝大多数移动端适配屏幕尺寸的问题。但是既然它并不是一个完美的解决方案,那就有其局限性所在。

举个例子: 作者有一大爱好是看小说,大屏智能机时代确实几乎完全替代了我十年前纸质化阅读的习惯。从2011年至今,手上的手机屏幕宽度一直在提升,但是使用的看小说软件的显示字号几乎是不变的。使用rem会在一定程度上打破用户的文字内容阅读习惯,特别是在大篇幅的内容时。

iOS与Android平台的适配方式背后隐藏的设计哲学是这样的:阅读文字时,可读性较好的文字字号行距等绝对尺寸数值组合与文字所在媒介的绝对尺寸关系不大。(可以这样简单理解:A4大小的报纸和A3大小甚至更大的报纸,舒适的阅读字号绝对尺寸是一样的,因为他们都需要拿在手里阅读,在手机也是上同理);在看图片视频时,图片、视频的比例应该是固定的,不应该出现拉伸变形的情况。而rem用在字号时,使字号在不同屏幕上的绝对尺寸不一致,违背了设计哲学。

5. 工程应用

我们平时使用rem还有遇到的一大问题就是我们习惯使用px来定义样式,而px到rem是需要计算转化过程的,刚接触rem的时候你可能需要px先定义好页面布局,然后一个一个计算并替换rem单位。

当然我们有更加科学的方式来使用rem单位。

5.1 px转rem网页工具

你可以前往px转rem工具,轻松一键上传你的css文件让这个网页工具帮你完成计算和替换。

5.2 mixin

1、rem

输入:

.element {
  @include rem('padding',10px 0 2px 5px);
}

输出:

.element {  padding: 10px 0 2px 5px;  padding: 1rem 0 0.2rem 0.5rem;
}

2、sass-rem

输入:

.demo {
  font-size: rem(24px); // Simple
  padding: rem(5px 10px); // Multiple values
  border-bottom: rem(1px solid black); // Multiple mixed values
  box-shadow: rem(0 0 2px #ccc, inset 0 0 5px #eee); // Comma-separated values
  text-shadow: rem(1px 1px) #eee, rem(-1px) 0 #eee; // Alternate use
}

输出:

.demo {  font-size: 1.5rem;  padding: 0.3125rem 0.625rem;  border-bottom: 0.0625rem solid black;  box-shadow: 0 0 0.125rem #ccc, inset 0 0 0.3125rem #eee;  text-shadow: 0.0625rem 0.0625rem #eee, -0.0625rem 0 #eee;
}

5.3 构建

作为工程化的今天,我们同样有大量的构建插件来帮助我们自动完成px单位到rem单位的转换过程:

  • fis3: fis3-postprocessor-px2rem
  • gulp stylus-px2rem
  • webpack px-to-rem-loader 更多插件

本文作者:孙世吉

原文链接:http://imweb.io/topic/5a523cc0a192c3b460fce3a5

原文发布于微信公众号 - 腾讯NEXT学位(NextDegree)

原文发表时间:2018-01-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序人生 阅读快乐

超实用的jQuery代码段

本书精选近350个jQuery代码段,涵盖页面开发中绝大多数要点、技巧与方法,堪称史上最实用的jQuery代码参考书,可以视为网页设计与网站建设人员的好帮手。本...

1031
来自专栏九彩拼盘的叨叨叨

《写给大家看的设计书》摘要与总结

该书适合完全没有设计背景,或在设计方面没有经过正规培训的人。 该书的描述浅显易懂,并且配有很多插图来做描述的说明。阅读起来觉得很轻松。

743
来自专栏IMWeb前端团队

rem不是神农草,治不了移动端百病

有很多朋友一聊起做移动端重构,第一个问题就是用什么单位合适。%,还是rem?(如果你还不太了解rem是什么单位,可先前往CSS3的REM设置字体大小了解。) 然...

21910
来自专栏各种机器学习基础算法

关于Web语义化的意义

随着现在WEB(网页)的越来越火爆,WEB开发也越来越受人们重视。Tim Berners-Lee 可能不会想到它现在会达到的规模以及深入到我们生活的那么多方面。...

3136
来自专栏MixLab科技+设计实验室

从线条艺术到DIY实现一个网状体Net的js库

今天无意中看到一个可视化作品: WHAT MADE ME? INTERACTIVE PUBLIC INSTALLATION Most Original Exh...

3006
来自专栏菜鸟前端工程师

html+css学习笔记004-元素选择器0背景属性

1135
来自专栏Golang语言社区

【Golang语言社区】H5游戏开发--从零开始开发一款H5小游戏(二) 创造游戏世界,启动发条

上一节介绍了canvas的基础用法,了解了游戏开发所要用到的API。这篇文章开始,我将介绍怎么运用这些API来完成各种各样的游戏效果。这个过程更重要的是参透一些...

3753
来自专栏腾讯社交用户体验设计

H5动效的常见制作手法 - 腾讯ISUX

5472
来自专栏互联网杂技

如何打造一个高效适配的H5

以往拿到一份视觉稿要做页面适配,通常都是针对不同分辨率尺寸做断点写 media query,然后看效果再微调。开发过程中视觉稿要是做了修改,修改的地方就得再走一...

3395
来自专栏偏前端工程师的驿站

CSS3魔法堂:说说Multi-column Layout

前言  是否记得《读者文摘》中那一篇篇优美感人的文章呢?那除了文章内容外,还记得那报刊、杂志独有的多栏布局吗?  当我们希望将报刊、杂志中的阅读体验迁移到网页...

2085

扫码关注云+社区

领取腾讯云代金券