乐趣区

关于css:深究移动端适配那些坑小数像素图片模糊

一、适配计划的利弊

缩放

最早是间接用 px 来写,而后用 meta 标签里的 scale 来缩放整个页面,简略粗犷。益处是简略疾速,害处是不能管制局部款式的缩放,一些边框之类的在小屏会变得很细。据说晚期天猫首页就是这么干的。其实之后所有适配计划都是这个原理,在编码的时候以设计稿为规范,到手机显示时则依据不同机型的显示宽度而缩放,只是缩放的技术不同。

rem

  • 1rem 等于 <html> 的 fontSize 大小;
  • rem 适配计划只须要给 <html> 的 fontSize 设置任意大小。因为设计稿个别为 750px 宽,所以 fontSize 设置为 75px 是比拟常见的教训规范,太大或太小对最终后果的精准度可能有影响。之后就能够确定 1rem = 75px,而后在还原设计稿时将 px 计算转成 rem 即可。并且要在 JavaScript 中退出脚本(flexable.js),依据屏幕显示宽度来动静扭转 <html> 的 fontSize,屏幕宽度越大则 fontSize 越大;
  • rem 的劣势是 根节点 fontSize 可控(即 rem 的缩放规范齐全可控),兼容性好 。但始终是为了模拟出 vw 的成果, 存在多一层转换,麻烦、不直观且精准度稍差

vw

  • 1vw 等于以后屏幕显示区域的百分之一;
  • vw 就是为动静布局而生的,所以不须要辅助任何脚本。个别设计稿宽度为 750px,那么还原设计稿的时候,1vw = 7.5px,依据这个将设计稿上的 px 换算成 vw 即可;
  • vw 劣势是 准确、便捷,但兼容性稍差,规范的实现比 rem 晚 3 年;

em

  • em 当初个别不用来做挪动端适配,这里只是顺带一讲;
  • em 是惟一一个能够在部分实现绝对长度的单位;

em 在 font-size 中应用是绝对于父元素的字体大小,在其余属性中应用是绝对于本身的字体大小,如 width(来自:MDN)

  • em 的呈现是为了解决文字无奈跟着页面一起放大这个问题。在 ie6 的那个年代,若应用 px 来设置 font-size,当用户应用 Ctrl+ 滚轮 来放大页面时,文字是不会跟着放大的。然而古代的浏览器曾经没有这个问题了;
  • 利用 em 依据本身字体动静适配的个性,能够实现很多需要,如依据字体大小动静扭转行高、宽度、边距等;

二、逻辑像素和物理像素

逻辑像素就是咱们平时所讲的像素,也就是 CSS 中的 px,所以逻辑像素是一种抽象化的数字单位。而物理像素是指电子屏幕的最小发光单元。

其实最早的时候,不须要这样严格辨别,因为那时候 1 逻辑像素就是用 1 物理像素来显示,也就是设配像素比(DPR,物理像素和逻辑像素的比例)为 1。起初 iphone4 突破了这个规定,它那块视网膜屏幕能够用 2 倍物理像素来显示 1 逻辑像素,从而使手机的显示成果更细腻。如下图,即 DPR2 ⇒ 横纵各有 2 个像素。

手机还有屏幕像素密度(PPI as Pixels Per Inch)的概念,也就是每英寸所蕴含的物理像素数量,一般来说在手机的应用视距下 PPI 达到 300 人眼就无奈看出屏幕的像素点,这也就是苹果的视网膜屏幕的名称来由。

三、挪动端图片含糊

挪动端适配图片,因为挪动端 dpr 不同,导致雷同的位图会在高 dpr 的手机上含糊,需依据 dpr 应用 N 倍图可解决,即 dpr = 2 应用 2 倍图。

起因是,位图的像素信息(地位、色彩)是固定的,但在高 dpr 的屏幕显示时,会用数倍的物理像素去显示同样的逻辑像素,底层的算法并不会将物理像素一一对应上图片像素,而是进行 就近取色,最终导致图片含糊。如下图:

为什么要就近取色,而不是间接通过多个物理像素显示同一色彩呢?是因为用数倍物理像素显示一张图片时,如果只是简略粗犷的用 N 个物理像素间接显示 1 个图片像素,在挪动端的高素质屏幕下锯齿感会很显著,为了解决这个问题则采纳了 平滑解决技术(就近取色属于其中一个操作)。假如有一张显示 0 的图片,则上面是处理过程:

从上图能够看出,dpr2 在图像的细腻水平上能比 dpr1 解决得更好,所以才不是简略地用 4 个物理像素代替 1 个物理像素。最终论断是不是不能间接取色,而是就近取色更好。

四、小数像素导致的图片比例失调

做挪动端适配的时候因为 px 是由 rem/vw 转换后的值,所以必定会存在小数的状况,小数逻辑像素无奈与物理像素完满对齐的,不可能让 1 个残缺的物理像素去显示 0.333 的逻辑像素,所以面对这种状况 webkit 内核会有两种对齐计划:

蓝色代表计算尺寸,黑线框代码理论对齐后的尺寸。图片来自:[](https://trac.webkit.org/wiki/…https://trac.webkit.org/wiki/…

enclosingIntRect 是简略地将渲染面积扩充 1px,保障能齐全笼罩渲染的物理像素,这个计划只在少部分中央用到,如渲染 svg,为了保障盒子能残缺包裹矢量图。

pixelSnappedIntRect 则顾名思义,是指在容器内折断像素的计划。但并不是简略的四舍五入,因为如果仅仅四舍五入,会导致最终撑开或与容器相差太大,这个计划是为了保障最终渲染后果跟计算结果至少相差 1px。一个容器内有三张宽 14.25px 的图片真正的大抵渲染计算过程是:

  • 首先将容器第一张图宽度四舍五入,那么第一个张图变成 14px 宽;
  • 因为第一张图四舍五入后少了 0.25px,那第二张图则须要相应加上 0.25px,14.25 + 0.25 = 14.5px,四舍五入后则为 15px;
  • 第二张图多用了 15 – 14.5 = 0.5px,所以第三张图要减去这 0.5px,14.5 – 0.5 四舍五入后为 14px;
  • 最终,容器都计算宽度为 14.25 * 3 = 42.75,理论对齐物理像素后是 14 +15 +14 = 43,这跟咱们申明的宽度仅误差了 0.25px,所以最终渲染后果与小数像素的误差不超过 1px。

从下面的计算结果来看三个 div 中第二个的宽度是不同的,所以这也就是小数像素导致款式偏差的起因。因为这种款式偏差在各种布局盒子里都会存在,但因为在图片上成果更显著(图片挤压),所以通常只在图片显示时须要解决这个问题。目前没有比拟好的解决方案,只能尽量写死像素,图片则能够应用 svg。

这一块是对于 LayoutUint 的常识,是用来解决页面缩放时的渲染问题的,具体能够查看 webkit 团队的文章

五、挪动端适配计划的思考(起源:[](https://www.zhihu.com/questio…https://www.zhihu.com/questio…):

  • 在嵌入进客户端时,会呈现不同尺寸手机的 web 适配和 native 适配不统一,导致用户体验割裂;
  • 在设计层面,当客户应用更大屏幕冀望地是能看到更多的内容,而这个适配计划却仅仅是让 5 寸屏幕和 4 寸屏幕到的信息量是一样的;
  • 对于字体的问题,从用户体验来说用户心愿看到的字体是相对大小的,就像看报纸,多大张的报纸,字体都应该是一样大,有一个最适宜浏览的字体大小,而自适应突破了这种设计哲学。知乎的挪动端页面,则齐全应用了 px;

参考资料:
CSS 的值与单位
LayoutUnit & Subpixel Layout
rem 产生的小数像素问题
LayoutUnit
深刻理解 canvas 在挪动端绘制含糊的问题

退出移动版