专有名词

设备像素(device pixel, dp)

又称为物理像素。指设备能控制显示的最小物理单位,意指显示器上一个个的点,由工厂生产决定,它上面设备像素点就固定不变了。

单位 pt,在CSS中是真正的绝对单位。

CSS像素(css pixel, px)

在不考虑屏幕缩放等情况下,CSS像素等同于逻辑像素。

CSS 样式代码中使用的逻辑像素。又叫设备独立像素

我们给文字设置font-size: 12px 时,屏幕不能按照物理像素和CSS像素1:1的比例来绘制,否则文字会小到看不见。换个分辨率低的设备,文字大小又会变大很多。

这时候设备厂商发明了一个逻辑像素(设备独立像素)的概念。比如 IPhone 12 Pro Max 水平方向的逻辑像素是428px,那么在默认情况下,当我们给页面元素设置样式 width: 428px 时,在IPhone 12 Pro Max 正好能水平撑满整个屏幕。

在不同设备逻辑像素相同则视觉尺寸相同,每一个逻辑像素包含物理像素点不一样多,包含越多物理像素点越多则越清晰。

Untitled

屏幕像素密度

屏幕像素密度 (Pibel Per Inch) 简称ppi,表示每英寸(屏幕对角线长度)物理像素。

对于 iPhone12 mini,5.4英寸(屏幕对角线长度),分辨率为1080 x 2340,则

设备像素比

缩写简称dpr

设备像素比 = 设备像素 / css像素(垂直方向或水平方向)

可以通过JS来获取:window.devicePixelRatio

Untitled

CSS单位

PX

在屏幕分辨率固定,不考虑屏幕缩放的情况下,px是绝对的,不会随着浏览器视口变化而变化。比如,电脑屏幕分辨率调为1440*900时,css里设置的1px实际的物理尺寸就是屏幕宽度的1/1440

em

默认字体大小的倍数。

比如,给元素设置font-size: 2em,这里的默认字体大小实际上是继承自父亲的大小,font-size: 2em表示当前元素字体大小是父亲的2倍。

当给元素设置width: 2em,这里的默认字体大小是该元素自身的实际字体大小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>em 演示</title>
</head>
<body>
<article>
<p>hello 饥人谷</p>
</article>

<style>
body{
font-size: 2em;
}
p {
font-size: 2em;
width: 2em;
}
</style>
</body>
</html>

如上例示,html默认是16pxbody2em,其父元素即为html,所以是16px232pxarticle32px,那么pfont-sizearticle264pxp的宽度width是它自身字体的2倍,即64px * 2 = 128px

rem

以根元素字体大小为基准。

1
2
3
4
html {font-size: 12px;}
h1 { font-size: 2rem; } /* 2 × 12px = 24px */
p { font-size: 1.5rem;} /* 1.5 × 12px = 18px */
div {width: 20rem;} /* 20 * 12px = 240px*/

百分比%

对不同属性有不同的含义。

  • font-size: 200%font-size: 2em,表示字体大小是默认(继承自父亲)字体大小的2倍。
  • line-height: 200% 表示行高是自己字体大小2倍。
  • width: 100%标准盒模型下表示自己content的宽度等于父亲content的宽度,在IE盒模型下表示自己content+padding+border的宽度等于父亲content的宽度。

vw, vh

代表当前浏览器视口宽度/高度的百分之几。

比如,1vw代表浏览器视口宽度的1%100vh代表浏览器视口高度的100%

适配方案

一种适配方案是对不同屏幕尺寸设置根元素htmlrem

可以通过JavaScript读取屏幕宽度,然后根据宽度计算出对应的尺寸并设置根元素的font-size

1
2
3
4
const oHtml = document.getElementsByTagName('html')[0]
const width = oHtml.clientWidth;
// 320px的屏幕基准像素为12px
oHtml.style.fontSize = 12 * (width / 320) + "px";

或者通过媒体查询根据屏幕宽度适配。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@media screen and (min-width: 375px){
html {
font-size: 14.0625px;
}
}
@media screen and (min-width: 360px){
html {
font-size: 13.5px;
}
}
@media screen and (min-width: 320px){
html {
font-size: 12px;
}
}
html {
font-size: 16px;
}

rem有其局限性。

iOSAndroid平台的适配方式背后隐藏的设计哲学是这样的:阅读文字时,可读性较好的文字字号行距等绝对尺寸数值组合与文字所在媒介的绝对尺寸关系不大。(可以这样简单理解:A4大小的报纸和A3大小甚至更大的报纸,舒适的阅读字号绝对尺寸是一样的,因为他们都需要拿在手里阅读,在手机也是上同理);在看图片视频时,图片、视频的比例应该是固定的,不应该出现拉伸变形的情况。而rem用在字号时,使字号在不同屏幕上的绝对尺寸不一致,违背了设计哲学。

布局视口

在移动端,默认的情况下,布局视口的宽度是要远远大于浏览器的宽度的。

浏览器厂商为了让用户在小屏幕下网页也能够显示地很好,所以把布局视口宽度设置地很大,一般在768px-1024px之间,最常见的宽度是980px

如下图例子,在iPhone6(375*667)下,浏览器宽度只有375px,但是body的宽度却是980px

这个宽度可以通过document.documentElement.clientWidth得到。

为何要这样设计呢?

在没有做任何移动端适配的时候,浏览器希望在移动端也尽可能合适的显示网页,如果没有设置比较大的布局适口宽度,移动端的宽度比 PC 端是小很多的,很容易造成布局崩溃。

meta 标签

做移动端适配,总是要加上这行代码

1
<meta name="viewport" content="width=device-width">

意思是让页面的布局视口的宽度等于视觉视口的宽度,此时页面元素会以设备逻辑像素宽度做为文档宽度进行布局。

一般还会禁止用户缩放

1
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;">

参考资料

  1. https://mp.weixin.qq.com/s/W0KtXtLYUskJ48NOQUPHUg
  2. https://imweb.io/topic/5a523cc0a192c3b460fce3a5