背景介绍

目前,随着移动设备的普及和4G网络的普及,web在移动端的占比已经远远超过PC端,各种H5页面推广页面,H5小游戏热度火爆。以前简单的使用px单位(没有弹性)的时代已经无法满足各位设计师和用户了。如何100%还原UI设计师的设计图,一直困扰着前端工程师。

css单位

学习首先我们简单了解下css目前都支持哪些单位:

  • px: 设置固定的布局或者元素大小,缺点是没有弹性
  • em: 参考父元素的font-size,em会继承父级元素的字体大小,em的值并不是固定的
  • rem: 相对根元素html的font-size
  • %: 相对父元素,对于position: absolute;的元素是相对于已定位的父元素,对于position: fixed;的元素是相对于ViewPort(可视窗口)
  • vw: view width的简写, 是指可视窗口的宽度,浏览器宽度1200px, 1 vw = 1200px/100 = 12 px
  • vh: view height的简写,是指可视窗口的高度,浏览器高度900px, 1 vh = 900px/100 = 9 px
  • vm: 相对于视口的宽度或高度中较小的那个, 其中最小的那个被均分为100单位的vm,浏览器高度900px,宽度1200px,取最小的浏览器高度,1 vm = 900px/100 = 9 px
  • in: 寸
  • cm: 厘米
  • mm: 毫米
  • pt: point, 大约1/72寸
  • pc: pica, 大约6pt, 1/6寸

具有弹性布局能力的单位:

  • em,%: 相对于父元素
  • rem: 相对于html
  • vw, vh, vm: 相对于可视窗口

从上可以看出,要做页面整体弹窗缩放的话,使用rem, vm, vw, vh更适合,因为任何内容都可以找到同一个基准。

HTML viewport基础

概念

viewport 是用户网页的可视区域。

手机浏览器是把页面放在一个虚拟的"窗口"(viewport)中,通常这个虚拟的"窗口"(viewport)比屏幕宽,这样就不用把每个网页挤到很小的窗口中(这样会破坏没有针对手机浏览器优化的网页的布局),用户可以通过平移和缩放来看网页的不同部分。

用法

<meta name="viewport" content="width=device-width, initial-scale=1.0">

属性说明

  • width:控制 viewport 的大小,可以指定的一个值,如 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)。
  • height:和 width 相对应,指定高度。
  • initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例,默认值1。
  • maximum-scale:允许用户缩放到的最大比例。
  • minimum-scale:允许用户缩放到的最小比例。
  • user-scalable:用户是否可以手动缩放。

弹性布局方案

通过以上可以看出,使用弹性布局的css单位配合设置html viewport元信息,就可以实现整体页面的弹性布局(包含字体大小)。

先弄明白几个概念:

设备分辨率:一个物理像素是显示器(手机屏幕)上最小的物理显示单元,在操作系统的调度下,每一个设备像素都有自己的颜色值和亮度值;
设备屏幕宽度:设备显示器的实际宽度;
DPR:设备上物理像素和设备独立像素(device-independent pixels (dips))的比例,DPR = 设备分辨率/设备屏幕宽度;
300ppi:每英寸300个像素点

思路

根据以上的概念,那么,我们知道

window.devicePixelRatio = document.body.clientWidth / window.screen.width;

如果屏幕分辨率宽是1080px,屏幕宽度为360px,那么DPR=1080/360=3。

如果现在UI设计图也是1080px,那么前端工程师不想丢失任何细节的使用代码如何还原呢?

可以设置屏幕宽度为1080px, 设置viewport属性initial-scale = 1/3;

这样360px的屏幕就可以容纳1080px宽的内容了。

但是每个手机的分辨率都不一样,那么如何来设置这个这个initial-scale呢?我们可以通过以下方式:

var scale = 1 / window.devicePixelRatio;
document.querySelector('meta[name="viewport"]').setAttribute('content', 'user-scalable=no,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale);

将user-scalable设置为no, 不允许缩放,有缩放需要的,可以不设置

之后如何设置某一个区块的宽,高,或者字体大小呢?

我们还需要设置html标签,字体的大小,我习惯于使用设计图的宽/20来获取元素的rem数值。比如

  • UI设计图文字大小30px, 那么我习惯使用 font-size: 1.5rem;
  • UI设计图图片宽100px, 我习惯使用 width: 5rem;

那么我会设置html的font-size为 deviceWidht / (UI设计图宽/20);

var base = 720 / 20; // 720为UI设计稿的宽
var fontSize = deviceWidth / base;
document.documentElement.style.fontSize = fontSize + 'px';

结合以上,完整代码为:

<script type="text/javascript">
var scale = 1 / window.devicePixelRatio;
document.querySelector('meta[name="viewport"]').setAttribute('content', 'user-scalable=no,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale);
window.onresize = function (base) {
  var deviceWidth = (document.body.clientWidth < document.documentElement.clientWidth) ? document.body.clientWidth : document.documentElement.clientWidth;
  var screenWidth = window.screen.width;
  if (deviceWidth / screenWidth != window.devicePixelRatio) {
    document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no');
    deviceWidth = (document.body.clientWidth < document.documentElement.clientWidth) ? document.body.clientWidth : document.documentElement.clientWidth;
  }
  var fontSize = deviceWidth / base;
  document.documentElement.style.fontSize = fontSize + 'px';
};
window.onresize(720);
</script>

以上代码我放在<head>里面,在html标签渲染前就开始设置。

一开始就根据DPR设置initial-scale,之后在onresize里面设置html字体大小。

大家会注意到onresize里面有这样一段代码:

var deviceWidth = (document.body.clientWidth < document.documentElement.clientWidth) ? document.body.clientWidth : document.documentElement.clientWidth;
var screenWidth = window.screen.width;
if (deviceWidth / screenWidth != window.devicePixelRatio) {
  document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no');
  deviceWidth = (document.body.clientWidth < document.documentElement.clientWidth) ? document.body.clientWidth : document.documentElement.clientWidth;
}

这一段代码是为了兼容一部分旧款机器,这些机器无法正常的获取到DPR值,那么我们就只能设置屏幕页面内容宽度为设备宽度。

有疑问,欢迎联系博主讨论。

适用于移动设备弹性布局的js脚本(rem单位)的更多相关文章

  1. 【前端开发】移动端适配方案js,rem单位转换,640设计稿20px=1rem

    ! function() { var style = document.createElement("STYLE"), docEl = document.documentEleme ...

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

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

  3. web app 自适应方案总结 弹性布局之rem

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

  4. web app 自适应 弹性布局之rem

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

  5. Flex弹性布局在移动设备上的应用

    引文 首先,我们有表格布局.当不考虑语义并且利用一些适当的嵌套和其他技巧,我们可以用table建立具有一定功能的布局. 然后是现在大多数人都在使用的浮动布局.我们可以使用任何我们想用的元素,但浮动并不 ...

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

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

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

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

  8. 基于淘宝弹性布局方案lib-flexible的问题研究

    上篇文章<淘宝弹性布局方案lib-flexible实践>结合一个简单的实例,说明了lib-flexible的基本用法,但是lib-flexible的这种适配方式在适配的时候会修改viewp ...

  9. 百度在PWA中阐述的弹性布局-[CSS]

    原文链接 响应式布局 自从进入移动互联网时代,响应式布局这个词经常出现在 Web 设计和开发领域,它让 Web 页面在不同尺寸的设备上都具有良好的浏览体验. 开始之前 在讲解响应式布局之前,需要先了解 ...

随机推荐

  1. pyCharm django 中新加app

    1.在manage.py@djangotest中输入命令: 1.startapp   realnameauth   ---新建一个app,名字为realnameauth 2.在 django 项目中的 ...

  2. CSS3圆环动态弹出菜单

    体验效果:http://hovertree.com/texiao/css3/44/ 代码如下: <!DOCTYPE html> <html lang="zh"&g ...

  3. D1 java概述

    首先扯点别的.在学习知识的过程中非常重要的一点是沟通交流,拿自学java来说绝不是抱着一本Head First Java闷头看.感觉自学入门这一阶段相当于启蒙,绝不能向无头苍蝇一样到处乱撞.java的 ...

  4. Spring Security框架下Restful Token的验证方案

    项目使用Restful的规范,权限内容的访问,考虑使用Token验证的权限解决方案. 验证方案(简要概括): 首先,用户需要登陆,成功登陆后返回一个Token串: 然后用户访问有权限的内容时需要上传T ...

  5. s21day20 python笔记

    s21day20 python笔记 一.内容回顾 面向对象的三大特性 封装 函数封装到类 数据封装到对象 继承 多态 二.成员 2.1 类成员 类变量(静态字段) 定义:写在类的下一级,和方法同一级 ...

  6. cf——C. Serval and Parenthesis Sequence

    括号正确匹配问题,应该不难 #include <iostream> #include <cstring> #include <string> #include &l ...

  7. Python:从入门到实践--第十一章--测试代码--练习

    #1.城市和国家:编写一个函数,它接受两个形参:一个城市名和一个国家名. #这个函数返回一个格式为City,Country的字符串,如Santiago,Chile.将这个函数 #存储在一个名为city ...

  8. ASCII工具类

    对字符串简单的加密解密 描述:加密的时候对每个字符转成ASCII的时候进行 +1操作,最后用 “/” 拼接,解密原理相反. /** * ASCII 工具类 * Created by Administr ...

  9. 前端代理----whistle

    场景一:如何将本地的请求代理到服务器上(如果接口没有校验登陆的情况) 最简单的方法:在项目文件中找到webpack开发环境的配置文件,配置devServer对象 devServer: { conten ...

  10. Codeforces 977E:Cyclic Components(并查集)

    题意 给出nnn个顶点和mmm条边,求这个图中环的个数 思路 利用并查集的性质,环上的顶点都在同一个集合中 在输入的时候记录下来每个顶点的度数,查找两个点相连,且度数均为222的点,如果这两个点的父节 ...