jieye の 数字花园

Search

Search IconIcon to open search

基本知识

Last updated Aug 19, 2022

# 基本知识

#

视口(viewport)就是浏览器显示页面内容的屏幕区域。最先由 Apple 引入,用于解决移动端页面的显示问题,通过一个叫 <meta> 的 DOM 标签,允许我们可以定义视口的各种行为,比如宽度,高度,初始缩放比例等,视口可以分为布局视口视觉视口理想视口

# 布局视口 layout viewport

一般移动设备的浏览器都默认设置了一个布局视口,用于解决早期的 PC 端页面在手机上显示的问题。

layout viewport 是一个固定的值,由浏览器厂商设定,

所以 PC 上的网页大多都能在手机上呈现,只不过元素看上去很小,一般默认可以通过手动缩放网页。

image-20210806171825292

而在移动端上,由于要使为 PC 端浏览器设计的网站能够完全显示在移动端的小屏幕里,此时的布局视口会远大于移动设备的屏幕,就会出现滚动条。

1
2
var layoutViewportWidth = document.documentElement.clientWidth
var layoutViewportHeight = document.documentElement.clientHeight

# 视觉视口 visual viewport

image-20210806171911621

用户正在看到的网页的区域。用户可以通过缩放来查看网站的内容。如果用户缩小网站,我们看到的网站区域将变大,此时视觉视口也变大了,同理,用户放大网站,我们能看到的网站区域将缩小,此时视觉视口也变小了。不管用户如何缩放,都不会影响到布局视口的宽度。

1
2
var visualViewportWidth = window.innerWidth
var visualViewportHeight = window.innerHeight

# 理想视口 ideal viewport

现在已经有两个 viewport 了,但浏览器觉得还不够,因为现在越来越多的网站都会为移动设备进行单独的设计,所以必须还要有一个能完美适配移动设备的 viewport。

所谓的完美适配指的是:

这个 viewport 叫做 ideal viewport(理想视口)window.screen.width

我们可以通过 meta 设置将布局视口转换为理想视口,

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

# meta 视口标签

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

属性解释
width正整数|device-width,视口宽度,单位是 CSS 像素,如果等于 device-width,则为理想视口的宽度
height正整数|device-height,视口宽度,单位是 CSS 像素,如果等于 device-height,则为理想视口的宽度
initial-scale0-10,初始缩放比例,允许小数点
maximum-scale0-10,最大缩放比例,必须大于等于 minimum-scale
minimum-scale0-10,最小缩放比例,必须小于等于 maximum-scale
user-scalableyes/no,是否允许用户缩放页面,默认是 yes

# 常用单位

# 物理像素

设备屏幕实际拥有的像素点,屏幕的基本单元,是有实体的。比如 iPhone 6 的屏幕在宽度方向有 750 个像素点,高度方向有 1334 个像素点,所有 iPhone 6 总共有 750*1334 个像素点。同一个设备的物理像素是固定的,这是厂商在出厂时就设置好了的。

屏幕普遍采用 RGB 色域(红、绿、蓝三个子像素构成),而印刷行业普遍使用 CMYK 色域(青、品红、黄和黑)。

# 逻辑像素

也叫“设备独立像素”(Device Independent Pixel,DIP),可以理解为反映在 CSS/JS 程序里面的像素点,也就是说 css 像素是逻辑像素的一种。除了 css 像素是逻辑像素以外,我们平时描述一张图片宽高时一般用 200px * 100px,这里的px也是逻辑像素。

# 设备像素比(Device Pixel Ratio,DPR)

在很久以前,CSS 里写个 1px,屏幕就给你渲染成 1 个实际的像素点,即 DPR=1。

后来苹果公司为其产品 mac、iPhone 以及 iPad 的屏幕配置了 Retina 高清屏,也就是说这种屏幕拥有的物理像素点数比非高清屏多 4 倍甚至更多。如果还按照 DPR=1 进行展示,那么同一张图片在高清屏上面显示的区域面积会是非高清屏的 1/4,这样的话由于图片在屏幕上的展示面积大大缩小,也会导致出现“看不清”的问题。

因此苹果使用 4 个乃至更多物理像素来渲染 1 个逻辑像素,这样一来,同样的 CSS 代码设置的尺寸,在 Retina 和非 Retina 屏幕上看起来大小是一样的,但在 Retina 屏幕上要精细得多。

image-20210806174558008

image-20210806175307321

在 Retian 屏上,DPR 不再是 1,而是大于 1,比如 2(iPhone 5 6 7 8)或 3(iPhone 6 Plus 等一系列 Plus)或者为非整数(一些 Android 机),说不定还会涨。

image-20210806174807000

