关于移动端 rem 布局的一些总结
【资源一】基础知识恕不回顾
基础知识参考以下两篇博客:
http://isux.tencent.com/web-app-rem.html
http://www.w3cplus.com/css3/define-font-size-with-css3-rem
【资源二】淘宝m站首页的动态实现
学习http://m.taobao.com 首页的实现。
最近读到@大漠的新文章《使用Flexible实现手淘H5页面的终端适配》,和本部分有点关系。暂且加上来以供参考。(updated 2015-11-24)
源码进行美化、解读之后,基本布局部分的代码已经被我还原出来了:(2016-01-13补充:后来才发现,早就开源在github上了)
!function(win, lib) {
var timer,
doc = win.document,
docElem = doc.documentElement,
vpMeta = doc.querySelector('meta[name="viewport"]'),
flexMeta = doc.querySelector('meta[name="flexible"]'),
dpr = 0,
scale = 0,
flexible = lib.flexible || (lib.flexible = {});
// 设置了 viewport meta
if (vpMeta) {
console.warn("将根据已有的meta标签来设置缩放比例");
var initial = vpMeta.getAttribute("content").match(/initial\-scale=([\d\.]+)/);
if (initial) {
scale = parseFloat(initial[1]); // 已设置的 initialScale
dpr = parseInt(1 / scale); // 设备像素比 devicePixelRatio
}
}
// 设置了 flexible Meta
else if (flexMeta) {
var flexMetaContent = flexMeta.getAttribute("content");
if (flexMetaContent) {
var initial = flexMetaContent.match(/initial\-dpr=([\d\.]+)/),
maximum = flexMetaContent.match(/maximum\-dpr=([\d\.]+)/);
if (initial) {
dpr = parseFloat(initial[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
if (maximum) {
dpr = parseFloat(maximum[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
}
}
// viewport 或 flexible
// meta 均未设置
if (!dpr && !scale) {
// QST
// 这里的 第一句有什么用 ?
// 和 Android 有毛关系 ?
var u = (win.navigator.appVersion.match(/android/gi), win.navigator.appVersion.match(/iphone/gi)),
_dpr = win.devicePixelRatio;
// 所以这里似乎是将所有 Android 设备都设置为 1 了
dpr = u ? ( (_dpr >= 3 && (!dpr || dpr >= 3))
? 3
: (_dpr >= 2 && (!dpr || dpr >= 2))
? 2
: 1
)
: 1;
scale = 1 / dpr;
}
docElem.setAttribute("data-dpr", dpr);
// 插入 viewport meta
if (!vpMeta) {
vpMeta = doc.createElement("meta");
vpMeta.setAttribute("name", "viewport");
vpMeta.setAttribute("content",
"initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no");
if (docElem.firstElementChild) {
docElem.firstElementChild.appendChild(vpMeta)
} else {
var div = doc.createElement("div");
div.appendChild(vpMeta);
doc.write(div.innerHTML);
}
}
function setFontSize() {
var winWidth = docElem.getBoundingClientRect().width;
if (winWidth / dpr > 540) {
(winWidth = 540 * dpr);
}
// 根节点 fontSize 根据宽度决定
var baseSize = winWidth / 10;
docElem.style.fontSize = baseSize + "px";
flexible.rem = win.rem = baseSize;
}
// 调整窗口时重置
win.addEventListener("resize", function() {
clearTimeout(timer);
timer = setTimeout(setFontSize, 300);
}, false);
// 这一段是我自己加的
// orientationchange 时也需要重算下吧
win.addEventListener("orientationchange", function() {
clearTimeout(timer);
timer = setTimeout(setFontSize, 300);
}, false);
// pageshow
// keyword: 倒退 缓存相关
win.addEventListener("pageshow", function(e) {
if (e.persisted) {
clearTimeout(timer);
timer = setTimeout(setFontSize, 300);
}
}, false);
// 设置基准字体
if ("complete" === doc.readyState) {
doc.body.style.fontSize = 12 * dpr + "px";
} else {
doc.addEventListener("DOMContentLoaded", function() {
doc.body.style.fontSize = 12 * dpr + "px";
}, false);
}
setFontSize();
flexible.dpr = win.dpr = dpr;
flexible.refreshRem = setFontSize;
flexible.rem2px = function(d) {
var c = parseFloat(d) * this.rem;
if ("string" == typeof d && d.match(/rem$/)) {
c += "px";
}
return c;
};
flexible.px2rem = function(d) {
var c = parseFloat(d) / this.rem;
if ("string" == typeof d && d.match(/px$/)) {
c += "rem";
}
return c;
}
}(window, window.lib || (window.lib = {}));
注意:
淘宝首页在iPhone4上设置的initial-scale是0.5(其他尺寸类似)。
因此,这句在iPhone4上得出的结果是640:
```
var winWidth = docElem.getBoundingClientRect().width;
```
正是因为淘宝这种独特的设置,使得 ios 上 1px边框的问题完美解决(1px变2px, 又被 initial-scale=0.5
缩小了一半)。
【资源三】常规情况下js根据屏幕宽度动态计算
使用js动态计算:
!(function(doc, win) {
var docEle = doc.documentElement,
evt = "onorientationchange" in window ? "orientationchange" : "resize",
fn = function() {
var width = docEle.clientWidth;
width && (docEle.style.fontSize = 20 * (width / 320) + "px");
};
win.addEventListener(evt, fn, false);
doc.addEventListener("DOMContentLoaded", fn, false);
}(document, window));
【资源四】媒体查询较密集的断点
使用css3 media query 实现
@media screen and (min-width: 320px) {
html {font-size: 14px;}
}
@media screen and (min-width: 360px) {
html {font-size: 16px;}
}
@media screen and (min-width: 400px) {
html {font-size: 18px;}
}
@media screen and (min-width: 440px) {
html {font-size: 20px;}
}
@media screen and (min-width: 480px) {
html {font-size: 22px;}
}
@media screen and (min-width: 640px) {
html {font-size: 28px;}
}
【资源五】强大的单位——vw
使用单位 vw 实现动态计算。
html {
font-size: 31.25vw; /* 表达式:100*100vw/320 */
}
不过考虑到国内兼容性的问题,还是结合媒体查询来使用比较好。(媒体查询的断点暂时是借用上面的例子)
@media screen and (min-width: 320px) {
html {
font-size: 100px;
}
}
@media screen and (min-width: 360px) {
html {
font-size: 112.5px;
}
}
@media screen and (min-width: 400px) {
html {
font-size: 125px;
}
}
@media screen and (min-width: 440px) {
html {
font-size: 137.5px;
}
}
@media screen and (min-width: 480px) {
html {
font-size: 150px;
}
}
@media screen and (min-width: 640px) {
html {
font-size: 200px;
}
}
html {
font-size: 31.25vw;
}
【总结】
对以上种种方法的综合:
1、meta:viewport, 还是initial-scale为 1;
2、320px屏幕下,把页面根元素html的字体大小设置为50px;
3、鉴于我们拿到的设计图目前是640px宽的基准,这样我们就不用每次自己除以2了,直接在PS中量就好;
4、宽度什么的最好还是用百分比处理;涉及到高度、字体大小之类的则用rem。
eg:
设计稿上,div高度为40px;那么css就是 div {height: 0.4rem;}
结果就只剩下一步转换:设计稿上量的长度转化为小数。 50% => 0.5
这种计算,不要太简单。。。
【方法一】纯粹css,支持calc函数的动态计算;不支持的用css媒体查询断点,优雅降级。
@media screen and (min-width: 320px) {
html {
font-size: 50px;
}
}
@media screen and (min-width: 360px) {
html {
font-size: 56px;
}
}
@media screen and (min-width: 400px) {
html {
font-size: 63px;
}
}
@media screen and (min-width: 440px) {
html {
font-size: 69px;
}
}
@media screen and (min-width: 480px) {
html {
font-size: 75px;
}
}
/**
* 2016-01-13 订正
* 做适当限制
* 大于640的屏幕 固定为100px
* 同时需要对body或者最外层wrapper做max-width: 640px的限制
*/
/*
@media screen and (min-width: 640px) {
html {
font-size: 100px;
}
}
html {
font-size: 15.625vw;
}
*/
html {
font-size: 15.625vw;
}
@media screen and (min-width: 640px) {
html {
font-size: 100px;
}
}
【方法二】脚本动态计算
大前提:
1、initial-scale 为 1;
2、在项目css中(注意不要被公共的base、common之类的影响了,资源加载顺序也是蛮重要的),先把html的fontSize设置为 50px(或者加上媒体查询代码), 避免加载未完成时候样式错乱;
/* css */
html {font-size: 50px;}
/* javascript */
!(function(win, doc){
function setFontSize() {
// 获取window 宽度
// zepto实现 $(window).width()就是这么干的
var winWidth = window.innerWidth;
// doc.documentElement.style.fontSize = (winWidth / 640) * 100 + 'px' ;
// 2016-01-13 订正
// 640宽度以上进行限制 需要css进行配合
var size = (winWidth / 640) * 100;
doc.documentElement.style.fontSize = (size < 100 ? size : 100) + 'px' ;
}
var evt = 'onorientationchange' in win ? 'orientationchange' : 'resize';
var timer = null;
win.addEventListener(evt, function () {
clearTimeout(timer);
timer = setTimeout(setFontSize, 300);
}, false);
win.addEventListener("pageshow", function(e) {
if (e.persisted) {
clearTimeout(timer);
timer = setTimeout(setFontSize, 300);
}
}, false);
// 初始化
setFontSize();
}(window, document));
嗯。。。
就这么愉快地结束了。。。
不知道解读了某宝首页的一点点代码,然后发在这里,会不会有什么后果。。。
==================================================
2016年1月13日补充
写过这篇博客之后,又陆续读过几篇关于布局的文章。
具体已经忘了,大约是大漠的文章,还有一篇应该是搜车前端的博文,另外应该还有关于手淘首页的分析的文章。
另外,自己也用rem布局实践过几个项目。
不得不说,个人觉得rem布局现在已经可以放弃了。flex
布局已经很好用了,早已有之的百分比布局等稍用点心思也并不难。
这篇博客一直想改。但懒惰总是占据着我的身体。
最后再说下,字体大小自适应是错误的,字体大小自适应是错误的,字体大小自适应是错误的。
rem 布局,可以告别了。
迎接 flex 布局吧。
=========================================
写在最后
这篇博客写于半年前,那时候还是个刚毕业的菜鸟。
偶尔有点想法,看了一些大牛的文章,有了这篇博客。
这也是半年来唯一一篇产出。
5k的浏览量,95收藏,13推荐,已经让我很惊讶了。
谢谢各路大神们的关注。
半年来感受到的前端大环境变化还是很大。虽然在公司没有太多变化,但眼睛总得看着世界吧。
接下来,还得继续学习。
由于手上没什么项目,一直想探索出一套自己的自动化流程,但到现在也只是积累了许多版的草稿。
nodejs
方面也得有所探索,nodejs
再加上 shelljs
和 yargs
用起来是真的很爽。(鸣谢阮大神的文章)
算是年终总结了。在前端的路上继续走吧。
=========================================
一点想法:评论区的回复
媒体查询和js动态计算是两种方式。
首先,支持 CSS3 calc
方法 和 rem
、vw
单位的浏览器下,只需要html {font-size: 15.625vw;}
这样一句就好,另外加个媒体查询限制下。
之前的一大堆密集的断点只是为了hack不支持calc
或者calc
的情况。其次,js动态设置html的font-size
,只要浏览器支持rem单位即可。
为什么会考虑到密集的mq断点呢,因为当时还在考虑文字大小的自适应问题。
实践证明,字体大小自适应是一种错误的想法。
移动开发在必要情况的下,可以适当使用mq来调整字体大小,但做成完全自适应则是一种存在问题的做法。
因此,这里提到的 calc
和vh
rem
配合的做法,最好只用来做布局的工作。js动态计算也是类似,更适合做布局。
关于移动端 rem 布局的一些总结的更多相关文章
- 第130天:移动端-rem布局
一.关于布局方案 当拿到设计师给的UI设计图,前端的首要任务就是布局和样式,相信这对于大部分前端工程师来说已经不是什么难题了.移动端的布局相对PC较为简单,关键在于对不同设备的适配.之前介绍了一篇关于 ...
- 移动端REM布局模板(阿里高清方案)
移动端REM布局模板(阿里高清方案),蛮好的,转自: http://www.jianshu.com/p/985d26b40199 . <!DOCTYPE html> <html la ...
- 移动端Rem布局注意事项
1.布局的总体结构框架: 2.注意事项: (a):如果是左右两栏的布局方式,须在article的同级加一个aside: 因为是同级,所以必须设置同样的样式:而且他俩的父级,也就是sectio ...
- 一看就懂得移动端rem布局、rem如何换算
这里使用了js控制根元素的font-size大小,然后进行rem换算,在js代码后面会说明以下问题. 1.如何进行rem运算? 2.如果纯js控制根元素用rem布局会出现的小问题,如何解决? 3.如有 ...
- 移动端rem布局和百分比栅格化布局
移动端的rem: 使用方法: 设置html的font-size,根据浏览器分辨率缩放 设置根元素font-size为100px这样好用的值,不要设为10px这样的: 然后获取浏览器的分辨率,也就是视口 ...
- 移动端rem布局雪碧图解决方案 以及分享腾讯团队的在线雪碧图工具
先分享一下地址:http://alloyteam.github.io/gopng/ 使用的方法也很简单,将需要的小图标拖进去,全部拖进去后再调位置(每拖一个进去都会帮你排列好,但是没有间隔,所以全部拖 ...
- 第132天:移动web端-rem布局(进阶)
rem布局(进阶版) 该方案使用相当简单,把下面这段已压缩过的 原生JS(仅1kb,源码已在文章底部更新,2017/5/3) 放到 HTML 的 head 标签中即可(注:不要手动设置viewport ...
- 关于移动端rem 布局的一些总结
1.rem是什么? rem(font size of the root element)是指相对于根元素的字体大小的单位 2.为什么web app要使用rem? 实现强大的屏幕适配布局(淘宝,腾讯,网 ...
- 十八、移动端rem布局
使用rem布局,首先要知道自己是根据UI给的视效图的多少基准的,这里是以750px为基准,代码如下: //rem布局,此处根据750px来设置,放大100倍 (function(doc, win) { ...
随机推荐
- 我的Fedora22美化日记
首先我说一下,我命令是乱打的[不要打我],用之前先google 配置RPMFusion仓库 $ sudo dnf install --nogpgcheck http://download1.rpmfu ...
- ButterKnife使用小结
项目官网:http://jakewharton.github.io/butterknife/ Github主页:https://github.com/JakeWharton/butterknife 这 ...
- latex如何把目录页的页码去掉?
页眉的显示与关闭,清空,还有样式之间的切换,需要用到如下几个命令: \pagestyle 用于设置当前页以及后续页面的页眉显示情况(可称为页版式).中间页版式可由\thispagestyle命令来指 ...
- 大数据技术 vs 数据库一体机[转]
http://blog.sina.com.cn/s/blog_7ca5799101013dtb.html 目前,虽然大数据与数据库一体机都很火热,但相当一部分人却无法对深入了解这两者的本质区别.这里便 ...
- css多行文本垂直居中问题研究
css多行文本垂直居中问题研究 <body> <h2>垂直居中对齐</h2> <style> *{margin:0; padding:0;} div { ...
- Qt监测光驱变化(使用WM_DEVICECHANGE)
xxx.h protected: bool winEvent(MSG *msg,long * result); xxx.cpp bool CBlurayTranscoderDlg::winEvent( ...
- 【转载】Android Studio jar、so、library项目依赖,原文链接http://zhengxiaopeng.com/2014/12/13/Android-Studio-jar、so、library项目依赖/
前言 Android Studio(以下简称AS)在13年I/O大会后放出预览版到现在放出的正式版1.0(PS.今天又更新到1.0.1了)历时一年多了,虽然Google官方推出的Android开发者的 ...
- Ext2文件系统布局,文件数据块寻址,VFS虚拟文件系统
注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...
- 判断两个XML文件结构与内容是否相同
1. 引入 目前公司的这款软件导入导出数据库信息的方法是:组织数据的内容和结构 利用MS com的sax解析 储存数据为XML格式 优点是可以选择部分导出 缺点是速度慢文件导出的文件庞大,若客户出现 ...
- [LeetCode]题解(python):134-Gas Station
题目来源: https://leetcode.com/problems/gas-station/ 题意分析: 在一个圈子路线里面有N个汽油站,i站的汽油有gas[i]汽油.现在有一辆无限容量的车,它从 ...