一、meta标签的效果
- 移动端页面一般会在head头部添加如下meta标签。
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- 该meta标签是否添加对页面渲染的影响
在移动端,未添加该meta标签时,html元素的宽度一般为980px;添加该meta标签之后,html的宽度与设备物理尺寸宽度一致。
二、几个名词和单位
- 设备物理像素
设备物理像素又被称为设备像素,是显示器设备上的一个最微小的物理部件。每个像素可以根据操作系统设置自己的颜色和亮度。
设备物理像素的物理尺寸是固定的。在移动端浏览器中,设备物理像素的物理尺寸只与设备有关,不随手指的缩放而缩放。 - 设备独立像素
设备独立像素也被称为密度无关像素,可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用并控制的虚拟像素(例如:CSS像素),然后由相关系统转换为物理像素。
设备独立像素的物理尺寸是不固定的。在移动端浏览器中,设备独立像素的物理尺寸随着手指的缩放而缩放。
- CSS像素
CSS像素是设备独立像素的一种,是一种抽象单位,主要作用在浏览器上。 - 设备像素比(dpr)
设备像素比等于设备物理像素与设备独立像素(在浏览器中为CSS像素)的比值。可以通过window.devicePixelRatio获取移动设备的像素比。 - 分辨率(pt)
表示设备屏幕在水平和垂直方向上的物理像素个数。例如,iPhone6的分辨率为750pt * 1334pt。 - 屏幕尺寸
表示屏幕对角线的长度,单位为英寸(in),1英寸等于2.54厘米。例如:iPhone6的屏幕尺寸为4.7英寸。 - 像素密度(ppi)
指每英寸屏幕上诉拥有的物理像素数目。计算公式为:PPI = (横向像素2 +纵向像素2 )1/2 /屏幕尺寸。例如:iPhone6的像素密度等于 (7502 +13342 )1/2 /4.7 = 326。
三、视口
- 三个视口
布局视口、视觉视口和理想视口。以下视口中所涉及的像素均为CSS像素,并且默认不考虑缩放。 - 布局视口
布局视口指网页布局区域。该视口取决于网页制作时的CSS样式,与用户设备无关。 布局视口宽度可以通过document.documentElement.clientWidth得到。
html根元素的包含块即是初始包含块,如果给html元素设置width: 100%; height:100%的CSS样式,则该页面的布局视口尺寸等于初始包含块的尺寸。 - 视觉视口
视觉视口指设备物理屏幕的可视区域。该视口与用户设备有关,在PC端浏览器和移动端浏览器上表现不同。
在PC端浏览器中:视觉视口的宽度与浏览器可视窗口的宽度一致。
在移动端浏览器中:①当无viewport对应的meta标签时,为了正常显示那些传统的为PC端浏览器设计的网页,移动设备浏览器一般都会通过一个小于零的默认初始缩放比例(initial-scale)将默认视觉视口宽度设置为980px或1020px,大于浏览器的宽度。②当设置viewport对应的meta标签且缩放比例为1.0时,视觉视口的宽度等于浏览器的宽度。③当用户手动缩小网页时,视觉视口变大;当手动放大网页时,视觉视口缩小。需要注意的是,用户手动缩放网页时,只影响视觉视口,布局视口保持不变。
注释:布局视口是网页的CSS尺寸,视觉视口是用户在浏览器屏幕上可见的CSS尺寸。 - 理想视口
布局视口等于视觉视口时产生理想视口。
理想视口中的网站拥有最理想的浏览和阅读的宽度,用户刚进入页面时不再需要缩放,并且没有横向滚动条。
当添加以下meta标签时,就将当前理想视口的宽度设置为设备宽度,同时不允许用户手动缩放。
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
四、Retina屏幕与普通屏幕
- 在上面讲了, 设备像素比(dpr)等于设备物理像素(分辨率)与设备独立像素(在浏览器中为CSS像素)的比值,可以通过window.devicePixelRatio获取移动设备的像素比。
- 在大部分PC设备以及早期的移动设备中,屏幕像素密度比较低,设备像素比(dpr)等于1,一个设备独立像素(CSS像素)对应一个物理像素。随着技术的发展,移动设备的像素密度越来越高,设备像素比(dpr)等于2或者3,一个设备独立像素(CSS像素)对应2或3个物理像素。
- 在不同屏幕上,不论是设备像素比(dpr)等于几,一个设备独立像素(CSS像素)所呈现的视觉大小是一致的。不同的只是他们对应(覆盖)的物理像素个数。
-
对于iPhone6设备的Retina屏幕而言,设备物理像素数(分辨率)为750pt * 1334pt,当缩放比例为1时,视觉视口为375px * 667px,设备像素比(dpr)为2,一个CSS像素对应4个物理像素。对于大部分PC端设备或早期移动设备等普通屏幕上,当缩放比例为1时,设备像素比(dpr)为1,一个CSS像素对应1个物理像素。他们的屏幕表现对比图如下:
五、图像显示
- 当一个设备独立像素(CSS像素)对应一个物理像素时,图片才能够完美清晰的显示。
- 当一个设备独立像素(CSS像素)对应多个物理像素时,由于设备独立像素(CSS)像素已经是最小的数据单位,不能被继续切割。为了能够显示出来,只能就近取色,从而导致图片模糊的问题。
- 设备像素比(dpr)大于1时,一个设备独立像素(CSS像素)对应多个物理像素。此时需要提供与设备像素比(dpr)同倍数大小的图片,这样就能够解决图片模糊的问题。例如:对于dpr为2的Retina屏幕,一个200px * 300px的img标签,需要提供400 * 600的原型图片。
- 当一个物理像素对应多个设备独立像素(CSS像素)时,由于物理像素是显示器设备上可以设置自己颜色和亮度的最微小部件。为了能够显示出来,只能够通过一定的算法进行缩减显示,从而导致图片出现色差的问题。
- 下面是一张100 * 100的图片分别放在100px * 100px、 50px * 50px、 25px * 25px的img容器中,在设备像素比(dpr)为2的屏幕中的显示效果。
条形图,通过放大镜其实可以看出边界像素点取值的不同:
①图1,就近取色,色值介于红白之间,偏淡,图片看上去会模糊(可以理解为图片拉伸)。
②图2,没有就近取色,色值要么是红,要么是白,图片看上去很清晰。
③图3,就近取色,色值介于红白之间,偏重,图片看上去有色差,缺少锐利度(可以理解为图片挤压)。
六、1px边框问题
- 如果页面中DOM元素的CSS样式设置边框宽度为1px。
① 对于设备像素比(dpr)为1的设备,1个设备独立像素(CSS像素)对应1个物理像素。则显示在浏览器屏幕上的边框占1个物理像素宽度。
② 对于设备像素比(dpr)为2的设备,1个设备独立像素(CSS像素)对应2个物理像素。则显示在浏览器屏幕上的边框占2个物理像素宽度。
显示效果对比图如下:
对于一条1px宽的直线,它们在屏幕上的物理尺寸(灰色区域)的确是相同的,不同的其实是屏幕上最小的物理显示单元,即物理像素,所以对于一条直线,iphone5它能显示的最小宽度其实是图中的红线圈出来的灰色区域,用css来表示,理论上说是0.5px。然而并不是所有手机浏览器都能识别border: 0.5px;,ios7以下,android等其他系统里,0.5px会被当成为0px处理。 - 1px边框的实现方式
① 0.5px边框
优点:写法简单。
缺点:无法兼容安卓设备、 iOS 8 以下设备。
② 设置缩放比例 + rem布局
优点:满足所有场景。
缺点:影响范围大。
③ 伪类 + transform缩放
优点:满足所有场景
缺点:对于已经使用伪类的元素,需要多层嵌套 - 设置缩放比例和rem实现1px边框
<script>
(function(){
var rem = window.innerWidth/10;
var fn=function(){
var dpr = window.devicePixelRatio;
var scale = 1/dpr;
var html=document.getElementsByTagName('html')[0];
var meta = document.getElementById('vp');
html.style.fontSize=rem+'px';
html.setAttribute('data-dpr',dpr);
meta.setAttribute('content','initial-scale='+scale+',minimum-scale='+scale+',maximum-scale='+scale+',user-scalable=no');
};
fn();
window.onresize=fn;
}())
</script>
对于任何移动设备:①一个rem对应innerWidth的1/10像素,10rem占满屏幕宽度。②页面缩放比例为1/dpr。设备独立像素(CSS像素)与设备物理像素一一对应。
- 伪类和transform实现1px边框
//右边框
.bd-r{
position: relative;
}
.bd-r:after{
height: 100%;
content: '';
width: 1px;
border-right: 1px solid black;
position: absolute;
top: 0;
right: -1px;
transform: scaleX(.5);
-webkit-transform: scaleX(.5);
z-index: 10;
}
//四个边框
.bd-1px{
position: relative;
margin-bottom: 20px;
border:none;
}
.bd-1px:after{
content: '';
position: absolute;
top: 0;
left: 0;
border: 1px solid #000;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 200%;
height: 200%;
-webkit-transform: scale(0.5);
transform: scale(0.5);
-webkit-transform-origin: left top;
transform-origin: left top;
}
七、移动端适配
- Flex布局
2009年,W3C提出了一种新的方案——Flex布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,成为未来布局的首选方案。
参考: http://www.ruanyifeng.com/blog/2015/07/… - 流式布局(百分比布局)
百分比 = 目标元素宽度 / 父元素宽度 - 媒体查询
在不改变内容的情况下在样式中选择一种页面的布局以精确地适应不同的设备,从而改善用户体验。网页制作者针对不同的浏览器窗口尺寸来编写不同的样式,浏览器根据不同的窗口尺寸来选择使用不同的样式。
格式:@media 设备类型 and (设备特性){样式代码}
举例: 如果屏幕宽度小于400像素(max-device-width: 400px),则加载tinyScreen.css文件。
<link rel="stylesheet" type="text/css" media="screen and (max-device-width: 400px)" href=“tinyScreen.css” />
- rem布局
px:像素; em:相对于父级元素字体大小的倍数;rem :相对于HTML根元素(HTML)字体大小的倍数。
八、手淘团队的flexible.js布局
- 手淘团队推出了一套flexible布局方案。
参考: http://www.w3cplus.com/mobile/lib-flexible-for-html5-layout.html - 如果要适配iPhone6设备
① 设计师给了一个750px宽度的设计稿(注意是750px而不是375px)。
② 前端工程师用750px的这个比例还原。
③ 把宽高是px的转换成rem。
④ 字体使用px而不使用rem。
⑤ flexible.js会自动判断dpr进行整个布局视口的放缩。 - 布局单位(rem)与字体单位(px)
在flexible.js中,布局尺寸宽高使用rem是为了保证在不同宽度尺寸的移动设备中能够保证布局的等比例缩放。字体大小尺寸使用px是为了保证font-size值不出现小数,且在不同宽度尺寸的移动设备中能够保证字体视觉大小一致。对于字体的适配,更好的做法是使用px单位和媒体查询来进行适配。 - flexible布局方案没有适配Android设备。Android设备的像素比(dpr)五花八门,从1到4,甚至可能出现小数。
九、响应式布局与自适应布局
- 响应式布局即是一个网页能够响应不同分辨率设备,在不同分辨率设备中可以展示特定版本的页面内容。自适应布局即是一个网页能够适应不同分辨率设备,在不同分辨率设备中可以大致等比例展示网页内容。
- 现如今的大型网站,使用响应式布局的不多,更普遍的做法是针对PC和移动端分别做一套页面,用户打开页面时根据客户端类型进行重定向。原因在于,响应式布局在PC端会显示比较复杂的DOM结构,而在移动端通过DOM结构的隐藏进行简洁展示,代码较为冗余且在移动端消耗了太多的流量和加载速度。
参考文章
解惑好文:移动端H5页面高清多屏适配方案
7种方法解决移动端Retina屏幕1px边框问题
前端移动端适配总结
使用Flexible实现手淘H5页面的终端适配