web前端开发人员如何才能开发出适配每个终端的wap页面呢?如果还有点迷茫不知所措,下面的文章希望可能给你帮助,同时也可以加深自己的记忆,有欠缺错误的地方,欢迎评论指出,相互学习。
备注:(不讨论百分比布局方式)
如果有点心急的话可以直接跳到第5步,欲知其原理还得慢慢来
首先,在解决问题之前,我们先了解一下熟悉一些有趣的概念,帮助我们更深的理解解决办法哦!
1、像素
什么是像素?
像素是web页面布局的基础,估计我们每个前端开发人员都离不开,那么到底什么才是一个像素呢?可能大家会和我一样有点质疑,是的平时每天都在写,但是到底是指什么呢?
像素:就是计算机屏幕所能显示一种特定颜色的最小区域。
在web前端开发领域,像素有以下两种含义:
1、设备像素(物理像素):设备屏幕的物理像素,对于任何设备来讲物理像素的数量是固定不变的。
2、设备独立像素(也称密度无关像素,虚拟像素):可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用的虚拟像素(比如说CSS像素),然后由相关系统转换为物理像素。
CSS像素(虚拟像素):这是一个抽象的像素概念,它是为web开发者创造的。
设备 | 年份 | 尺寸 | 像素 | 点数 |
---|---|---|---|---|
iPhone4S | 2011年 | 3.5 | 640*960 | 320*480 |
iPhone5S | 2013年 | 4.0 | 640*1136 | 320*568 |
iPhone6 | 2014年 | 4.7 | 750*1334 | 375*667 |
iPhone6S Plus | 2015年 | 5.5 | 1242*2208 | 414*736 |
备注:此表所列举的像素即为设备像素(物理像素)
2、屏幕密度
指一个设备表面上存在的像素数量,它通常以每英寸有多少像素来计算(PPI)。
3、设备像素比
简称为dpr,其定义了物理像素和设备独立像素的对应关系。它的值可以按下面的公式计算得到:
设备像素比(DPR) = 设备像素个数 / 理想视口CSS像素个数(device-width)
在JavaScript中,可以通过 window.devicePixelRatio 获取到当前设备的dpr
举例:iPhone6的设备宽度和高度为375pt * 667pt,可以理解为设备的独立像素;而其dpr为2(window.devicePixelRatio ),根据上面公式,我们可以很轻松得知其物理像素(设备像素)为750pt * 1334pt。
4、视口(viewport)
布局视口:移动端CSS布局的依据视口,即CSS布局会根据布局视口来计算
可以通过以下JavaScript代码获取布局视口的宽度和高度:
document.documentElement.clientWidth;
document.documentElement.clientHeight;
可视视口:用户正在看到网站的区域
理想视口:定义了理想视口的宽度,比如对于iphone6来讲,理想视口是375*667。
但是最终作用的还是布局视口,因为我们的css是依据布局视口计算的,
所以你可以这样理解理想视口:理想的布局视口。
下面这段代码可以告诉手机浏览器要把布局视口设为理想视口:
<meta name="viewport" content="width=device-width" />
打起精神咯,讲了这么多开始进入正题咯...此时可以来一条华丽的风格线
5、基本定义了解之后开始写代码了,边写代码边打开调试模式,对照看可能理解更深刻。以iPhone6设备为例子(如果下面出现的术语有疑问可以返回来继续浏览)
马上开始解决问题喽!
前情概要:iPhone6的设备宽度和高度为375pt * 667pt,可以理解为设备的独立像素;
而其dpr为2,根据上面公式,我们可以很轻松得知其物理像素(设备像素)为750pt * 1334pt。
a、创建HTML页面,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>适配移动终端</title>
<style>
/* 初始化样式 */
*{padding: 0;margin: 0}
.box{width: 375px;height: 375px;background: blanchedalmond}
</style>
</head>
<body>
<div class="box"></div>
<script>
window.onload = function () {
const screenWidth = document.body.clientWidth;
console.log("window.devicePixelRatio "+window.devicePixelRatio);
console.log("document.body.clientWidth的值为 " + screenWidth);
}
</script>
</body>
</html>
打开调试器,查看设备像素比=2;布局视口的宽度=980px
查看body的宽度:980px,为布局视口的宽度
查看box元素的宽度:375px
此时,为了让box元素的宽度占满屏幕,我们需要将box的宽度设置为多少呢?自己可以动手操作一下 . . . . ...
最后.box{width:980px;height:980px},如下图所示
原因:
980px是布局视口,通过document.documentElement.clientWidth获得,
而我们平时写的css样式则是相对于布局视口操作的,
所以,但是当布局视口发生变化的时候我们需要手动改页面中元素的尺寸,
那么有没有简单的办法呢或者可优化的地方呢?
继续:
b、在该HTML页面中加入
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
这行代码大家一定很熟悉,移动端开发一般都要加,加入这行代码的意思是什么呢?可以让布局视口的宽度等于理想视口的宽度,页面的初始缩放比例以及最大缩放比例都为1,且不允许用户对页面进行缩放操作
这样布局视口和设备的宽度一样了,都是375px;但是页面元素box上一步设置的大小是980px所以已经超出了当前屏幕出现了滚动条,要让该元素全屏显示需要修改box样式将宽度改成375px; 但是还是一样的问题,当设备变成了一下设备甚至更多,如下:
设备 | 设备宽度 |
---|---|
iPhone5S | 320*568 |
iPhone6 | 375*667 |
iPhone6S Plus | 414*736 |
... | ... |
还有很多的安卓手机
宽度还是会改变,应该继续做些什么呢?
叮咚!接着就要给大家推荐一个牛一般的存在移动端适配flexible方案
下载链接中的js,同时引入到我们的HTML页面中。 看看是不是解决问题了,不管在iPhone5、iPhone6、iPhone6S Plus...各种设备下.box{width:10rem}都能让该元素宽度显示全屏幕,那这个JS到底做了些什么操作呢?
在这里先要插播一个单位rem,相信大家都很熟悉, rem 是相对于根元素<html>的font-size来做计算。
而在这个方案中使用rem单位,是能轻易的根据<html>的font-size计算出元素的盒模型大小。
那么应该怎样换算成rem呢?
上图中:根元素HTML字体大小为37.5px
那么在该实例中 1rem = 37.5px
同理:
如果根元素HTML字体大小为75px
那么在该实例中 1rem = 75px
那么如果一个页面根元素(html)字体大小设置为41.4px,那么该页面中有一个元素宽度是270px,转化成rem是多少呢?
结
果
是
1rem = 41.4px
270px / 41.4px = 6.52rem(约等于)
移动端适配flexible方案主要做了些什么呢?
目的:适配移动终端 当我们将页面的字体设置为 布局视口/10的时候,想要让一个元素全屏显示宽度,就都是设置10rem
下面我们来自己算一下:
设置 | 布局视口 | 根目录字体 大小 | 页面中某元素宽度100% |
---|---|---|---|
iphone5 | 320px | 32px | 1rem = 32px 320px/32px = 10rem |
iphone6 | 375px | 37.5px | 1rem = 37.5px 375px/37.5px = 10rem |
iphone6Ps | 414px | 41.4px | 1rem = 41.4px 414px/41.4px = 10rem |
... | ... | ... | ... |
解析:布局视口 (375px)/ 根元素字体大小(37.5px) = 10rem
附上flexible.js(细细品味)
(function flexible (window, document) {
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1
// adjust body font size
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded',
setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
希望你可以自己做一个实例,毕竟书上得来终觉浅,绝知此事要躬行(对某个元素疑问的可以返回去自己看或者搜索更多的内容,帮助理解)。
你可以找个现有的PSD设计图开始练习,尺寸为750px*1300px(其实和PSD的大小是没有关系的)
将PSD的尺寸当成布局视口就可以了,当然根元素字体就是布局视口尺寸/10
怎么样了?加油,你是最棒的,其实解决这个不只是这种办法,大家可以在理解都基础上开始各种尝试,比如根据dpr的值改变布局视口的大小等等...
总结:其实下载移动端适配flexible方案的js,引入js就可以解决适配问题,前面啰啰嗦嗦的只是为了清楚为什么这样做可以解决问题,希望能有所帮助。自己理解可能也有些误差,不足之处望指正。
(参考链接:github.com/amfe/articl…)