# 9.什么是像素

转自:锐基

个人总结:

  • 1px 就是 1 个像素,而 1 个像素就是屏幕上一个点的大小,这个点究竟有多大,是由显示器的分辨率以及显示器的物理尺寸来决定的

  • 物理像素:设备屏幕实际拥有的像素点。

  • 逻辑像素:可以理解为反映在 CSS/JS 代码里的像素点数。

  • dpr = 物理像素/逻辑像素

  • 以前 CSS 写一个 1px ,屏幕就会给渲染成 1 个实际的像素点,即 dpr = 1

# 面试官:我是小白,像素是什么?

个人总结:

近几天面试时被问到 CSS 单位时,涉及到了 px ,面试官则说:

我现在就是一个小白,麻烦你跟我讲一下什么叫像素?

😭 害,我支支吾吾地说了物理像素和逻辑像素,还有 dpr ,然后被面试官追问了...

以前写移动端页面的时候有简单的了解过,但是至今也已经一年多了,是该好好来总结一下了。

# 什么是像素?

维基百科 (opens new window) :像素(px)是影像显示的基本单位,译自英文“pixel”,pix 是英语单词 picture 的常用简写,加上英语单词“元素”element,就得到 pixel,故“像素”表示“画像元素”之意,有时亦被称为 pel(picture element)。

从概念上来说,像素既不是一个确定的物理量,也不是一个点或者小方块,而是一个抽象概念。所以像素在不同的上下文中所描述的东西可能不一样,一般分为“物理像素”和“逻辑像素”

# 物理像素(设备像素)

**设备屏幕实际拥有很多像素,它是屏幕的基本单元,是有实体的。**比如 iPhone 6 的屏幕在宽度方向有 750 个像素,高度方向有 1334 个像素点,那么 iPhone 6 就总共有 750 * 1334 个像素点

  1. 从出厂就固定了,单位为 pt,每个手机的物理像素是固定的,有实体的。

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

image

# 逻辑像素

也叫“设备独立像素”(DIP,device independent pixels),可以理解为放映在 CSS/JS 程序中的像素点,也就是说 CSS 像素就是逻辑像素的一种。平时描述一张图片的宽高时也是指逻辑像素。

# 1. 设备独立像素

  1. 设备独立像素与设备无关的逻辑像素。可以通过程序控制的,是一个总体概念,包括 px
  2. 分辨率(非严禁的说)就是设备独立像素。比如分辨率:375 * 667,就是人工把屏幕分为:宽 375 个方块,高 667 个方块。
  3. 一个设备独立像素可能有 1 个或多个物理像素点,包含越多,屏幕越清晰

# 2. px 是相对单位,相对的是设备独立像素

  1. 一般情况,页面缩放比 1:1 时,1px 就是一个设备独立像素
  2. 同个设备,调整分辨率可以改变 1px 的值。
  3. 页面放大一倍,原来 1px 变成 2px。就是变成 2px 的宽高了。假设原来 320px 填满,现在只需要 160px

即:物理像素=》设备独立像素=》px

# 为什么要有设备独立像素和设备像素

  • iPhone3GS 和 iPhone 尺寸都是 3.5 寸,但是 iPhone4 的物理分辨率是 640×960,iPhone3GS 物理分辨率是 320×480。如果按照真实物理像素布局,到 640 物理像素的手机就会有一半空白。为了避免这种问题,就产生了虚拟像素单位。
  1. 设两种手机都是 320 个虚拟像素,只是在 iPhone3GS 上,1 个虚拟像素就是 1 个物理像素。iPhone4 上,1 个虚拟像素就是 2 个物理像素。
  2. 1 个虚拟像素被换算成几个物理像素,这个我们称之为设备像素比,也就是 dpr。
  3. 设备像素比 1:1,使用 1(1×1)个物理像素显示 1 个逻辑像素==1px(页面缩放比 1:1 时)
  4. 设备像素比 3:1,使用 9(3×3)个物理像素显示 1 个逻辑像素==1px(页面缩放比 1:1 时)

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

DPR 是一个设备的物理像素与逻辑像素的比率,即 dpr = 物理像素 / 逻辑像素

