带你走进“像素”的世界

前言

一位漂亮的UI小姐姐,给了一个高60px、宽112px的确定按钮,和一个宽高都是60px的返回按钮,其中返回按钮由端上实现,确定按钮由H5实现。于是大家都按照设计稿写好了样式,联调的时候,pc没有问题,开心;ios没有问题,开心极了;然而安卓在安卓机上拉胯了!!
在这里插入图片描述
于是开始排坑之路。

像素(pixel)

像素(pixel)是影像显示的基本单位,它是一个取样单位,一般情况像素采用点或者方块显示。一般屏幕上每个像素采用RGB色域(红、绿、蓝),印刷机采用CMYK色域(青、品红、黄、黑)。详情可以参考wiki百科。

物理像素(physical pixel)

物理像素是显示屏中最小的物理显示单位,它是一个纯硬件指标,反映了显示屏内led灯的数量,在出厂时就已经固定。比如我把屏幕对半折,那么它的物理像素也只有一半。每个像素点具有自己的颜色值和亮度。
在这里插入图片描述
现代液晶屏幕按设计有一个原始分辨率,它代表像素和三元素组之间的完美匹配。(阴极射线管也是用红-绿-蓝荧光三元素组,但是它们和影像像素并不重合,因此和像素无法比较)

非原始分辨率必须通过在液晶屏幕上拟合重新取样来实现,要使用插值算法。这经常会使屏幕看起来破碎或模糊。例如,原始分辨率为1280×1024的显示器在分辨率为1280×1024时看起来最好,也可以通过用几个物理三元素组来表示一个像素以显示800×600,但可能无法完全显示1600×1200的分辨率,因为物理三元素组不够。

CSS像素(CSS pixel)

在CSS规范中,长度单位可以分为绝对(absolute)单位和相对(relative)单位两类。其中CSS像素px是相对单位。
在这里插入图片描述

由于不同的物理设备的物理像素的大小是不一样的,所以css认为浏览器应该对css中的像素进行调节,使得浏览器中 1css像素的大小在不同物理设备上看上去大小总是差不多 ,目的是为了保证阅读体验一致。css规范中使用“参考像素”来进行换算。

参考像素

根据W3C文档中的描述:

The reference pixel is the visual angle of one pixel on a device with a pixel density of 96dpi and a distance from the reader of an arm’s length. For a nominal arm’s length of 28 inches, the visual angle is therefore about 0.0213 degrees. For reading at arm’s length, 1px thus corresponds to about 0.26 mm (1/96 inch).

在这里插入图片描述

参考像素是一个视觉角度。假设当前设备的像素密度96dpi(即一英寸96个点),当用户从距离一胳膊远的地方看设备,眼睛与其中两个相邻点之间距离形成的夹角度数就是参考像素。常人的胳膊长度约为28英寸,其可视角度约为(1/96)in / (28in * 2 * PI / 360deg) = 0.0213度,此时1px大约是0.26mm。当观看距离越远时,参考像素就越大(指角度对应在屏幕上的尺寸变大)。

虽然规范这么定义,但明显不好理解,所以每个浏览器具体实现的时候,都是根据“设备像素”直接换算的。

举一个🌰

直观感受一下css像素的相对性。写一个如下的样式:

.box {
    width: 100px;
    height: 100px;
    background-color: aqua;
}

在这里插入图片描述

此时修改页面,放大200%。
在这里插入图片描述

可以看到方块变大了一倍,但是宽高样式还是100px。
在这里插入图片描述

这是因为默认情况下,一个CSS像素等于一个物理像素。将浏览器放大200%后,就是让一个1CSS像素等于2物理像素,即使用22的物理像素表示一个11的CSS像素。在高PPI的设备上,一个CSS像素默认等于多个物理像素的尺寸。

像素密度(Dots Per Inch,Pixel Per Inch )

像素密度也叫显示密度或者屏幕密度,缩写为DPI(Dots Per Inch)或者PPI(Pixel Per Inch),含义相同。细微差异如下:

ppi和dpi(每英寸点数)。从技术角度说,“像素”(p)只存在于计算机显示领域,而“点”(d)只出现于打印或印刷领域。

经常看到相同尺寸的屏幕像素尺寸却不同,也就是DPI的差异,比如4.7英寸的iPhone6像素尺寸为750x1334px,而4.7英寸的HTC One像素尺寸为1080x1920px

像素密度很容易算出来:
P P I = d p d i = w p 2 + h p 2 d i PPI ={dp\over{di} }={\sqrt{wp^2+hp^2}\over di} PPI=didp=diwp2+hp2
其中:

  • dp为屏幕对角线的分辨率
  • di为屏幕对角线的长度(单位为英寸)
  • wp为屏幕横向分辨率
  • hp为屏幕纵向分辨率

