用rem来实现移动端的弹性布局是个好主意!用法如下:

CSS

@media only screen and (max-width: 320px), only screen and (max-device-width:320px) {
html {
font-size:10px;
}
}
@media only screen and (max-width: 640px), only screen and (max-device-width:640px) {
html {
font-size:20px;
}
}
.test-div{width: 10rem;}

那么这个.test-div的宽度在320px的分辨率下会是10 * 10 = 100px, 在640下是10 * 20 = 200px,从而达到了弹性缩放的目的。

但是这样做还是有2个问题:

1. 随着各种新手机的发布,分辨率也碎片化了,我们无法预知将来会出现的分辨率宽度,我们不可能把所有要兼容的分辨率写到css里。

2. 这样写只能做到页面适配不同的宽度,对于那种在各种屏幕上都要在一屏幕内显示的页面,就没有办法适配了。

比如这种非常流行的整屏滑动页面,当屏幕宽高比小于设计稿的比例时会缩放:

所以完美解决适配的问题就得靠js了,思路非常简单,判断一下当前终端的宽度(这里在安卓上有个坑,后面会说)和设计稿宽度的比例,计算出需要缩放的倍数,然后根据这个倍数值改变html的字体大小即可。

如果需要横竖屏都适配,那么根据终端宽高比例较小的那一个来计算。用通俗的语言来说,如果终端屏幕比设计稿更加宽矮一些,那么久根据它和设计稿的高度比例来计算字体。

思路永远是简单,实现永远是有问题需要解决的,先上代码:

https://github.com/leon776/setHtmlRem

JAVASCRIPT

console.time("test");
/*
# 按照宽高比例设定html字体, width=device-width initial-scale=1版
# @pargam win 窗口window对象
# @pargam option{
designWidth: 设计稿宽度,必须
designHeight: 设计稿高度,不传的话则比例按照宽度来计算,可选
designFontSize: 设计稿宽高下用于计算的字体大小,默认20,可选
callback: 字体计算之后的回调函数,可选
}
# return Boolean;
# xiaoweili@tencent.com
# ps:请尽量第一时间运行此js计算字体
*/
!function(win, option) {
var count = 0,
designWidth = option.designWidth,
designHeight = option.designHeight || 0,
designFontSize = option.designFontSize || 20,
callback = option.callback || null,
root = document.documentElement,
body = document.body,
rootWidth, newSize, t, self;
root.style.width = 100%;
//返回root元素字体计算结果
function _getNewFontSize() {
var scale = designHeight !== 0 ? Math.min(win.innerWidth / designWidth, win.innerHeight / designHeight) : win.innerWidth / designWidth;
return parseInt( scale * 10000 * designFontSize ) / 10000;
}
!function () {
rootWidth = root.getBoundingClientRect().width;
self = self ? self : arguments.callee;
//如果此时屏幕宽度不准确,就尝试再次获取分辨率,只尝试20次,否则使用win.innerWidth计算
if( rootWidth !== win.innerWidth && count < 20 ) {
win.setTimeout(function () {
count++;
self();
}, 0);
} else {
newSize = _getNewFontSize();
//如果css已经兼容当前分辨率就不管了
if( newSize + 'px' !== getComputedStyle(root)['font-size'] ) {
root.style.fontSize = newSize + "px";
return callback && callback(newSize);
};
};
}();
//横竖屏切换的时候改变fontSize,根据需要选择使用
win.addEventListener("onorientationchange" in window ? "orientationchange" : "resize", function() {
clearTimeout(t);
t = setTimeout(function () {
self();
}, 300);
}, false);
}(window, {
designWidth: 640,
designHeight: 1136,
designFontSize: 20,
callback: function (argument) {
console.timeEnd("test")
}
});

然后再说几个点和问题:1. 这段代码对viewport有要求,必须是width=device-width initial-scale=1,即窗口的大小是设备物理宽度(分辨率 / devicePixelRatio),并且禁止缩放。另外还有一种做法就是手机淘宝的做法,窗口大小是分辨率宽度,然后缩放倍数是1/devicePixelRatio,这里暂且不讨论。

2.就是解决安卓上的问题。经过实测,有些安卓机器,使用1的viewport,在页面刚加载的时候。不管是读取window.innerWidth,还是doc的getBoundingClientRect().width,或者是body的clientWidth,都不是设备的物理宽度。所以只好祭出黑魔法setTimeout,一试果然可以,异步100ms执行获取屏幕宽度的代码就准确了。但是这种不可控的代码让人不爽。

因为width=device-width initial-scale=1,documentElement的宽度又是100%,所以当这两个值相等的时候我们可以认为目前获取到的屏幕宽度是准确的。那么使用此条件作为判断条件,不断的setTimeout(fun(){}, 0)去判断,当此条件为真时改变documentElement的字体。可以尽可能快的执行目标代码。但是又万一这两个值一直不相等又不能无限的死循环下去,所以设置了一个尝试上限,到上限之后用窗口宽度来计算(缩放比例不对的话用户起码可以看到完整的页面)。在chrome下测试,执行40次代码的平均时间是230ms,考虑到安卓机的js引擎速度,将上限设为了20。