举个例子:iPhone 6 的物理像素上面已经说了,是 750 _ 1334,那它的逻辑像素呢?我们只需在 iPhone 6 的 Safari 里打印一下screen.widthscreen.height就知道了,结果是 375 _ 667,这就是它的逻辑像素,据此很容易计算出 DRP 为 2。当然,我们还可以直接通过window.devicePixelRatio这个值来获取 DRP,打印结果是 2,符合我们的预期。

PS:在苹果的带动下,Retina 技术在移动设备上已经成了标配,所以前端攻城狮必须直面如下事实:

1
2
1. 你想画个1px的下边框,但屏幕硬是塞给你一条宽度为2—3个物理像素的线。
2. 你没法像安卓或iOS的同事那样直接操纵物理像素点。

这就是初级前端面试必考题之“1px 边框问题”的由来。

# EM

EM 相对于元素自身的 font-size

1
2
3
4
p {
  font-size: 16px;
  padding: 1em; /* 1em = 16px */
}

如果元素没有显式地设置 font-size,那么 1em 等于多少呢?

这个问题其实跟咱说的 em 没啥关系,这里跟 font-size 的计算规则相关,回顾一下。如果元素没有设置 font-size,会继承父元素的 font-size,如果父元素也没有,会沿着 DOM 树一直向上查找,直到根元素 html,根元素的默认字体大小为 16px。

# REM

REM = Root EM,顾名思义就是相对于根元素的 EM。所以它的计算规则比较简单,

1 rem 就等于根元素 html 的字体大小,

1
2
3
4
5
6
7
html {
  font-size: 14px;
}

p {
  font-size: 1rem; /* 1rem = 14px */
}

所以,如果我们改变根元素的字体大小,页面上所有使用 rem 的元素都会被重绘。

EM 和 REM 都是相对单位,我们在做响应式布局的时候应该如何选择呢?

根据两者的特性,

实际开发中,设计图的单位是 CSS 像素,我们可以借助一些工具将 px 自动转换为 rem,下面是一个用 PostCSS 插件在基于 Webpack 构建的项目中自动转换的例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var px2rem = require('postcss-px2rem');

module.exports = {
  module: {
    loaders: [
      {
        test: /\.css$/,
        loader: "style-loader!css-loader!postcss-loader"
      }
    ]
  },
  postcss: function() {
    return [px2rem({remUnit: 75})];
  }
}

# vw,vh,百分比

浏览器对于 vwvh 的支持相对较晚,在 Android 4.4 以下的浏览器中可能没办法使用,下面是来自 Can I use 完整的兼容性统计数据,

![image-20210503152608975](../../../../../Mobile Documents/com~apple~CloudDocs/learn-articles/pics/image-20210503152608975.png)

新生特性往往逃不过兼容性的大坑,但是这并不妨碍我们了解它。

响应式设计里,vwvh 常被用于布局,因为它们是相对于理想视口:

以 iPhoneX 为例,vw 和 CSS 像素的换算如下,

1
2
3
4
5
6
7
8
<!-- 假设我们设置视口为完美视口,这时视口宽度就等于设备宽度,CSS 像素为 375px -->
<meta name="viewport" content="width=device-width, initial-scale=1">

<style>
  p {
    width: 10vw; /* 10vw = 1% * 10 * 375px = 37.5px */
  }
</style>

我们说百分比也可以用来设置元素的宽高,它和 vwvh 的区别是什么?

这里只需要记住一点,百分比是相对于父元素的宽度和高度计算的。

# 二倍图

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 /* 在 iphone8 下面 */
img{
 /*原始图片100*100px*/
 width: 50px;
 height: 50px;
}
.box{
 /*原始图片100*100px*/
 background-size: 50px 50px;
}

# 媒体查询

媒体查询(Media Query)是 CSS3 规范中的一部分,媒体查询提供了简单的判断方法,允许开发者根据不同的设备特征应用不同的样式。响应式布局中,常用的设备特征有,

选择 min-widthmax-width 取值的过程,称为设备断点选择,它可能取决于产品设计本身,下面是 百度 Web 生态团队 总结的一套比较具有代表性的设备断点,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/* 很小的设备(手机等,小于 600px) */
@media only screen and (max-width: 600px) { }

/* 比较小的设备(竖屏的平板,屏幕较大的手机等, 大于 600px) */
@media only screen and (min-width: 600px) { }

/* 中型大小设备(横屏的平板, 大于 768px) */
@media only screen and (min-width: 768px) { }

/* 大型设备(电脑, 大于 992px) */
@media only screen and (min-width: 992px) { }

/* 超大型设备(大尺寸电脑屏幕, 大于 1200px) */
@media only screen and (min-width: 1200px) { }