以iPhone6为例:

// 屏幕对角线的像素尺寸 / 物理尺寸(inch)
Math.sqrt(750*750 + 1334*1334) / 4.7 = 326ppi

常见像素密度缩写:

缩写名称PPI
TVDPIMedium High density≈160–213
HDPI or HiDPIHigh density≈213–240
XHDPIeXtra High density≈240–320
XXHDPIeXtra eXtra High density≈320–480
XXXHDPIeXtra eXtra eXtra High density≈480–640

设备独立像素(device independent pixel)

设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css像素),然后由相关系统转换为物理像素。

如果设备独立像素作为单位,在Android中缩写为DIP(Device Independent Pixels)或者DP(Density-independent Pixels),含义一致。

Android设备的特点是屏幕尺寸很多,因此为了显示能尽量和设备无关,dip参照的density是160。计算公式为:

// 当屏幕密度为160(单位是ppi或者dpi,一个意思)时,px === dip
px = dip * density / 160 
// 所以
dip = px * 160 / dpi

当然,这两个式子都只适用于Android设备,这个dip拿到其它地方去没什么意义。

一般情况可以认为下面等式成立:

设备独立像素 = CSS像素 = 逻辑像素(都具备相对性)

物理像素和设备独立像素之间的关系就是设备像素比。

设备像素比(device pixels ratio)

Device pixel ratio, the ratio between physical pixels and logical pixels used by cascading style sheets (CSS): other names for it are “CSS Pixel Ratio” and “dppx”

从定义中可以知道,DPR就是物理像素 (physical pixels) 和设备无关像素 (device-independent pixels (dips)) 的比例。公式表示就是:window.devicePixelRatio = physical pixels / dips

通过devicePixelRatio,就可以知道一个设备独立像素代表多少个物理像素。例如,在Retina屏上,devicePixelRatio的值为2,也就是说1个css像素相当于2个物理像素。但是早期devicePixelRato输出的值不太准确(目前可以放心使用),具体的情况可以看下PPK大神的文章。

  • IE以及FireFox压根不支持。可能接下来的版本会支持。
  • Opera桌面浏览器时,即使是视网膜设备,返回的值也是1而不是2。不过,这个bug在后续的版本中会修复的。
  • Opera Mobile 10不支持,不过Opera Mobile 12正确支持。
  • UC总是显示1,不过其viewport属性有些让人费解。
  • 只有最近的Chrome浏览器才能正确实现该属性。Chrome19返回不准确的1, Chrome22可以正确返回2。
  • MeeGo WebKit (Nokia N9/N950)就吓人了:当你应用了meta viewport时候(类似<meta name="viewport" content="width=device-width">),值会从1变成1.5!
    在css中,可以通过-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和 -webkit-max-device-pixel-ratio进行媒体查询,对不同dpr的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)。

viewport像素

ppk大神对于移动设备上的viewport有着非常多的研究(第一篇,第二篇,第三篇),有兴趣的同学可以去看一下。ppk认为,移动设备上有三个viewport。

layout viewport(布局视口)

如果把移动设备上浏览器的可视区域设为viewport的话,某些网站就会因为viewport太窄而显示错乱,所以这些浏览器就决定默认情况下把viewport设为一个较宽的值,比如980px,这样的话即使是那些为桌面设计的网站也能在移动浏览器上正常显示了。ppk把这个浏览器默认的viewport叫做 layout viewport。这个layout viewport的宽度可以通过 document.documentElement.clientWidth 来获取。
在这里插入图片描述

visual viewport(视觉视口)

因为 layout viewport 的宽度是大于浏览器可视区域的宽度的,所以我们还需要一个viewport来代表 浏览器可视区域的大小,ppk把这个viewport叫做 visual viewport。visual viewport的宽度可以通过window.innerWidth 来获取,但在Android 2, Oprea mini 和 UC 8中无法正确获取。
在这里插入图片描述

Ideal viewport(理想视口)

但浏览器觉得还不够,因为现在越来越多的网站都会为移动设备进行单独的设计,所以必须还要有一个能完美适配移动设备的viewport。所谓的完美适配指的是,首先不需要用户缩放和横向滚动条就能正常的查看网站的所有内容;第二,显示的文字的大小是合适,比如一段14px大小的文字,不会因为在一个高密度像素的屏幕里显示得太小而无法看清,理想的情况是这段14px的文字无论是在何种密度屏幕,何种分辨率下,显示出来的大小都是差不多的。当然,不只是文字,其他元素像图片什么的也是这个道理。ppk把这个viewport叫做 ideal viewport。此时Ideal viewport像素可以理解为设备独立像素。
在这里插入图片描述
在这里插入图片描述

