主题 HTML
移动端页面开发适配 rem布局原理

什么是适配,为什么要适配

我们拿到的设计图一般是以640,750,1080分辨率为基准设计的,而现在的手机终端各式各样,分辨率不同,逻辑像素不同 ,适口不同,所以为了让我们的页面在每个设备上都可以良好的展示,那么就需要为这些设备做统一的处理,这个过程就称为移动端适配。

需要知道的一些概念:

物理像素(physical pixel)

一个物理像素是显示器(手机屏幕)上最小的物理显示单元,可以理解为我们平时说的分辨率;

设备独立像素(density-independent pixel)

设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如 css像素),然后由相关系统转换为物理像素,在这里可以理解为我们说的视觉视口的大小;

所以说,物理像素和设备独立像素之间存在着一定的对应关系,这就是接下来要说的设备像素比。

设备像素比(device pixel ratio)

设备像素比(简称dpr)定义了物理像素和设备独立像素的对应关系,它的值可以按如下的公式的得到:

设备像素比 = 物理像素 设备独立像素 在某一方向上,x方向或者y方向

设备像素比也是设备生产的时候设置好的,在javascript中,可以通window.devicePixelRatio获取到当前设备的dpr。

视口(viewport)

pc端视口指浏览器窗口内的内容区域,不包含工具条,滚动条.

移动浏览器中视口分为几种情况

metaname=viewportcontent=“width=device-width,minimum-scale=1.0,maximum-scale=1.0”中content所设置的视口,称为布局视口,最大值由浏览器厂商规定 ,可以document.documentElement.clientWidth获取其宽度.

而我们看到的浏览器的窗口,网页区域的大小,称为视觉视口,用css像素表示(设备逻辑像素)

rem

rem是css3 的一个长度单位 ,相对文档跟元素 html;比如设置html font-size=100px;那么1rem=100px;之后的所有元素都可以用这个基准值来设置大小;

常用的方案:

固定高度,宽度自适应(百分比,em)

使用 rem布局

下面总结了网易 淘宝首页使用rem的方案

网易的做法:

1) 将布局适口设置为视觉适口,不进行缩放,即理想适口。

meta name=viewportcontent=initial-scale=1,maximum-scale=1, minimum-scale=1”

2) 以设计稿分辨率为基准,取100px为font-size的参照,那么body元素的宽度就可以设置为width6.4rem(640100),当我们将布局视口设置为320时,于是html的 font-size=deviceWidth 6.4。

3) 通过document.documentElement.clientWidth获取 deviceWidth;

4) 当页面的dom ready后设置html font-size,

document.documentElement.style.fontSize =document.documentElement.clientWidth 6.4 + ‘px’
5) 通过 mediaQuery 设置字体大小,字体大小不可以使用rem,原因是误差太大。

以640的设计稿为例最终的设置html font-size代码如下,布局时拿设计稿标注的尺寸除以100,就是rem的值,相当简单啊

var deviceWidth = document.documentElement.clientWidth;
if(deviceWidth 640) deviceWidth = 640;
document.documentElement.style.fontSize = deviceWidth 6.4 + 'px';
这里if(deviceWidth 640) deviceWidth = 640; 是因为当deviceWidth大于640时物理分辨率已经大于1280(取决于 dpr ),应该去访问pc的网站;

淘宝的做法:

原理

1) 通过dpr设置缩放比,实现布局视口大小,

var scale = 1 devicePixelRatio;
document.querySelector('meta[name=viewport]').setAttribute('content','initial-scale='+ scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
2) 动态计算html的font-size

document.documentElement.style.fontSize = document.documentElement.clientWidth 10 + ‘px’;
这里的意思是,clientWidth 10 得到是布局视口下的rem基准值(以iphone6为例 1rem=75px),那么设计稿正好也是 750,所以对应的关系 clientWidth 10==设计稿的尺寸x, 那么x=设计稿的尺寸rem基准值。

如果是iphone6 plus rem基准值等于clientWidth 10 等于124.2,那么x=750124.2。

关于具体的实现 淘宝提供了一个开源的方案lib-flexible: httpsgithub.comamfelib-f... ;

具体逻辑 :

1)判断head中是否设置了viewport,如果有设置,按照已有viewport 设置缩放比;

if (metaEl) {
console.warn('将根据已有的meta标签来设置缩放比例');
var match = metaEl.getAttribute('content').match(initial-scale=([d.]+));
if (match) {
scale = parseFloat(match[1]);
dpr = parseInt(1 scale);
}
}
2)如果没有设置meta viewport,判断是否设置dpr,如果有,通过dpr计算缩放scale。

var content = flexibleEl.getAttribute('content');
if (content) {
var initialDpr = content.match(initial-dpr=([d.]+));
var maximumDpr = content.match(maximum-dpr=([d.]+));maximum 设置最大值,与initial的值比较,取最小值;
if (initialDpr) {
dpr = parseFloat(initialDpr[1]);
scale = parseFloat((1 dpr).toFixed(2));
}
if (maximumDpr) {
dpr = parseFloat(maximumDpr[1]);
scale = parseFloat((1 dpr).toFixed(2));
}
}
3)如果 dpr &scale都没有设置,那么就通过设备的dpr设置起缩放 scale,

if (!dpr && !scale) {meta[name=viewport]&&meta[name=flexible]都不存在。

var isAndroid = win.navigator.appVersion.match(androidgi);
var isIPhone = win.navigator.appVersion.match(iphonegi);
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;
}
4)得到scale之后 ,如果meta 的viewport不存在,那么就创建一个meta[name=“viewport”],将scale配置进去。

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);

}
5)动态改写html的font-size

