【CSS】 浅析rem布局方案
共 3082字,需浏览 7分钟
· 2021-02-26
一些像素概念
物理像素:即实际的每一个物理像素,也就是移动设备上每一个物理显示单元(点) 设备逻辑像素( css
中的px
):可以理解为一个虚拟的相对的显示块,与物理像素有着一定的比例关系,也就是下面的设备像素比设备像素比( dpr
):= 物理像素 / 设备独立像素(px
)
如果
dpr
为1
的话,那么1px = 1物理像素
,x
轴y
轴加起来就是1
如果
dpr
为2
的话,那么1px = 2
物理像素,x
轴y
轴加起来就是4
![](https://filescdn.proginn.com/63f8f4f3016ce53bf6e8c47fcda21fed/e35c039777e538a69d603873f6ed9944.webp)
以此类推
在js中可以通过
window.devicePixelRatio
获取当前设备的dpr
。
这里说明一下,无论dpr
多大,1px
的大小通常来说是一致的,这也就意味着,随着dpr
的增大,物理像素点会越来越小,这样才能容纳更多的物理像素,才能更高清,更retina
![](https://filescdn.proginn.com/5516ce3768588f22fcecaf53a1407f73/8d922c1ed31e687ef3e133e11b3f306c.webp)
说完基本概念,来说一下几个问题:
retina屏图片模糊
首先普及一下位图像素:一个位图像素是图片的最小数据单元,每一个单元都包含具体的显示信息(色彩,透明度,位置等等)
那为什么在dpr高的retina屏上反而会模糊呢?看图~
![](https://filescdn.proginn.com/b530a58eb943a9847e5618f71ae003a5/8bf1e9c27b8effa65ae6f29ffc16bbeb.webp)
在
1dpr
的屏幕上,位图像素和物理像素一一对应没什么问题,但是在retina
屏上,由于一个px
由4
个甚至更多的物理像素组成,并且单个位图像素不能进一步分割,所以会出现就近取色的情况,如果取色不均,那么就会导致图片模糊。
对于这种情况,只能采用
@2x
、@3x
这样的倍图来适配高清展示,这样侧向说明了为什么照着iphone6
做的ui
稿不是375
,而是750
的问题。
虽然这样在dpr
为1
的屏幕上会导致1
个物理像素上有4
个位图像素,但是这种情况的取色算法更优,影响不大,不做讨论。
1px的粗细问题
由于
1px
的实际大小是一样的,只是里面的物理像素数量不同,所以如果直接写1px
是没问题的,不会出现粗细不同的情况,但是这样一来retina
的优势也rem
的作用也就没了,其实还是dpr
的问题,dpr
为1
,那么1px
就是一个物理像素,但是在retina
中。1px
实际可能有4
、9
个物理像素,ui
想要的其实是1
个物理像素,而不是1px,不过由于不是素所有的手机都能适配0.x
,所以曲线救国,采用scale
缩放或者设置meta
都可以
![](https://filescdn.proginn.com/7fb39fee607dc0f7a23a43094e41b7f7/8d79a3fa61b6545f63ead1112bf2d5f0.webp)
viewport
三个概念
layout viewport
visual viewport
ideal viewport
layout viewport
最开始,
pc
上的页面是无法再移动端正常显示的,因为屏幕太小,会挤作一团,所以就有了viewport
的概念,又称布局视口(虚拟视口),这个视口大小接近于pc
,大部分都是980px
visual viewport
有了布局视口,还缺一个承载它的真是视口,也就是移动设备的可视区域-视觉视口(物理视口),这个尺寸随着设备的不同也有不同。这样在视觉视口中创建了一个布局视口,类似
overscroll:scroll;
这样,可以通过滚动拖拽、缩放扩大进行较好的访问体验
ideal viewport
像上面的体验在早些年可能比较多,但是近几年几乎很少了,还是归咎于用户体验,所以,我们还需要一个视口-理想视口(同样是虚拟视口),不过这个理想视口的大小是等于布局视口的,这样用户就能得到更好的浏览体验。
一个特性
viewport
有六种可以设置的常用属性:
width
:定义layout viewport
的宽度,如果不设置,大部分情况下默认是980
height
:非常用initial-scale
:可以以某个比例将页面缩放\放大,你也可以用它来设置ideal viewport
:
<meta name='viewport' content='initial-scale=1' />
maximum-scale
:限制最大放大比例minimum-scale
:限制最小缩小比例user-scalable
:是否允许用户放大\缩小页面,默认为yes
rem适配方案
先说原理,通过
meta
修正1px
对应的物理像素数量,在根据统一的设计稿来生成html
上的动态font-size
,根据dpr
构造字体等误差较大的样式的mixin
// 第一版:
function initRem() {
const meta = document.querySelector('meta[name="viewport"]');;
const html = document.documentElement;
const cliW = html.clientWidth;
const dpr = window.devicePixelRatio || 1;
meta.setAttribute('name', 'viewport');
meta.setAttribute(
'content',
`width=${cliW * dpr}, initial-scale=${1 /
dpr} ,maximum-scale=${1 / dpr}, minimum-scale=${1 /
dpr},user-scalable=no`
);
html.setAttribute('data-dpr', dpr);
// 这样计算的好处是,你可以直接用ui的px/100得到的就是rem大小,方便快捷,无需mixin
html.style.fontSize = 10 / 75 * cliW * dpr + 'px';
}
initRem();
window.onresize = window.onorientationchange = initRem();
对于引入的第三方ui组件,需要使用px2rem转换工具去做整体转换,比如
postcss-pxtorem
:https://github.com/cuth/postcss-pxtorem
最后
欢迎加我微信(winty230),拉你进技术群,长期交流学习...
欢迎关注「前端Q」,认真学前端,做个专业的技术人...
![](https://filescdn.proginn.com/f52e96941dc352587d2105c098795dac/0bd8e66b0062b28b020ccdb64f4d7065.webp)
![](https://filescdn.proginn.com/4fdadf8227178da3aeace80ec453abc7/17c7ecbb0626bc4c32a1048bbeaecb3f.webp)