小结

其中的ideal viewport是最适合移动设备的viewport,ideal viewport的宽度等于移动设备的屏幕宽度,只要在css中把某一元素的宽度设为ideal viewport的宽度(单位用px),那么这个元素的宽度就是设备屏幕的宽度了,也就是宽度为100%的效果。ideal viewport 的意义在于,无论在何种分辨率的屏幕下,那些针对ideal viewport 而设计的网站,不需要用户手动缩放,也不需要出现横向滚动条,都可以完美的呈现给用户。

其他名词

看一张从网上淘来的图片:
在这里插入图片描述

渲染像素(render pixel)

渲染像素是在系统内部对物理像素的分配进行再一次的调整,在pc上,渲染像素其实就是设置里边的分辨率。对于显示设备,系统为显示设备提供渲染尺寸,由显示设备的“缩放引擎”(带存储器阵列的数字视频处理器)处理。这种“缩放引擎”一般内部有一系列的合理分辨率和一个推荐分辨率。一般推荐分辨率就是最大渲染像素,也是设备的物理分辨率(为了最佳表现)。这是一个软硬件(偏硬)结合的缩放方案。由于部分设备不能设置渲染像素,可直接等同于物理像素

逻辑像素/点(device point / device pixel / point )

逻辑像素/点是为了调和距离不一样导致的差异,将所有设备根据距离,透视缩放到一个相等水平的观看距离之后得到的尺寸,是一个抽象的概念,这个单位就是ios开发的pt,安卓开发的dp,前端的css px。对于pc,包括win(8+) linux,mac,由各自系统的或者对应软件(比如webview内部)提供的图像界面处理引擎处理进行缩放。

相关文档

设备像素比devicePixelRatio简单介绍 « 张鑫旭-鑫空间-鑫生活
Android dp 和 CSS px
https://www.zhihu.com/question/313971223/answer/628236155
https://www.zcoldwater.com/articles/2019/12/10/1575969868852.html
The Ultimate Guide To iPhone Resolutions
CSS像素、物理像素、逻辑像素、设备像素比、PPI、Viewport
移动前端开发之viewport的深入理解 - 无双 - 博客园
【CSS】绝对单位和相对单位
你真的了解css像素嘛?
完全理解px,dpr,dpi,dip | 黯羽轻扬

热门文章

暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法&#xff0c;在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较&#xff0c;从而确定目标数是在中间数的左边还是右边&#xff0c;将查…
暂无图片
编程学习 ·

GMX 命令分类列表

建模和计算操作命令&#xff1a; 1.1 . 创建拓扑与坐标文件 gmx editconf - 编辑模拟盒子以及写入子组(subgroups) gmx protonate - 结构质子化 gmx x2top - 根据坐标生成原始拓扑文件 gmx solvate - 体系溶剂化 gmx insert-molecules - 将分子插入已有空位 gmx genconf - 增加…
暂无图片
编程学习 ·

一文高效回顾研究生课程《数值分析》重点

数值分析这门课的本质就是用离散的已知点去估计整体&#xff0c;就是由黑盒子产生的结果去估计这个黑盒子。在数学里这个黑盒子就是一个函数嘛&#xff0c;这门课会介绍许多方法去利用离散点最大化地逼近这个函数&#xff0c;甚至它的导数、积分&#xff0c;甚至微分方程的解。…
暂无图片
编程学习 ·

在职阿里5年,一个28岁女软测工程师的心声

简单的先说一下&#xff0c;坐标杭州&#xff0c;14届本科毕业&#xff0c;算上年前在阿里巴巴的面试&#xff0c;一共有面试了有6家公司&#xff08;因为不想请假&#xff0c;因此只是每个晚上去其他公司面试&#xff0c;所以面试的公司比较少&#xff09; ​ 编辑切换为居中…
暂无图片
编程学习 ·

字符串左旋c语言

目录 题目&#xff1a; 解题思路&#xff1a; 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a; 总代码&#xff1a; 题目&#xff1a; 实现一个函数&#xff0c;可以左旋字符串中的k个字符。 例如&#xff1a; ABCD左旋一个字符得到BCDA ABCD左旋两个字符…
暂无图片
编程学习 ·

设计模式--观察者模式笔记

模式的定义与特点 观察者&#xff08;Observer&#xff09;模式的定义&#xff1a;指多个对象间存在一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式&#xf…
暂无图片
编程学习 ·

睡觉突然身体动不了,什么是睡眠痽痪症

