前端移动开发之rem
前言
作为一名前端工程师,我们不仅要会PC端开发,还要会移动端开发,而且现在移动端占据主要流量,所以掌握移动端开发的技能更是必须的。
那么进行移动端的开发,什么是必须,我们想要的效果是什么?
自适应。对,我们想要的效果应该是网页上的元素能随着窗口大小的变化而跟着同比的变化。
假如我们拿到一张750px宽的设计图,上面有一个元素是75px宽,当这张页面出现在只有540px宽的设备上,这个元素就得是54px宽。
如果你使用px这种固定的长度单位,在不同大小的设备上会出现什么情况,不用我说你也知道吧。
现在手机机型五花八门,主流手机iPhone6/7/8 4.7英寸、iPhone6/7/8 Plus 5.5英寸、iPhoneX 5.8英寸等。
那么如何让这些机型不同大小不一致的手机呈现出我们想要的效果呢?
方案
解决移动端适配问题其实有多种方案。
1.百分比
很容易就能想到百分比能实现自适应,但百分比非常局限。
在一张网页上,有一个元素占这个网页宽度的一半,你很容易就想到width: 50%。
但这个元素如果出现在不知道距页面左边缘多少px的情况下,你一下子无法看出占多少百分比,这时候你就得去测量、去算占比,如果元素非常多的话,那就相当麻烦了。
然而,使用百分比真正的弊端在于字体大小和元素高度。
字体大小是无法通过百分比实现自适应的。
元素的高度也是一样,一般移动端的页面是不知道高度的,可以随着内容无限下拉,元素的高度很难通过百分比去计算。
2.媒体查询(@media)
使用多套CSS也可以实现移动端自适应。
但媒体查询最适合的场景是一个网页在PC端是一种呈现形式,在移动端是另一种呈现形式。
如果纯移动端网页(只考虑移动设备不考虑PC设备)使用媒体查询,面对不同机型,就会有多套CSS,代码相当冗长。
3.vw
vw是一种CSS长度单位,是相对单位。
表示相对视口宽度(Viewport Width),1vw = 1% * 视口宽度,100vw等于屏幕宽度。
它的自适应效果非常好,但是目前它的兼容性不好,特别是在移动端浏览器有很多兼容问题的环境下,这里显得特别不合适,所以不推荐。
4.rem
rem也是一种CSS长度单位,也是相对单位。
它相对于根元素(<html>)下的font-size的值,1rem = html下font-size的值。
这个单位可谓集相对大小和绝对大小的优点于一身,通过它既可以做到只修改根元素就成比例地调整所有字体大小,又可以避免字体大小逐层复合的连锁反应。
目前,除了IE8及更早版本外,所有浏览器均已支持rem。
viewport
在真正使用之前,我必须介绍一下<meta name="viewport">这个元素标签。
想必,在每一个移动端页面,都有这么一段代码:
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
这段代码的意思是让视口(viewport)的宽度等于设备的宽度,初始缩放比例为1,最小缩放比例为1,最大缩放比例为1,禁止用户缩放。content的内容是可以配置的。
移动端浏览器会把网页放在一个viewport中,
默认情况下,移动设备上的viewport是大于浏览器可视区域的,
所以一般会出现滚动条,这是为了能在移动设备上正常显示那些为PC端设计的网站,移动设备上的浏览器都会把自己默认的viewport设为980px或其他值。
像下面这样,在还没有写<meta>的情形,模拟手机浏览器:

所以我们必须使用<meta>元素来限制viewport的大小和缩放,一般我们都是等于设备的宽度。
必须使用<meta>元素还有一点是和rem相关的。
上面说过,rem是一种相对单位,相对于html元素下的font-size的值。
如果html元素下的font-size的值能随着页面的大小变化而变化,那么rem也能做出相应的变化。
所以,如果没有加上<meta>元素标签这一段代码,在不同机型大小下,html元素下的font-size的值是一直不变的,因为viewport不变,一直保持980px。
使用
“假如我们拿到一张750px宽的设计图,上面有一个元素是75px宽,当这张页面出现在只有540px宽的设备上,这个元素就得是54px宽。”
我们说过达到这种移动端自适应的效果最好的方法是使用rem单位。
因为1rem = html下font-size的值,如果html下font-size的值能随着页面的大小改变而改变,我们在代码写的rem就不用改变。
先约定1rem = 50px,如750px页面,75px元素,那么元素的width我们在代码中设置的值就是1.5rem。当页面大小变成540px,1rem = 36px,代码中元素的宽度是1.5rem,所以元素现在在页面的宽度是54px。
好,现在我们就写一段代码来让html下font-size的值能随着页面的大小改变而改变,代码如下:
(function(doc, win){
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
docEl.style.fontSize = 50 * (clientWidth / 750) + 'px';
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
实例
假设我们的设计师给我们一张设计图(嗯,没错!就长这个样子)

这是一张 750*1334 px的设计图,在设计图上量得这个黄色的矩形的长是330px,宽是190px。
因为一般设计图都是按照iPhone6的二倍图进行设计,所以iPhone6的实际尺寸是 375*667 px,所以黄色矩形的长应是165px,宽是95px,
而且PC端浏览器调试手机模式下iPhone6的尺寸也是 375*667 px。
我们约定1rem = 50px,所以黄色矩形 width: 3.3rem; height: 1.9rem;
我们的设置html下font-size的值的js代码为
// 50是1rem等价于多少px,375是设计稿的宽度,这里我们除以了2
docEl.style.fontSize = 50 * (clientWidth / 375) + 'px';
效果:



源码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>rem</title>
<style>
div {
width: 3.3rem;
height: 1.9rem;
background-color: yellow;
}
</style>
</head>
<body>
<div></div>
<script>
(function(doc, win){
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
docEl.style.fontSize = 50 * (clientWidth / 375) + 'px';
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
</script>
</body>
</html>
额外概念
在为写这篇博客上网查资料的过程中,总结了几个与移动端开发相关的概念。
1.物理像素physical pixel
一个物理像素是显示器上最小的物理显示单位。
2.设备独立像素(也叫密度无关像素、css像素、逻辑像素)
device independent pixels(dips)
一种物理测量单位,基于计算机控制的坐标系统和抽象像素(虚拟像素),由底层系统的程序使用,转换为物理像素的应用。
3.设备像素比device pixel ratio(dpr)
定义了物理像素和设备独立像素的对应关系。
公式:设备像素比 = 物理像素 / 设备独立像素 (该值也是平时手机说的几倍屏几倍屏的值)
4.分辨率
比如图片是由1280个像素* 720个像素组成。
5.PPI(每英寸所拥有的像素)
PPI是用来描述屏幕的像素显示密度。
6.DPI(每英寸打印的点数)
DPI表示每英寸打印的点数。
前端移动开发之rem的更多相关文章
- 移动web开发之rem适配布局
移动web开发之rem适配布局 方案: 页面布局文字能否随着屏幕大小变化而变化 流式布局和flex布局主要针对于宽度布局,那高度如何布局? 怎样让屏幕发生变化的时候元素高度和宽度等比例缩放? 1. r ...
- web app开发之rem
CSS3新增了一个相对单位rem,官方的解释为“font size of the root element”,相对于根元素(html)的font size. rem,em,px单位的区别: rem单位 ...
- 前端工程化开发之yeoman、bower、grunt
上两遍文章介绍了前端模块化开发(以seaJs为例)和前端自动化开发(以grunt为例)的流程,参见: http://www.cnblogs.com/luozhihao/p/4818782.html ( ...
- 前端自动化开发之grunt
上篇文章介绍了前端模块化开发工具seaJs,利用seaJs我们可以轻松实现前端的模块化编程,参见http://www.cnblogs.com/luozhihao/p/4818782.html 那么今天 ...
- 前端模块化开发之seaJs
了解后端语言的童鞋一定听过模块化开发的概念,比如java.python等后端语言都有自己的模块化特性,然而和后端语言相比,javascript还尚未实现模块化的功能,虽然之后的更高版本可能引入模块化开 ...
- webApp移动开发之REM
最近发现一偏很好的文章,关于webAPP开发REM 一个css单位: 来自腾讯ISUX; web app变革之rem
- 移动web开发之rem的使用
为什么要使用rem 移动端设备尺寸五花八门,单纯使用px这个单位无法轻易适配,rem就可以为我们解决这个问题! 如何使用rem 1rem默认等于16px,这是因为页面的默认字体大小就是16px.r 代 ...
- 前端基础开发之HTML
简介: 1.HTML是什么? htyper ...
- #笔记# 移动前端开发之viewport
一般移动设备的浏览器都默认设置了一个 viewport ,并初始定义一个虚拟的layout viewport(布局视口),用于解决早期的页面在手机上显示的问题.下面我们来认识几个与 viewport ...
随机推荐
- idc市场
机房 idc服务商 ============================== 电信1.古城热线-西部数据中心于2001年正式投入运营,有经济技术开发区和高新技术产业开发区两个核心机房高新路电信广场 ...
- Mysql环境搭建(及中文乱码解决)
卸载MySQL 电脑已经安装过mysql的 卸载电脑上的mysql方法: 我的电脑-->右键-->属性-->高级系统设置-->环境变量-->系统变量里面-->找到环 ...
- WinFormEx
项目地址 : https://github.com/kelin-xycs/WinFormEx WinFormEx 一个 用 C# 写的 WinForm 扩展库 , 用于改善 WinForm 的 界面 ...
- pre-commit 钩子,代码质量检查:在 vue-cli 3.x 版本中,已经使用尤大改写的yorkie,yorkie实际是fork husky,然后做了一些定制化的改动,使得钩子能从package.json的 "gitHooks"属性中读取
pre-commit 钩子,代码质量检查:在 vue-cli 3.x 版本中,已经使用尤大改写的yorkie,yorkie实际是fork husky,然后做了一些定制化的改动,使得钩子能从packag ...
- mvc ajax访问后台时session过期无法跳转到Login页面问题解决
public class BaseController : Controller { protected User UserInfo { set { Session["UserInfo&qu ...
- 一次完整的HTTP事务是怎样一个过程?(转)
HTTP协议 关于HTTP协议可以参考以下: HTTP协议漫谈 http://kb.cnblogs.com/page/140611/ HTTP协议概览 http://www.cnblogs.com/v ...
- 将Long类型转为字母数字组合的jar包---Hashids
在设计数据库时,我有时喜欢使用自增Id,而不是uuid,但是在面对终端用户时,直接暴露id不是一个好的行为. 经过查询,可以使用 Hashids 这个jar包将id转为类似YouTube的大小写字母和 ...
- Java中产生随机数的两个方法
Java中产生随机数的两个方法 一.利用random方法来生成Java随机数. 在Java语言中生成Java随机数相对来说比较简单,因为有一个现成的方法可以使用.在Math类中,Java语言提供了一个 ...
- Python递归调用
递归调用:在调用一个函数过程中,直接或间接又调用该函数本身,称之为递归调用 递归必备的2个阶段 1递推 2回溯 当递推结束后就可以进行回溯了 Python默认设置递归层数为1000 递归示例: de ...
- SOA和微服务的原则及对比
一.面向服务设计的原则 服务可复用:不管是否存在即时复用的机会,服务均被设计为支持潜在的可复用 服务共享一个标准契约:为了与服务提供者交互,消费者需要导入服务提供者的服务契约,这个契约可以是一个IDL ...