移动端布局基本概念
物理像素(设备像素),物理像素是显示器(手机屏幕)上最小的物理显示单元,在操作系统的调度下,每一个设备像素都有自己的颜色值和亮度值;
设备独立像素,设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css像素),然后由相关系统转换为物理像素;
CSS像素,主要使用在浏览器上,用来精确的度量(确定)Web页面上的内容。一般情况下,CSS像素被称为与设备无关的像素(device-independent像素),简称为“DIPs”。在一个标准的显示密度下,一个CSS像素对应着一个设备像素;
设备像素比,设备像素比(简称dpr)定义了物理像素和设备独立像素的对应关系,设备像素比不会影响元素显示的大小,但会影响显示的清晰度;
设备像素比 = 物理像素 / 设备独立像素 window.devicePixelRatio // JS获取设备像素比
根据上面的概念:
// HTML代码:
<div style="with: 300px; height: 200px;"></div>
// 不同的屏幕上(普通屏幕 vs retina屏幕),css像素所呈现的大小(物理尺寸)是一致的,不同的是1个css像素所对应的物理像素个数是不一致的。在普通屏幕下,1个css像素 对应 1个物理像素(1:1)。 在retina 屏幕下,1个css像素对应4个物理像素(1:4)
// 上面会在显示屏绘制一个300px * 200px的盒子,这是CSS像素,即设备独立像素
// 根据设备像素比,如果dpr = 2,那么设备像素为600px * 400px,即一个CSS像素里放着四个设备像素,这样就会导致元素看起来模糊
viewport,视口,不同浏览器上viewport都有一个默认值,即为该浏览器想要向我们展示信息的窗口大小;
// meta viewport 有6个属性: // width,设置layout viewport的宽度,为一个正整数,或字符串"device-width",device-width指的是设备的物理宽度 // height,设置layout viewport的高度,这个属性不重要,很少使用 // initial-scale,设置页面的初始缩放值,为一个数字,可以带小数 // minimum-scale,允许用户的最小缩放值,为一个数字,可以带小数 // maximum-scale,允许用户的最大缩放值,为一个数字,可以带小数 // user-scalable,是否允许用户进行缩放,值为"no"或"yes", no 代表不允许,yes代表允许 <meta name="viewport" content="width=device-width, user-scalable=no"> document.documentElement.clientWidth // JS获取视窗宽度,一般浏览器默认该值为980px,这就是我们没有设置mete的width的时候PC页面在移动端设备中打开,会显示的特别小,字根本看不清
layout viewport 布局视口,即浏览器视口,不同的手机浏览器可能不同,例如常见为980px。布局视口可以通过
document.documentElement.clientWidth/clientHeight
,元素的宽度继承于布局视口;visual viewport 虚拟视口,浏览器可视窗口大小,
window.innerWidth/Heigh
,缩放可以改变虚拟视口可以通过视口来理解浏览器缩放原理,缩放的时候布局视口和网页布局大小是不变的,缩放类似于将页面远离或拉近显示屏,而能从视口看到的部分内容就是虚拟视口。
移动端常用布局方案
响应式布局
通过几个关键断点进行媒体查询区分设备类型来改变页面布局的布局方式。常用媒体查询关键点:
/* 超小屏幕(手机,小于 768px) */ @media (max-width: 768px) { ... } /* 小屏幕(平板,大于等于 768px) */ @media (min-width: 768px) { ... } /* 中等屏幕(桌面显示器,大于等于 992px) */ @media (min-width: 992px) { ... } /* 大屏幕(大桌面显示器,大于等于 1200px) */ @media (min-width: 1200px) { ... }
rem布局
在移动端,因为设备的布局视口的不同,如果使用px单位布局的话,不同设备下的显示会不一致。rem布局,根据PSD设计图的宽度的1/10设置HTML元素的font-size,这个值会作为rem基础值。然后将PSD上的尺寸都转化为rem进行页面布局。例如750px的PSD图,设置rem为75px,,PSD上一个150px*150px,CSS代码:
// 元素尺寸:PSD标注尺寸 / PSD宽度 * 10 * rem div { width: 2rem; height: 2rem; }
上面的布局会在布局视口为750px的浏览器正确显示,但假如我们更换在布局视口为980px的手机浏览器上浏览网页,只需要更改rem的值为98px(rem值为:
设备屏幕大小 / 设计图尺寸 * 基础rem
),页面布局就会正确显示。实际运用中,当然不需要手动更改rem,可以利用JS动态监听更改rem的值来让网页适应不同的浏览器。rem布局的实质是利用rem模拟vw。一般情况下设定1rem = 10vw
淘宝Flexible移动端适配方案
这个方案是通过JS动态设置HTML标签的font-size值,然后通过rem实现页面布局。同时还会改写meta标签,设置当前缩放比。
flexible.js源码阅读vw
方案使用JS或者flexible.js来通过设置rem值适配的本质是模拟vw,那么当然也可以直接使用vw进行页面布局。
常见问题和解决方法
移动端图片
对于dpr=2的retina屏幕而言,1个位图像素对应于4个物理像素,由于单个位图像素不可以再进一步分割,所以只能就近取色,从而导致图片模糊(注意上述的几个颜色值)。
解决方案就是:不同的dpr下,加载不同的尺寸的图片,例如dpr为2,则加载@2x宽高两倍的图片,但图片CSS像素仍设置为原来大小,这样图片会被缩放满足1个位图像素对应一个物理像素。dpr为1的时候加载正常的图片。
移动端文字
文本还是使用px,只不过使用dpr属性来区分不同dpr下的文本字号大小。
Retina下,border: 1px问题
淘宝flexible.js方案可以解决