像素为什么会有“物理像素”和“逻辑像素”之分?

在以前确实是没有区别, CSS 写一个 1px ,屏幕就会给渲染成 1 个实际的像素点,即 dpr = 1

后来苹果公司为其产品 maciPhone 以及 iPad 的屏幕配置了 Retina 高清屏,也就是说这种屏幕拥有的物理像素点数比非高清平多 4 倍甚至更多。

如果仍然按照 dpr = 1 进行展示,那么同样的驿站图片在高清屏上显示的区域面积会是非高清屏的 1/4 ,由于图片在屏幕上的展示面积大大缩小,也会导致“模糊”的问题。

既然苹果公司推出了 Retina 技术,那么它带来高清展示的前提下也要解决 dpr = 1 的问题。解决的方案就是让 dpr !== 1 。苹果公司经过一系列技术使用 4 个乃至更多物理像素来渲染 1 个逻辑像素,这样,同样的 CSS 代码设置的尺寸,在 Retina 和非 Retina 屏上看起来大小一样,但是高清屏的要精细的多!如图:

image

image

举个 🌰:

上面说到 iPhone 的物理像素是 750 * 1334 ,那它的逻辑像素呢?

Safari 打印 screen.widthscreen.height 得到: 375 * 667

因此易得 dpr = 750 / 375 = 2 。也可以通过 window.devicePixelRatio 来打印 dpr

# 1px 边框问题

前端工程师现在必须直面如下事实:

  1. 你想画一个 1px 的下边框,但是屏幕却展示了一条 2-3 物理像素的线
  2. 你无法像 ios 和安卓一样直接操纵物理像素点

1px 问题有很多解决方案,如:

  • border-image 图片
  • background-image 渐变
  • box-shadow 等
  • 伪元素 + transform 对边框进行缩放

但目前最推崇的还是利用 CSS3transform: scale ,因为其简单易用且兼容性好。

屏幕显示了两个物理像素点,那就可以设置 scale(0.5) ;三个像素点则设置 0.33

可以利用 CSS-webkit-min-device-pixel-ratio 媒体查询针对不同的 dpr 做出处理,以下以 less 代码为例:

@media (-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2) {
  .border-bt-1px(@color) {
    postion: relative;
    &::after {
        position: absolute;
      bottom: 0;
      width: 100%;
      height: 1px;
      background-color: @color;
      transform: scaleY(0.5);
    }
  }
}

# rpx 的原理是什么

rpx 是微信小程序解决自适应屏幕尺寸的尺寸单位。微信小程序规定屏幕的宽度为 750rpx。

无论是在 iPhone6 上面还是其他机型上面都是 750rpx 的屏幕宽度,拿 iPhone6 来讲,屏幕宽度为 375px,把它分为 750rpx 后, 1rpx = 0.5px。

微信小程序同时也支持 rem 尺寸单位, rem 规定屏幕的宽度为 20rem, 所以 1rem = (750/20)rpx = 37.5 rpx

# 如何实现 0.5px

# scale (推荐,但只适用在以 px 为单位的时候)

// 通过伪元素实现 0.5px border
.border::after {
  content: "";
  box-sizing: border-box;
  /* // 为了与原元素等大 */
  position: absolute;
  left: 0;
  top: 0;
  width: 200%;
  height: 200%;
  border: 1px solid gray;
  transform: scale(0.5);
  transform-origin: 0 0;
}

// 通过伪元素实现 0.5px 细线
.line::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 200%;
  height: 1px;
  background: #b3b4b8;
  transform: scale(0.5);
  transform-origin: 0 0;
}

// 进行 dpr 适配可以这样写
@media (-webkit-min-device-pixel-ratio: 2) {
  .line::after {
    /* ... */
    height: 1px;
    transform: scale(0.5);
    transform-origin: 0 0;
  }
}

@media (-webkit-min-device-pixel-ratio: 3) {
  .line::after {
    /* ... */
    height: 1px;
    transform: scale(0.333);
    transform-origin: 0 0;
  }
}

其他详情看:https://jelly.jd.com/article/5f5a4b31da524a0147e97da0

# 参考文章