1 基本概念
1.1 物理分辨率和逻辑分辨率
- 物理分辨率:显示器固有参数,不能够改变(与之对应的是物理像素的概念,下文会提到)
- 逻辑分辨率:由软件决定可以改变(对应逻辑像素的概念,下文有提到)
这时就会有一个问题,在windows系统中,
更改文本、应用等项目的大小
和调整显示器分辨率
到底是修改哪种分辨率?
1 开始我以为调整显示器分辨率
应该是修改物理分辨率,因为在实际操作中发现调到不同的分辨率,屏幕上会有黑边显示,但仔细一看,有一些分辨率,黑边的宽度是相同的,具体讲我当前屏幕物理分辨率是1920*1080
,当调整到1600*900
时,是没有给黑边的,因为长宽都是缩小了1.2(其实就是一个在1600*900
分辨率下的像素点占了1.2个1920*1080
分辨率(这是我的物理分辨率)下的像素点,也可以说一个在1600*900
分辨率下的像素点占用了1.2物理像素),但是对于1680*1050
就不一样了,两侧会有黑边,当把显示器的宽划分1050份时,其实与1080的比值是1.028左右,按照这个比值,计算长1.028*1680=1727左右
,这样就不够1920,于是就会出现黑边。无论长宽都会使用相同的比值,这个比值应该与DPR的概念相似(后文会有提到),综上调整显示器分辨率
应该是修改逻辑分辨率
2更改文本、应用等项目的大小
是修改逻辑分辨率,这个值感觉也类似于DPR的概念,应该是在你调整显示器分辨率的基础上,进行缩小和放大
补充一个移动端主流设备分辨率图
1.2 物理像素和逻辑像素
- 物理像素,也叫设备像素(dp),物理分辨率其实就是指显示器有多少个物理像素,比如iphone6有
750*1334
个物理像素 - 逻辑像素,也叫设备独立像素(dips),逻辑分辨率其实就是指显示器有多少个逻辑像素,比如iphone6有
375*667
个逻辑像素
1.3 设备像素比(DPR,device pixel ratio)
DPR = 同一方向上的物理像素 / 逻辑像素
举例:打开网页,按f12进入控制台,输入window.devicePixelRatio
可以获得当前网页的DPR,我当前的DPR为2,也就是说,一个逻辑像素会用4个物理像素展示,一个方向两个
1.4 css像素
也是一种虚拟的像素,个人理解,css像素其实和设备独立像素一样都是虚拟的,只不过设备独立像素是相对于物理像素而言的,而css像素是相对于设备独立像素的,可以由以下公式表示,dips = css像素 / scale(缩放比例) 也就是说在没有缩放的情况下,1个css像素等同于一个设备独立像素,个人推荐阅读 深入浅出移动端适配
1.5 DPI,PPI
直接看下面链接,就是描述单位内有多少像素点的第一话——什么是 DPI,什么又是 PPI ?
1.6 二倍图
对于一个位图图像(点阵图像)来说,它是由许多个位图像素组成(最小的数据单元),当1个位图像素对应于1个物理像素时,图片可以完美展示(如果大图占小位置,即多个位图像素对应一个物理像素,这样会浪费资源;如果是小图占大位置,就会模糊)
设计师给二倍图,对于DPR=2的屏幕(也就是一个CSS像素会用4个物理像素来描绘)来说,就正好是一个位图像素对应一个物理像素,举个例子,一张图片大小为200*200
,在css设计时,缩小为100*100
,对于DPR=2的屏幕,一个CSS像素会用4个物理像素来描绘,正好一个位图像素对应一个物理像素
1.7 视口
为了将PC端的网页直接显示到移动端,所以移动端的浏览器默认会将viewport设得大一点,比如980px或者1024px,这时就产生了第一个概念,默认设置的值就是布局视口;浏览器的可视区域是有限的,为了表示这个可视区域,就有了第二个概念视觉视口;现在大多都会给移动端单独设计网站,为了实现完美适配(首先不需要用户缩放和横向滚动条就能正常的查看网站的所有内容;第二,显示的元素,包括文字,图片,他们的大小是合适的),就有了第三个概念理想视口
布局视口(layout viewport)
可以考虑成CSS布局时的那个画布
视觉视口(visual viewport)
视觉视口是指当前通过浏览器窗口看到的网页区域
在PC端上,默认布局视口等于显示器的逻辑分辨率(有些博客这里是说“PC端布局视口等于浏览器窗口的宽度”,我这里个人觉得有点问题,不过欢迎大家交流!),视觉视口还是看到的网页区域,当对网页进行缩放或者直接手动修改浏览器网页宽度(如下图),视觉视口都会发生变化。在下图中发现出现了滚动条,这是因为布局视口大于视觉视口造成的,这其实和移动端出现的问题是一样的
而在移动端上,默认布局视口大于视觉视口,如果不缩放,就会出现滚动条
理想视口(ideal viewport)
在移动端,当布局视口的尺寸等于设备逻辑分辨率尺寸时,才是理想视口;也可以这样说理想视口的宽度和设备逻辑分辨率是一样的
利用meta标签控制viewport
为了让移动端的布局视口等于设备的逻辑分辨率(也就是得到理想视口),就需要添加视口标签
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
属性如下,
当然会发现,下面两种代码都可以得到理想视口,
<meta name="viewport" content="initial-scale=1">
<meta name="viewport" content="width=device-width">
因为浏览器是按照理想视口进行缩放的,所以以上两种方式会出现相同的效果,当两种方式出现冲突时,浏览器会选取大的值
2 适配方案
2.1 rem方案
介绍
rem是一个相对单位,它是相对于根标签(HTML标签)而言,1rem=1html字号大小;
采用这种方案一般会先根据不同的设备宽度利用媒体查询设置不同的font-size(HTML标签字号),然后将设计稿中的所有px单位换算成rem单位,例如根标签font-size:32px,设计稿中有一个64px,所以换算为2rem,媒体查询的代码如下,
@media (width:320px) {
html{
fonts-size: 32px
}
}
一般会将HTML标签字号设置为视口宽度的1/10
手淘的flexible
手淘开发了一个框架,帮助完成rem方案的第一步,即根据不同的视口宽度(理想视口)给网页中html标签设置不同的font-size,核心代码如下,
var docEl = document.documentElement
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit();
更多代码参看这篇文章 lib-flexible与viewport–关于移动端适配方案的替换
在lib-flexible中根据dpr的值来修改viewport实现1px的线
在设计稿(按照物理设备大小)中出现1px的线,如果我们直接写 css 的大小 1px,那当 dpr = 2 时,则等于 2px 设备像素,这一点其实在lib-flexible中已经解决(1px变2px, 又被 initial-scale=0.5 缩小了一半,在源码中会根据dpr设置 initial-scale)
flexible的缺陷
参考文章 Web移动端最强适配方案,很好用!
- 对iframe的使用不兼容,即iframe中展示的内容依然使用的是css像素(iframe标签是一个内联框架,就是用来在当前 HTML 页面中嵌入另一个文档的)
- 在lib-flexible的源码中,安卓手机的dpr一律等于1(安卓手机的dpr太多了)
- 不兼容响应式布局(响应式布局,其实质性做法就是结合css3的媒体查询@media对一些不同尺寸阈值做特定的布局设计)
- 无法正确响应系统字体大小
实际开发中操作
选用以下两个工具:
- postcss-pxtorem 是一款 PostCSS 插件,用于将 px 单位转化为 rem 单位(还有许多其他类似功能的工具)
- lib-flexible 用于动态设置 rem 基准值
// 配置 postcss-pxtorem
npm install postcss-pxtorem@5.1.1 -D
//在 vue 项目根目录下,创建 postcss 的配置文件 postcss.config.js,并初始化如下的配置:
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 37.5, // 根节点的 font-size 值
propList: ['*'] // 要处理的属性列表,* 代表所有属性
}
}
}
// 配置 amfe-flexible
npm i amfe-flexible@2.2.1 -S
//在 main.js 入口文件中导入 amfe-flexible:
import 'amfe-flexible'
2.2 vw方案
介绍
vw 作为布局单位,从底层根本上解决了不同尺寸屏幕的适配问题,因为每个屏幕的百分比是固定的、可预测、可控制的。
vw:1vw 等于 window.innerWidth(视觉视口宽度) 的 1%;
vh:1vh 等于 window.innerHeihgt 的 1%;
实际开发中的操作
使用 postcss-px-to-viewport 插件,来将 px 自动转换为 vw
// 安装 postcss-px-to-viewport
npm i postcss-px-to-viewport --save-dev
// 在 vue 项目根目录下,创建 postcss 的配置文件 .postcssrc.js
module.exports = {
plugins: {
autoprefixer: {}, // 用来给不同的浏览器自动添加相应前缀,如-webkit-,-moz-等等
'postcss-px-to-viewport': {
unitToConvert: 'px', // 要转化的单位
viewportWidth: 750, // UI设计稿的宽度
unitPrecision: 6, // 转换后的精度,即小数点位数
propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
selectorBlackList: ['wrap'], // 指定不转换为视窗单位的类名,
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
replace: true, // 是否转换后直接更换属性值
exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配
landscape: false, // 是否处理横屏情况
},
},
};