本文主要针对初学移动端web开发的读者,笔者也是初学者,文中有众多用词不当之处望读者指正。

前言

从开始做web app开发到现在,一直对移动端的尺寸适配有一种模糊的概念。能说得上来‘媒体查询’,‘栅格化布局’,‘流式布局’等若干技术名词和实现方式,但是每次自己做web app开发的时候,做出来的产物总是不尽人意,比如在iPhone5上出现文字溢出,调整好的布局位置在一些小尺寸手机上发现位置非常不对,或是遮盖了其他元素,或是换行了。

如果是之前,我是这样的做法:

不断写媒体查询做兼容,直到PM或者QA满意为止。

这样的方法,存在以下几个问题:

  1. 难以适应所有的手机屏幕尺寸,总是会有不兼容的尺寸出现,问题仍然存在,只是尚未被发现。
  2. 太累了,非常折磨人。特别是这些问题一般会集中涌现在上线前被一并提出来,而那个时候正好是压力最大的时候。

我想了想,为什么会出现治标不治本的情况:

  1. 在项目开始的时候没和UI协调好规范。
  2. 身边没有太多的测试机,没法测试得太全面。
  3. 没有意识到移动端适配是一个棘手的问题。

那么,有没有那样一种一劳永逸全尺寸支持不用动脑子算的移动端尺寸适配方案呢?

**答案当然是有的。**笔者结合了自己所看的几篇热门的博客,总结了其中比较有用的几个知识点,希望能让读者更快的掌握并使用这个'一劳永逸的方法'。能偷懒的事情绝对要偷懒。?(热门博客题目如图,含flexible的github repo)

我们要达到的效果

  • 直接根据UI的标注视觉稿上面的尺寸进行开发。如标注的是230px, 通过函数将其转为rem而不用人工计算。
  • 在大部分的手机机型上看起来的页面视觉效果都一致。

什么是rem

一句话概括: 假如<html>标签上设置了样式font-size:16px,那么 1rem = 16px。 所以:

与UI的配合

首先,需要和UI小姐姐说一句话:

"标注元素的时候请按照750px * 1334px为准。"

那么,你将会拿到一张如下的标注图:

【核心】动态计算+rem

到这一步,我们仍然没有解决核心问题:

  1. 要自己去将px换算成rem。(可能旁边会放一个计算器)
  2. 全尺寸适配。

接下来,就是最为核心的环节了,笔者通过步骤图向大家还原计算的过程。

第一步:假设有三款不同长宽的手机。

第二步:把手机的宽分为10份,那么上述三款手机的每份宽度是35px/36px/37px。并且将<html>标签添加不同的font-size设置。

即:一份分别为35px/36px/37px

第三步:根据UI的px标注图计算出相应的rem:

第四步:rem将转化成不同的px尺寸在不同的手机上呈现:(ps:图中的除法结果算错了)

通过这样的方式,即可以在不同尺寸的手机上有相同的展示效果。而最cool的地方,是上述整个过程时自动适配的。开发者只需根据UI标注图无脑写就行了,再也不用挤眉弄眼地对着Chrome Devtools 疯狂调试了。

代码实现

把手机的宽分为10份,那么上述三款手机的每份宽度是35px/36px/37px。并且将<html>标签添加不同的font-size设置。

通过JavaScript动态计算出当前的屏幕宽度,切割为10份并将<html>fontSize设置为1份单位宽度

document.addEventListener('DOMContentLoaded', function(e) {document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';
}, false);复制代码

当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。另一个不同的事件 load 应该仅用于检测一个完全加载的页面。 MDN::DOMContentLoaded

根据UI的px标注图计算出相应的rem

这一步需要使用Sass来定义一个px2rem的工具函数:

// utils.scss
@function px2rem($px){$rem : 75px; // '750/10':分成10份@return ($px/$rem) + rem;
}// foo.scss.box1 {width: px2rem(320px); // '(320/750) * 10 = 4.266rem'}
复制代码

这样,我们在styleSheet中实际生效的是height: 4.266rem,而1rem对应多少px是上述JavaScript代码根据不同的window.innerWidth提前计算好的。这样就实现了自动适配。

如果你嫌写 px2rem()也麻烦,那么可以把函数名定义简单一些。

绕不开的viewport和dpr