很多朋友可能有这样的体验&#xff0c;睡觉过程中突然意识清醒&#xff0c;身体却动弹不了。这时候感觉非常恐怖&#xff0c;希望旁边有一个人推自己一下。阳光以前也经常会碰到这样的情况&#xff0c;一年有一百多次&#xff0c;那时候很害怕晚上到来&#xff0c;睡觉了就会出…
暂无图片
编程学习 ·

深入理解C++智能指针——浅析MSVC源码

文章目录unique_ptrshared_ptr 与 weak_ptrstd::bad_weak_ptr 异常std::enable_shared_from_thisunique_ptr unique_ptr 是一个只移型别&#xff08;move-only type&#xff0c;只移型别还有std::mutex等&#xff09;。 结合一下工厂模式&#xff0c;看看其基本用法&#xff…
暂无图片
编程学习 ·

@TableField(exist = false)

TableField(exist false) //申明此字段不在数据库存在&#xff0c;但代码中需要用到它&#xff0c;通知Mybatis-plus在做写库操作是忽略它。,.
暂无图片
编程学习 ·

Java Web day15

第十二章文件上传和下载 一、如何实现文件上传 要实现Web开发中的文件上传功能&#xff0c;通常需要完成两步操作&#xff1a;一.是在Web页面中添加上传输入项&#xff1b;二是在Servlet中读取上传文件的数据&#xff0c;并保存到本地硬盘中。 需要使用一个Apache组织提供一个…
暂无图片
编程学习 ·

【51nod 2478】【单调栈】【前缀和】小b接水

小b接水题目解题思路Code51nod 2478 小b接水 题目 输入样例 12 0 1 0 2 1 0 1 3 2 1 2 1输出样例 6解题思路 可以发现最后能拦住水的都是向两边递减高度&#xff08;&#xff1f;&#xff09; 不管两个高积木之间的的积木是怎样乱七八糟的高度&#xff0c;最后能用来装水的…
暂无图片
编程学习 ·

花了大半天写了一个UVC扩展单元调试工具

基于DIRECTSHOW 实现的&#xff0c;用的是MFC VS2019. 详见&#xff1a;http://www.usbzh.com/article/detail-761.html 获取方法 加QQ群:952873936&#xff0c;然后在群文件\USB调试工具&测试软件\UVCXU-V1.0(UVC扩展单元调试工具-USB中文网官方版).exe USB中文网 USB中文…
暂无图片
编程学习 ·

贪心(一):区间问题、Huffman树

区间问题 例题一&#xff1a;区间选点 给定 N 个闭区间 [ai,bi]请你在数轴上选择尽量少的点&#xff0c;使得每个区间内至少包含一个选出的点。 输出选择的点的最小数量。 位于区间端点上的点也算作区间内。 输入格式 第一行包含整数 N&#xff0c;表示区间数。 接下来 …
暂无图片
编程学习 ·

C语言练习实例——费氏数列

目录 题目 解法 输出结果 题目 Fibonacci为1200年代的欧洲数学家&#xff0c;在他的着作中曾经提到&#xff1a;「若有一只免子每个月生一只小免子&#xff0c;一个月后小免子也开始生产。起初只有一只免子&#xff0c;一个月后就有两只免子&#xff0c;二个月后有三只免子…
暂无图片
编程学习 ·

Android开发(2): Android 资源

个人笔记整理 Android 资源 Android中的资源&#xff0c;一般分为两类&#xff1a; 系统内置资源&#xff1a;Android SDK中所提供的已经定义好的资源&#xff0c;用户可以直接拿来使用。 用户自定义资源&#xff1a;用户自己定义或引入的&#xff0c;只适用于当前应用的资源…
暂无图片
编程学习 ·

零基础如何在短时间内拿到算法offer

​算法工程师是利用算法处理事物的职业 算法&#xff08;Algorithm&#xff09;是一系列解决问题的清晰指令&#xff0c;也就是说&#xff0c;能够对一定规范的输入&#xff0c;在有限时间内获得所要求的输出。 如果一个算法有缺陷&#xff0c;或不适合于某个问题&#xff0c;执…
暂无图片
编程学习 ·

人工智能:知识图谱实战总结

人工智能python&#xff0c;NLP&#xff0c;知识图谱&#xff0c;机器学习&#xff0c;深度学习人工智能&#xff1a;知识图谱实战前言一、实体建模工具Protegepython&#xff0c;NLP&#xff0c;知识图谱&#xff0c;机器学习&#xff0c;深度学习 人工智能&#xff1a;知识图…
暂无图片
编程学习 ·

【无标题】

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…