3.是执行时机,个人建议将这段代码放到head里,第一时间计算好html的fontSize,避免重绘。如果你有有一些跟获取dom元素尺寸相关的操作,就得放到这个计算函数的回调里面了,这时候就不能放到head里(因为运行的时候dom都还没加载),只能放到底部或者doc的ready事件里了。最佳实践是有一个全屏的loading画面,当fontSize计算好了之后再把真正的页面展示出来。

30行js让你的rem弹性布局适配所有分辨率(含竖屏适配)(转载)的更多相关文章

  1. 30行js让你的rem弹性布局适配所有分辨率(含竖屏适配)

    用rem来实现移动端的弹性布局是个好主意!用法如下: CSS @media only screen and (max-width: 320px), only screen and (max-devic ...

  2. 不到30行JS代码实现的Excel表格

    不到30行JS代码实现的Excel表格,jQuery并非不可替代 某国外程序员展示了一个由原生JS写成不依赖第三方库的,Excel表格应用,有以下特性: 由不足30行的原生JavaScript代码实现 ...

  3. 30行js rem弹性布局适配所有分辨率

    <script> /* # 按照宽高比例设定html字体, width=device-width initial-scale=1版 # @pargam win 窗口window对象 # @ ...

  4. [JS代码]如何判断ipad或者iphone是否为横屏或者竖屏 - portrait或者landscape

    //判断横屏或者竖屏 function orient() { //alert('gete'); if (window.orientation == 0 || window.orientation == ...

  5. css弹性布局

    1.弹性布局是什么 在移动端一种方便的布局方式,打破了之前用浮动,定位的布局,更加灵活. 2.弹性布局的格式 包含父元素和子元素,有对应的属性应用在父元素和子元素达到布局的目的 3.父元素的属性 要开 ...

  6. 适用于移动设备弹性布局的js脚本(rem单位)

    背景介绍 目前,随着移动设备的普及和4G网络的普及,web在移动端的占比已经远远超过PC端,各种H5页面推广页面,H5小游戏热度火爆.以前简单的使用px单位(没有弹性)的时代已经无法满足各位设计师和用 ...

  7. 30行代码让你理解angular依赖注入:angular 依赖注入原理

    依赖注入(Dependency Injection,简称DI)是像C#,java等典型的面向对象语言框架设计原则控制反转的一种典型的一种实现方式,angular把它引入到js中,介绍angular依赖 ...

  8. 30行代码搞定WCF并发性能测试

    [以下只是个人观点,欢迎交流] 30行代码搞定WCF并发性能 轻量级测试. 1. 调用并发测试接口 static void Main()         {               List< ...

  9. web app 自适应方案总结 关键字 弹性布局之rem

    关于rem,主要参考文档 1.腾讯ISUX (http://isux.tencent.com/web-app-rem.html) 2.http://www.w3cplus.com/css3/defin ...

随机推荐

  1. C# 用QQ企业邮箱发邮件

    问题System.Net.Mail下的SmtpClient来发送邮件,而System.Net.Mail only仅支持Explicit SSL 不要465端口,用25,不用EnableSsl = tr ...

  2. Eclipse Git提交代码,多了一个“工程同名的文件夹”,找不到解决办法!!!

    提交代码到Git仓库,有2种方式. 第1种,先在OSChina等平台创建git项目,本地clone,再在本地修改代码提交.√ 这种方式,没任何问题. 不过,我平时不喜欢这么干. 第2种,本地已经有了项 ...

  3. 【python】Selenium隐藏控制台解决办法

    一.起因: 使用selenium 驱动浏览器的时候,如果使用headless模式,会有dos窗口弹出,输出监听信息,有时不想看到,很是麻烦. 二.解决办法: 修改源码:Lib \ site-packa ...

  4. c++ 方框中绘制菜单代码

    绘制静态菜单 getch与getchar 接收光标控制 一.绘制静态菜单 编写函数void mainmenu( void) 二.getch与getchar getch()的作用是从键盘接收一个字 ...

  5. 原来new的java对象不是所有的都存在堆内存

    JVM在晚期(运行期)优化时,使用到一种技术----逃逸分析. 补充说明:逃逸分析在1999年就已提出,但是JDK1.6才实现逃逸分析.而且,这项优化目前仍不成熟,仍有很大改进余地. 这是大坑啊,目前 ...

  6. window.location.hash 页面跳转,精确定位,实例展示:

    window.location.hash 页面跳转,精确定位,实例展示: (1).index.phtml,页面用于传参 <script id="bb_list_template&quo ...

  7. String与Date的互相转换

    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 也可以: SimpleDateFormat sd ...

  8. 大学生Linux常用命令(一)

    大学生Linux常用命令(一) 1.1 命令格式 命令格式一般为---命令名 [选项] [参数1] [参数2]- 例如:cp -I file1 cp为命令名,-l为选项,file1为参数. 其中,命令 ...

  9. 在WebGL场景中进行棋盘操作的实验

    这篇文章讨论如何在基于Babylon.js的WebGL场景中,建立棋盘状的地块和多个可选择的棋子对象,在点选棋子时显示棋子的移动范围,并且在点击移动范围内的空白地块时向目标地块移动棋子.在这一过程中要 ...

  10. vim文本编辑工具(全)

    VIM文本编辑工具 编辑模式 i    在当前字符前插入I   在光标所在的行首插入a 在当前字符后插入A 在光标所在行尾插入o 在当前行的下一行插入新的一行O 在当前行的上一行插入新的一行 s   ...