谈谈CSS中的单位

CSS的各种单位

谈谈CSS中的单位

在几年前,前端大都还只是一个“切图仔”的时候,CSS中用到的单位大多只有“px”,不过都9102年了,情况是否发生了变化呢?

众所周知,前端在近几年发展迅速,各种概念、框架层出不穷。作为前端的重要组成部分的CSS,在这几年也有了较大的发展,前有lesssass之类的预处理语言出现,后有flexgrid这样的布局方案大行其道,甚至在CSS中最常用的单位上,也呈现出百花齐放的景象。今天我们就来聊一聊CSS中的单位。

CSS中的单位还是蛮多的,“px”作为css届的老大哥,想必学习前端的小伙伴无人不识。不过至于后面冒出来的“小弟”,像是emremvwex 等,可能就不一定能认得全了。这里就先介绍一下这几位“小弟”:

em(font size of the element),相对单位,基准点为父节点字体的大小,如果自身定义了font-size按自身来计算,否则按照 1em=16px 来计算(浏览器默认字体是16px)。

rem(font size of the root element),相对单位,和em很相似,只是em是根据父元素计算,而rem是根据根元素(Html)的字体大小来计算,在国内比较流行,多用于移动端适配。

vw(viewport width),视窗宽度,根据视窗的百分比来计算,1vw等于视窗宽度的1%。类似的还有vhvminvmax。浏览器支持的时间较晚,国内流行度不高。

ex 和 ch 单位,类似于 em 和 rem, 依赖于当前的字体和字体大小。 但是,不同的是,这俩是基于字体的度量单位,依赖于设定的字体。多用于一些板式的微调,如角标。


接下来进入正题了,在项目中应该选择什么单位?

在实际项目中,我们在PC端直接使用px 来书写往往是没什么问题的,纠结最多的其实是移动端的适配问题。

移动端适配,指产品适应不同尺寸的手机屏幕。由于现在手机市场百花齐放,除了苹果年年用旧模具造新手机之外,各大安卓厂商充分发挥了自己的想象力,做出来的手机屏幕尺寸、分辨率五花八门,这就导致了在市面同时存在着几十种不同的型号、尺寸。

这下前端就头大了,如何拿着设计给的750px的设计稿,实现出能适配所有手机的效果呢?前端同学想了想,有了以下几种解决方案:

  • 媒体查询(@media)
  • 使用flex弹性布局
  • 使用rem 作为单位来书写,viewport缩放

媒体查询

使用媒体查询,即针对不同尺寸的屏幕定义不同的样式,是jQuery时代的解决方案,其中以Bootstrap 为代表。优点是可以做到一套代码同时运行在PC、iPad、移动端。此外,屏幕尺寸改变时,不同刷新即时就能看到新的展示效果。

不过缺点也很明显:

  • 代码量比较大,维护不方便
  • 为了兼顾大屏幕或高清设备,会造成其他设备资源浪费,特别是加载图片资源
  • 为了兼顾移动端和PC端各自响应式的展示效果,难免会损失各自特有的交互方式

总体而言,算是比较老的解决方案,增加的工作量和实现的效果一比,显得性价比不高,不太推荐。

flex弹性布局

使用flex布局的主要思想,就是定高不定宽,不管屏幕有多宽有多大都自适应,跟PC上的流式布局是一个思路。这样做确实可以适配一些以图文为主的页面,但不适用于功能复杂的系统,局限性比较大,不太推荐。

rem缩放大法

好了,传统的方案看起来都不行,那就换个思路,我就按照750px来写,最后再缩放一下不就好了。作为一个相对单位,rem就被前端同学选择作为书写的基本单位,配合viewport缩放。

方案一:rem 简单版

简单来说,就是根据设计稿都是750px的基础,计算根节点font-size的大小,然后设置meta标签的缩放比为1,使用rem来书写样式。实现起来比较简单,不过在某些尺寸的屏幕上缩放后显得有些糊,随后便有了方案二。

方案二:rem 高清版

所谓的高清方案就是根据设备屏幕的DPR(设备像素比,又称DPPX,比如dpr=2时,表示1个CSS像素由4个物理像素点组成) 动态设置 html 的font-size, 同时根据设备DPR调整页面的缩放值,进而达到高清效果。同样使用rem作为基础单位来书写样式。

这么做的优势:

  • 根据设备屏幕的DPR,自动设置最合适的高清缩放。
  • 保证了不同设备下视觉体验的一致性。(老方案是屏幕越大,看的越多)
  • 有效解决移动端真实1px问题(这里的1px 是设备屏幕上的物理像素)

那么缺点呢:

  • 简单的缩放处理,使得页面基本无法兼容PC端、iPad端
  • rem 作为相对单位,最后渲染出来的元素会有像素差(可能)
  • 使用富文本时,由于外部的viewport被缩放了,富文本内部使用px作为单位的部分就会显示异常
  • rem 在移动端存在部分显示Bug,例如:使用rem设置height和line-height相同时文字却没有垂直居中?

无法垂直居中

虽说有些不足,不过使用rem的方案还是比较“完美”的解决了移动端适配的问题。大家虽然手持不同的尺寸手机,但是看到的都是同一个样子,多一点不多,少一点不少,十分“公平”。好了,这下产品、设计、交互、前端都轻松了,只需出一个750px的设计稿,前端照着写就行了,皆大欢喜。

不过归根结底,rem其实也是根据宽高等比缩放的思想来实现适配的,从这个角度来说,rem只能算做vw、vh 的备胎,因为它俩天生就是干这个的。

至于为什么vw、vh 没火起来呢,主要还是由于这俩被浏览器支持得太晚导致的。当时移动端的需求已经十分旺盛了,而安卓端很多浏览器都还不支持,等你支持了黄花菜都凉了,这才让rem成功上了位,不然谁更火还真不好说。

rem 的支持情况:

rem

vw 的支持情况:

vw

不过现在安卓端最新浏览器对vw、vh 已经没有了兼容性问题,可以大胆的使用。

px的现状

这么看下来,px作为旧时代的产物,是不是可以退场了呢?

恰恰相反,很多知名的开源项目的源码都是用px 写的,比如Ant-design:

Ant-design

看到这个,大家可能就有了疑问,rem、em这些不都是很好用的嘛,怎么还是要用px来写呢?

rem虽然是一柄利器,但是也有它的局限性,跟其他工具搭配起来使用才能发挥出最大的效果。为了更好的兼容性,一般的做法是源码使用px来书写,再使用PostCss 工具(postcss-pxtorem、postcss-pxtovw之类),在编译过程中将px转换为rem或者vw。这样做的好处是不需要关心根元素的字体大小,又可以配合项目需要转换成想要的单位,在pc端使用也完全没问题。

所以,在不同的情况下使用的单位也是不同的,需要结合自己的需求选择合适的单位,切勿盲从跟风。

 
comments powered by Disqus