var width = docEl.getBoundingClientRect().width;获取html的宽度

if (width dpr 540) {判断屏幕逻辑像素大于540时,取540
width = 540 dpr;
}
var rem = width 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
总结:

使用rem布局,实质都是通过动态改写html的font-size基准值,来实现不同设备下的良好统一适配;

网易与淘宝不同 的地方是 ,网易将布局视口设置成了 视觉视口,淘宝将布局视口设置成了物理像素大小,通过 scale缩放嵌入了 视觉视口中;

容器元素的字体大小都不使用rem,需要额外的media查询;

移动端页面开发适配 rem布局原理的更多相关文章

  1. 移动端(手机端)页面自适应解决方案—rem布局篇

    移动端(手机端)页面自适应解决方案-rem布局 假设设计妹妹给我们的设计稿尺寸为750 * 1340.结合网易.淘宝移动端首页html元素上的动态font-size属性.设计稿尺寸.前端与设计之间协作 ...

  2. rem布局原理深度理解(以及em/vw/vh)

    一.前言 我们h5项目终端适配采用的是淘宝那套<Flexible实现手淘H5页面的终端适配>方案.主要原理是rem布局.最近和别人谈弹性布局原理,发现虽然已经使用了那套方案很久,但是自己对 ...

  3. 手机端页面自适应解决方案—rem布局进阶版

    手机端页面自适应解决方案—rem布局进阶版   https://www.jianshu.com/p/985d26b40199 注:本文转载之处:https://www.cnblogs.com/anni ...

  4. 手机端页面自适应解决方案—rem布局(进阶版,附源码示例)

    转自:https://segmentfault.com/a/1190000007350680 一年前笔者写了一篇 <手机端页面自适应解决方案—rem布局>,意外受到很多朋友的关注和喜欢.但 ...

  5. 使用vw做移动端页面的适配

    Flexible到今天也有几年的历史了,解救了很多同学针对于H5页面布局的适配问题.而这套方案也相对而言是一个较为成熟的方案.简单的回忆一下,当初为了能让页面更好的适配各种不同的终端,通过Hack手段 ...

  6. 手机端页面自适应之rem布局

    W3C官网上是这样描述rem的--"font size of the root element" . rem布局在移动端发挥的比较好. 阿里团队高清方案: <script&g ...

  7. 移动端页面怎么适配ios页面

    1.viewport 简单粗暴的方式:<meta name="viewport" content="width=320,maximum-scale=1.3,user ...

  8. 手机端页面自适应解决方案-rem布局

    rem布局 布局前插入原生js即可 (function (doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationch ...

  9. 手机端页面自适应:rem布局

    rem布局非常简单,首页你只需在页面引入这段原生js代码就可以了 (function (doc, win) { var docEl = doc.documentElement, resizeEvt = ...

随机推荐

  1. jquery easyui的datagrid在初始化的时候会请求两次URL?

    我们项目前端用的是jquery easyui,刚开始使用datagrid加载列表初始化时总是请求两次URL,这让人非常不解,怎么总是请求两次呢?数据一多,加载速度明显变慢,通过查资料才知道原来是重复声 ...

  2. bzoj4031 [HEOI2015]小Z的房间

    Description 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时候,相邻的格子之间都有墙隔着. ...

  3. jQuery 对页面元素的搜索包括父元素、同辈元素、子元素的搜索

    1.父元素搜索 (1)parents([selector]) 方法 $("p").parents().css("border","1px solid ...

  4. 开始使用gentoo linux——gentoo安装笔记(上)

    gentoo linux安装笔记(上) 家里有一台破旧的富士通笔记本,08年至今质量依然杠杠的,但是性能已经不能和现代超极本同日而语,装上了ubuntu更是不敢恭维,别提gnome和kde的linux ...

  5. 【算法系列学习】线段树 单点覆盖,区间查询最大值 [kuangbin带你飞]专题七 线段树 B - I Hate It

    https://vjudge.net/contest/66989#overview #include<iostream> #include<cstdio> #include&l ...

  6. 基于Struts2的SpringMVC入门

    1.SpringMVC概述 (1)SpringMVC为表现层提供基础的基于MVC设计理念的优秀Web框架, (2)SpringMVC通过一套mvc的注解,让POJO成为处理请求的控制器,而无需任何接口 ...

  7. 最准确的单点登录SSO图示和讲解(有代码范例)|手把手教做单点登录(SSO)系列之二

    写第一篇博客<手把手教做单点登录(SSO)系列之一:概述与示例>,就获得了园子里朋友们热情的评论和推荐,感谢各位. 我那篇文章同时发了CSDN和博客园.对比一下,更感受到博客园童鞋们的技术 ...

  8. Spring boot 默认静态资源路径与手动配置访问路径

    在application.propertis中配置 ##端口号server.port=8081 ##默认前缀spring.mvc.view.prefix=/## 响应页面默认后缀spring.mvc. ...

  9. python课程day_2-->总结-->字符串功能

    =======================课程大纲=======================> 基本数据类型 - 整数 - 布尔值 - 字符串 - 列表 - 元组 - 字典 - 集合 工 ...

  10. MapControl Application 添加自定义的工具条

    现在想用二次开发做一些东西,然后需要自定义的工具条,但是如何向MapControl Application 添加自定义的工具条呢,经过多次试验后,终于找到了相应的方法(左图是添加自定义的工具条之前,右 ...