在写这篇博客的开始,我曾试图绕开阐述viewportdpr这个抽象的概念,因为上述的内容已经可以从一个维度解决大多数问题了。但是,如果想做得更完美,就必须从另一个维度出发,而这个维度,就是dpr

首先,要区分两个概念:

  1. 设备的pixels
  2. css的pixels

有这样一个场景

一位前端工程师敲出了

.box {width: 100px;height:100px;
}
复制代码

那么此时,他的意思是box在我们的屏幕中占的实际长宽是100px,在他脑中是这样的画面:

项目上线之后,有一个用户'不怀好意'地使用了放大镜功能将长宽放大了两倍,现在就变成了:

你会发现,设备花了200px的长宽来渲染CSS里面定义的100px的长宽,而设备pixels和样式pixels的比值,就是dpr,即Device Pixel Ratio,如果对这个概念仍有问题,请查看viewport剖析。

我们大家都知道Retina屏(视网膜屏),之所以看起来这么高清,就是因为苹果设备花两个像素来渲染一个像素的物体,那么看起来肯定更为精致。

所以,如果我们针对dpr=1的书写了rem2px(100px),那么在dpr=2的设备看起来将会是被放大了2倍的元素。

那么,如果我们能够查询出当前设备的dpr,并且做相应的缩放就可以解决这个问题。

举个例子:某些安卓机的dpr=1,但是UI做标注图的时候是根据dpr=2来做的,就像我们上文的750px * 1334px。直接按照750px * 1334px写出来的元素将会被放大两倍,那么我们就使页面缩小两倍,如何控制呢?

用viewport

简言之,在这里我们使用viewport是为了控制屏幕的缩放。

var dpr = window.devicePixelRatio;
meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
// 帮助理解 如果dpr=2,说明写的100px渲染成了200px,所以需要缩小至1/2,即1/dpr
复制代码

另外值得一提的是,UI一般会以750px * 1334px的标准进行设计,因为这样使得设计稿更加精细。 比如我们写了rem2px(375px),那么会经过下列的过程换算到设备pixels宽度为390px且dpr=3的手机。

  1. rem2px(375px) ----> 5rem
  2. 5rem -----> 195px (样式pixels)
  3. 样式195px ------> 此时看起来(指的就是设备pixels)有195*3 = 585px的长度
  4. 设置dpr=1/3------->此时看起来只有195px

这样,我们完成了从dpr维度的适配。

show me the code:

<script>var dpr = window.devicePixelRatio;var meta = document.createElement('meta');// dprmeta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no'); document.getElementsByTagName('head')[0].appendChild(meta);// remdocument.addEventListener('DOMContentLoaded', function (e) {document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';}, false);
</script>
复制代码

为了防止全局变量污染或者覆盖他人的变量,请封装成模块再使用。

One More Thing

在写这篇博客的过程中,曾纠结过这样的问题:rem布局和百分比布局感觉差距不大啊,因为在写rem的时候是基于把宽度切为10份后再写的,就像是1rem = 10% = 10vw一样。这让我一度觉得可以用百分比布局。后来发现,如果出现盒子嵌套(这种场景太多了),那么百分比布局就出现问题了,因为其百分比的参考系选择的是父元素,所以我们如果在子盒子里面定义10%的宽度,指的是针对父盒子的而不是我们想要的针对整个window.innerWidth10%。而vw的代码可维护性不如上述的这套方案,且兼容性也没有rem好(这一点差距不是太大)。

如果想了解更多关于PC端or移动端布局,请看参考资源&鸣谢板块。

参考资源&鸣谢

移动端页面适配方案

使用Flexible实现手淘H5页面的终端适配

六种布局+rem布局的简介

DOMContentLoaded与load的区别

rem是如何实现的

AlloyTeam 移动web适配利器

viewport剖析

lib-flexible

轻松掌握移动端web开发【尺寸适配】常用解决方案相关推荐

  1. H5手机移动端WEB开发资源整合 常用的标签及注意事项

    meta基础知识 H5页面窗口自动调整到设备宽度,并禁止用户缩放页面 <meta name="viewport" content="width=device-wid ...

  2. # 移动端web开发

    ### 概述 随着互联网技术的快速发展,加之智能设备的迅速普及,传统网站都已经逐渐向移动端转移和扩展,移动端web开发技术的掌握也显得尤为重要. 移动端Web主要指运行在移动端(手机.ipad)的we ...

  3. 移动端WEB开发之响应式布局(响应式开发原理、bootstrap、阿里百秀案例)

    移动端WEB开发之响应式布局 1.1 响应式开发原理 就是使用媒体查询针对不同宽度的设备进行布局和样式的设置,从而适配不同设备的目的. 设备的划分情况: <!DOCTYPE html> & ...

  4. 视频教程-移动端Web开发-JavaScript

    移动端Web开发 TriAquae开源运维软件创始人,混迹IT运维领域多年,曾就职于松下.国政通.飞信.中金.NOKIA等公司,维护过少至几十台,多至数万台设备的IT系统,致力于提高企业运维自动化水平 ...

  5. 20.【移动端Web开发之响应式布局】

    文章目录 [移动端Web开发之响应式布局]前端小抄(20) 一.响应式开发 1.1 响应式开发原理 1.2 响应式布局容器 二.Bootstrap前端开发框架 2.1 Bootstrap简介 2.2 ...

  6. 蓝旭前端开发:GITtomcat+nginx原理移动端web 开发

    蓝旭前端开发:GIT+移动端 web 开发 目录 一.==GIT== 1.1 ==Git与GitHub== 1.2 ==GitHub注册和Git的下载安装== 二.==Git的使用== 2.1 ==本 ...

  7. 移动端WEB开发——响应式布局

    移动端WEB开发之响应式布局 1.0 响应式开发原理 1.1 响应式开发原理 就是使用媒体查询针对不同宽度的设备进行布局和样式的设置,从而适配不同设备的目的. 设备的划分情况: 设备划分 尺寸区间 超 ...

  8. 移动端Web开发 基础知识

    文章目录 移动端Web开发 移动端基础 浏览器 视口 样式编写 分辨率和设备像素比 二倍图 SVG矢量图 移动端Web开发 移动Web开发的两种主流方案,一种是单独制作移动端页面,另一种是制作响应式页 ...

  9. 前端移动端web开发(一)

    一.前端开发 1.前端开发分类: PC端开发:页面主要运行在PC端浏览器中 移动端开发:页面主要运行在手机上 移动web开发 在移动端表现良好的页面,如新浪网 混合式开发(Hybrid App) 也叫 ...

最新文章

  1. TensorFlow学习笔记(一)--windows系统安装配置
  2. 【Nginx】epoll事件驱动模块
  3. MongoDB限制与阈值
  4. 简单了解各种序列化技术-JSON序列化框架
  5. 剑指offer(C++)——链表中环的入口结点
  6. 深入浅出深度学习(一)深度学习的发展
  7. DML、DDl、DQL实战
  8. Gaze Estimation学习笔记(1)-Appearance-Based Gaze Estimation in the Wild
  9. springcloud与springcloudalibaba版本对应关系
  10. java队徽_求实况足球10PC版(PES6)存档修改器 PESFan Editor 6所需的Java程序(必须是能够下载的链接,死链接免扰!...
  11. [Verilog]半减器,全减器设计
  12. 上网行为安全之流量管理技术
  13. 自媒体多平台多账号群发工具开发日记:第1天 工具的统筹规划
  14. 用excel打开一个xls文件进度到36%就不动了
  15. 网络工具Netwox和Wireshark详解
  16. 阿尔法小蛋机器人热点密码_科大讯飞阿尔法小蛋智能机器人使用说明
  17. python tcp黏包和struct模块解决方法,大文件传输方法及MD5校验
  18. fgo1月23号服务器维护,FGO国服1月23日维护公告 终章最终决战开启
  19. c++day01 引用符号的使用
  20. 浙江省计算机二级函数,浙江省计算机二级办公软件之excel函数

热门文章

  1. 浅析 Linux 初始化 init 系统
  2. 使用Python脚本批量裁切栅格
  3. linux 下获取程序的绝对路径
  4. RDS for MySQL 5.7 备份恢复为本地实例
  5. Docker+Jenkins持续集成环境(1)使用Docker搭建Jenkins+Docker持续集成环境
  6. 常用的webservice接口
  7. c# 模拟window 操作鼠标|winapi
  8. Red Hat Enterprise Linux 5---system-config-*管理工具
  9. TCP/IP、 IPX/SPX、 NetBEUI、 AppleTalk协议
  10. GameObject 与gameObject的区别