前端基础知识概述 -- 移动端开发的屏幕、图像、字体与布局的兼容适配

本文是内部的一次分享沉淀,偏向基础可是涉及了一些有意思的细节,文笔有限,才疏学浅,文中如有不正之处,万望告知。css

前端的一大工做内容就是去兼容页面在不一样内核的浏览器,不一样的设备,不一样的分辨率下的行为,使页面的能正常工做在各类各样的宿主环境当中。html

而本文的主题 -- 移动端开发的兼容适配与性能优化,就是但愿能从一些常见的移动端开发问题出发,厘清 Web 移动端开发的前先后后,一些技术的发展过程,一些问题的优化手段以及给出一些常见的兼容性问题的解决方案。前端

 

什么是响应式设计

首先先聊聊响应式设计,这个与移动端开发有着密切的联系。node

响应式设计便是 RWD,Responsive Web Design。git

这里百度或者谷歌一下会有各类各样的答案。这里一段摘自知乎上我以为很棒的一个答案:什么是响应式布局设计?github

根据维基百科及其参考文献,理论上,响应式界面可以适应不一样的设备。描述响应式界面最著名的一句话就是“Content is like water”,翻译成中文即是“若是将屏幕看做容器,那么内容就像水同样”。web

 

为何要设计响应式界面

为何要费神地尝试统一全部设备呢?chrome

  • 即使是PC或Mac用户,有查显示只有一半的人会将浏览器全屏显示,而剩下的通常人使用多大的浏览器,很难预知;
  • 台式机、投影、电视、笔记本、手机、平板、手表、VR……智能设备正在不断增长,“主流设备”的概念正在消失;
  • 屏幕分辨率正飞速发展,同一张图片在不一样设备上看起来,大小可能天差地别;
  • 鼠标、触屏、笔、摄像头手势……不可预期的操控方式正在不断出现。

 

响应式界面的四个层次

  • 同一页面在不一样大小和比例上看起来都应该是温馨的;
  • 同一页面在不一样分辨率上看起来都应该是合理;
  • 同一页面在不一样操做方式(如鼠标和触屏)下,体验应该是统一的;
  • 同一页面在不一样类型的设备(手机、平板、电脑)上,交互方式应该是符合习惯的。

 

响应式界面的基本规则

  • 可伸缩的内容区块:内容区块的在必定程度上可以自动调整,以确保填满整个页面
    npm

  • 可自由排布的内容区块:当页面尺寸变更较大时,可以减小/增长排布的列数
    浏览器

  • 适应页面尺寸的边距:到页面尺寸发生更大变化时,区块的边距也应该变化

  • 可以适应比例变化的图片:对于常见的宽度调整,图片在隐去两侧部分时,依旧保持美观可用

  • 可以自动隐藏/部分显示的内容:如在电脑上显示的的大段描述文本,在手机上就只能少许显示或所有隐藏

  • 能自动折叠的导航和菜单:展开仍是收起,应该根据页面尺寸来判断

  • 放弃使用像素做为尺寸单位:用dp(对于前端来讲,这里多是rem)尺寸等方法来确保页面在分辨率相差很大的设备上,看起来也能保持一致。同时也要求提供的图片应该比预想的更大,才能适应高分辨率的屏幕

上面一段我以为已经涵盖了响应式设计的绝大部分,简单总结起来,能够归纳为:

  1. 媒体查询,边界断点的规则设定(Media queries && break point)
  2. 内容的可伸缩性效果(Flexibel visuals)
  3. 流式网格布局(Fluid grids)
  4. 主要内容呈现及图片的高质量(Main content and high quality)

 

响应式 vs. 自适应

响应式设计是 Responsive Web Design(RWD),自适应设计是 Adaptive Web Design(AWD)。常常有人会将二者混为一谈,或者其实根本也区分不了所谓的响应式与自适应。

其实在我写这篇文章的时候,我也没法很好的去区分二者。

RWD 和 AWD 二者都是为了适配各类不一样的移动设备,致力于提高用户体验所产生的的技术。核心思想是用技术来使网页适应从小到大(如今到超大)的不一样分辨率的屏幕。一般认为,RWD 是 AWD 的子集。

RWD:Ethan Marcote 的文章是你们认为 RWD 的起源。他提出的 RWD 方案是经过 HTML 和 CSS 的媒体查询技术,配合流体布局实现。RWD 倾向于只改变元素的外观布局,而不大幅度改变内容。Jeffrey Zeldman 总结说,咱们就把 RWD 定义为一切能用来为各类分辨率和设备性能优化视觉体验的技术。

AWD:Adaptive Design 是 Aaron Gustafson 的书的标题。他认为 AWD 在包括 RWD 的 CSS 媒体查询技术之外,也要用 Javascript 来操做 HTML 来更适应移动设备的能力。AWD 有可能会针对移动端用户减去内容,减去功能。AWD 能够在服务器端就进行优化,把优化过的内容送到终端上。

一图胜千言。

image

从定义上而言,RWD 是一套代码,适用于全部屏幕。而 AWD 则是多端多套代码。本文不会过多去纠结响应式与自适应区别,我以为这二者的本质都是致力于适配不一样设备,更好地提高用户体验。

Quora - Responsive Design vs. Adaptive Design?
zhihu -- Responsive design 和 Adaptive design 的区别

 

渐进加强 vs. 优雅降级

  • 渐进加强(progressive enhancement):针对低版本浏览器进行构建页面,保证最基本的功能,而后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

  • 优雅降级(graceful degradation):一开始就构建完整的功能,而后再针对低版本浏览器进行兼容。

区别:优雅降级是从复杂的现状开始,并试图减小用户体验的供给,而渐进加强则是从一个很是基础的,可以起做用的版本开始,并不断扩充,以适应将来环境的须要。降级(功能衰减)意味着往回看;而渐进加强则意味着朝前看,同时保证其根基处于安全地带。 

渐进加强/优雅降级一般是 AWD 会牵扯到的另外一个技术术语。本质上而言便是随着屏幕的大小的改变,功能会一点一点加强。

也一般会用在一些高级 CSS3 属性上,咱们对一些 CSS 属性进行特性检测,甚至不进行特性检测直接使用。后果是在支持它的网页上该属性正常展现,而不支持它的网页该属性不生效,但也不影响用户的基本使用。

典型的例子是 CSS3 逐渐被大众承认并被使用,PC端页面开始由 IE678 向兼容性更好的IE9+,chrome,firefox浏览器转变的时期。咱们能够对页面元素直接使用阴影,圆角等属性。对于不支持它的低版本 IE 而言,没有什么损失,而对于支持它的高级浏览器而言,带给了用户更好的交互视觉体验,这就是渐进加强。

 

移动端屏幕适配方案

下面会针对一些具体的案例,展开讲讲。第一个是高保真还原设计稿,也就是如何适配移动端繁杂的屏幕大小。

一般而言,设计师只会给出单一分辨率下的设计稿,而咱们要作的,就是以这个设计稿为基准,去适配全部不一样大小的移动端设备。

在此以前,有一些基础概念须要理解。

一些概念性的东西,大部分人很难一次性记住,或者记了又忘,我以为记忆这个东西比较看技巧,好比关联法,想象法,把这些生硬的概念与一些符合咱们常识的知识关联在一块儿记忆,每每可以事半功倍。

设备独立像素

以 iPhone6/7/8为例,这里咱们打开 Chrome 开发者工具:

image

这里的 375 * 667 表示的是什么呢,表示的是设备独立像素(DIP),也能够理解为 CSS 像素,也称为逻辑像素:

设备独立像素 = CSS 像素 = 逻辑像素

如何记忆呢?这里使用 CSS 像素来记忆,也就是说。咱们设定一个宽度为 375px 的 div,恰好能够充满这个设备的一行,配合高度 667px ,则 div 的大小恰好能够充满整个屏幕。

 

物理像素

OK,那么,什么又是物理像素呢。咱们到电商网站购买手机,都会看一看手机的参数,以 JD 上的 iPhone7 为例:

image

能够看到,iPhone7 的分辨率是 1334 x 750,这里描述的就是屏幕实际的物理像素。

物理像素,又称为设备像素。显示屏是由一个个物理像素点组成的,1334 x 750 表示手机分别在垂直和水平上所具备的像素点数。经过控制每一个像素点的颜色,就可使屏幕显示出不一样的图像,屏幕从工厂出来那天起,它上面的物理像素点就固定不变了,单位为pt。

设备像素 = 物理像素

 

DPR(Device Pixel Ratio) 设备像素比

OK,有了上面两个概念,就能够瓜熟蒂落引出下一个概念。DPR(Device Pixel Ratio) 设备像素比,这个与咱们一般说的视网膜屏(多倍屏,Retina屏)有关。

设备像素比描述的是未缩放状态下,物理像素和设备独立像素的初始比例关系。

简单的计算公式:

DPR = 物理像素 / 设备独立像素

咱们套用一下上面 iPhone7 的数据(取设备的物理像素宽度与设备独立像素宽度进行计算):

iPhone7’s DPR = iPhone7’s 物理像素宽度 / iPhone7's 设备独立像素宽度 = 2

750 / 375 = 2
或者是 1334 / 667 = 2

能够获得 iPhone7 的 dpr 为 2。也就是咱们常说的视网膜屏幕。

视网膜(Retina)屏幕是苹果公司"发明"的一个营销术语。 苹果公司将 dpr > 1 的屏幕称为视网膜屏幕。

image

在视网膜屏幕中,以 dpr = 2 为例,把 4(2x2) 个像素当 1 个像素使用,这样让屏幕看起来更精致,可是元素的大小自己却不会改变:

image

OK,咱们再来看看 iPhone XS Max:

屏幕快照 2019-07-08 下午8 02 00

它的物理像素如上图是 2688 x 1242

image

它的 CSS 像素是 896 x 414,很容易得出 iPhone XS Max 的 dpr 为 3。

上面三个概念(CSS像素、设备独立像素、DPR)是我以为比较重要的,还有一些其余比较重要的概念 PPI、DPI 不影响后续的内容,能够自行去加深理解。

OK,到这里咱们就完成了一个小的里程碑。咱们一般说的H5手机适配也就是指的这两个维度:

  1. 适配不一样屏幕大小,也就是适配不一样屏幕下的 CSS 像素
  2. 适配不一样像素密度,也就是适配不一样屏幕下 dpr 不一致致使的一些问题

 

适配不一样屏幕大小

适配不一样屏幕大小,也就是适配不一样屏幕下的 CSS 像素。最先移动端屏幕 CSS 像素适配方案是CSS媒体查询。可是没法作到高保真接近 100% 的还原。

适配不一样屏幕大小其实只须要遵循一条原则,确保页面元素大小的与屏幕大小保持必定比例。也就是:按比例还原设计稿

屏幕快照 2019-07-29 下午7 23 05

假设咱们如今拿到标注为 375*667 的大小的设计稿,其中一个元素的标注以下:

屏幕快照 2019-07-29 下午7 28 13

屏幕快照 2019-07-29 下午7 30 24

以页面宽度为基准的话,那么,

  • 元素的宽度为:209/375 = 55.73%
  • 元素的高度为:80/375 = 21.33%
  • 元素的上左右边距依次计算...

这样,不管屏幕的 CSS 像素宽度是 320px 仍是 375px 仍是 414px,按照等量百分比还原出来的界面老是正确的。

然而,理想很丰满,现实很骨感。实现上述百分比方案的核心须要一个全局通用的基准单位,让全部百分比展现以它为基准,可是在 CSS 中,根据CSS Values and Units Module Level 4的定义:

百分比值总要相对于另外一个量,好比长度。每一个容许使用百分比值的属性,同时也要定义百分比值参照的那个量。这个量能够是相同元素的另外一个属性的值,也能够是祖先元素的某个属性的值,甚至是格式化上下文的一个度量(好比包含块的宽度)。

具体来讲:

  • 宽度(width)、间距(maring/padding)支持百分比值,但默认的相对参考值是包含块的宽度;

  • 高度(height)百分比的大小是相对其父级元素高的大小;

  • 边框(border)不支持百分值;

  • 边框圆角半径(border-radius)支持百分比值,但水平方向相对参考值是盒子的宽度,垂直方向相对参考值是盒子的高度;

  • 文本大小(font-size)支持百分比值,但相对参考值是父元素的font-size的值;

  • 盒阴影(box-shadow)和文本阴影(text-shadow)不支持百分比值;

首先,支持百分比单位的度量属性有其各自的参照基准,其次并不是全部度量属性都支持百分比单位。因此咱们须要另辟蹊径。

 

rem 适配方案

在 vw 方案出来以前,最被大众接受的就是使用 rem 进行适配的方案,由于 rem 知足上面说的,能够是一个全局性的基准单位。

rem(font size of the root element),在 CSS Values and Units Module Level 3中的定义就是, 根据网页的根元素来设置字体大小,和 em(font size of the element)的区别是,em 是根据其父元素的字体大小来设置,而 rem 是根据网页的跟元素(html)来设置字体大小。

flexible

基于此,淘宝早年推行的一套以 rem 为基准的适配方案:lib-flexible。其核心作法在于:

  • 根据设备的 dpr 动态改写 <meta> 标签,设置 viewport 的缩放
  • 给 <html> 元素添加 data-dpr 属性,而且动态改写 data-dpr 的值
  • 根据 document.documentElement.clientWidth 动态修改 <html> 的 font-size ,页面其余元素使用 rem 做为长度单位进行布局,从而实现页面的等比缩放

关于头两点,其实如今的 lib-flexible 库已经不这样作了,再也不去缩放 Viewport,字体大小的设定也直接使用了 rem

hotcss

hotcss 不是一个库,也不是一个框架。它是一个移动端布局开发解决方案。使用 hotcss 可让移动端布局开发更容易。本质的思想与 flexible 彻底一致。

 

对于 rem 方案的一些总结

使用 flexible/hotcss 做为屏幕宽度适配解决方案,是存在一些问题的:

  1. 动态修改 Viewport 存在必定的风险的,譬如经过 Viewport 改变了页面的缩放以后,获取到的 innerWidth/innerHeight 也会随之发生变化,若是业务逻辑有获取此类高宽进行其余计算的,可能会致使意想不到的错误;

到今天,其实存在不少在 flexible 基础上演化而来的各类 rem 解决方案,有的不会对 Viewport 进行缩放处理,自行处理 1px 边框问题。

  1. flexible/hotcss 都并不是纯 CSS 方案,须要引入必定的 Javascript 代码
  2. rem 的设计初衷并不是是用于解决此类问题,用 rem 进行页面的宽度适配多少有一种 hack 的感受
  3. 存在必定的兼容性问题,对于安卓 4.4 如下版本系统不支持 viewport 缩放(固然,flexible 处理 Android 系列时,始终认为其 dpr 为 1,没有进行 viewport 缩放)

 

vw 适配方案

严格来讲,使用 rem 进行页面适配实际上是一种 hack 手段,rem 单位的初衷自己并非用来进行移动端页面宽度适配的。

到了今天,有了一种更好的替代方案,使用 vw 进行适配 。

百分比适配方案的核心须要一个全局通用的基准单位,rem 是不错,可是须要借助 Javascript 进行动态修改根元素的 font-size,而 vw/vh(vmax/vmin) 的出现则很好弥补 rem 须要 JS 辅助的缺点。

根据 CSS Values and Units Module Level 4:vw等于初始包含块(html元素)宽度的1%,也就是

  • 1vw 等于 window.innerWidth 的数值的 1%
  • 1vh 等于window.innerHeight 的数值的 1%

再以上面设计稿图的元素为例,那么,

  • 元素的宽度为:209/375 = 55.73% = 55.73vw
  • 元素的高度为:80/375 = 21.33% = 21.33vw
  • 元素的上左右边距依次计算...

根据相关的测试,可使用 vw 进行长度单位的有:

  • 容器大小适配,可使用 vw
  • 文本大小的适配,可使用 vw
  • 大于 1px 的边框、圆角、阴影均可以使用 vw
  • 内距和外距,可使用 vw

简单的一个页面,看看效果,彻底是等比例缩放的效果:

vw

CodePen Demo(移动端打开):使用 vw 进行页面适配

 

自动转换插件

当咱们使用 rem 做为长度单位的时,一般会有借助 Sass/Less 实现一个转换函数,像是这样:

// 假设设计稿的宽度是 375px,假设取设计稿宽度下 1rem = 100px
$baseFontSize: 100;

@function px2rem($px) {
	@return $px / $baseFontSize * 1rem;
}

同理,在 vw 方案下,咱们只须要去改写这个方法:

// 假设设计稿的宽度是 375px
@function px2rem($px) {
	@return $px / 375 * 100vw;
} 

固然,咱们还能够借助一些插件包去实现这个自动转换,提升效率,譬如 postcss-px-to-viewport

 

vw polyfill

vw 如今毕竟仍是存在兼容问题的,看看兼容性:

image

其实已经覆盖了绝大部分设备,那么若是业务使用了且又真的出现了兼容问题,应该怎么处理呢?有两种方式能够进行降级处理:

  • CSS Houdini:经过CSS Houdini针对vw作处理,调用CSS Typed OM Level1 提供的 CSSUnitValue API。
  • CSS Polyfill:经过相应的Polyfill作相应的处理,目前针对于 vw 单位的 Polyfill 主要有:vminpoly、Viewport Units Buggyfill、vunits.js和 Modernizr

 

对于 vw 方案的一些总结

vw 确实看上去很不错,可是也是存在它的一些问题:

  1. 也没能很好的解决 1px 边框在高清屏下的显示问题,须要自行处理
  2. 因为 vw 方案是彻底的等比缩放,在彻底等比还原设计稿的同时带来的一个问题是没法很好的限定一个最大最小宽度值,因为 rem 方案是借助 Javascript 的,因此这一点 rem 比 vw 会更加的灵活

固然,两个方案现阶段其实均可以使用甚至一块儿搭配使用,更多详情能够读读:

 

1px线

上面说到使用 vw 适配屏幕大小方案,其中有一个缺点就是在 Retina 屏下,没法很好的展现真正的 1px 物理像素线条。

设计师想要的 retina 下 border: 1px,实际上是 1 物理像素宽,而不是 1 CSS 像素宽度,对于 CSS 而言:

  • 在 dpr = 1 时,此时 1 物理像素等于 1 CSS 像素宽度;
  • 在 dpr = 2 时,此时 1 物理像素等于 0.5 CSS 宽度像素,能够认为 border-width: 1px 这里的 1px 实际上是 1 CSS像素宽度,等于 2 像素物理宽度,设计师其实想要的是 border-width: 0.5px;
  • 在 dpr = 3 时,此时 1 物理像素等于 0.33 CSS 宽度像素,设计师其实想要的是 border: 0.333px

然而,并非全部手机浏览器都能识别 border-width: 0.5px,在 iOS7 如下,Android 等其余系统里,小于 1px 的单位会被当成为 0px 处理,那么如何实现这 0.5px、0.33px 呢?

这里介绍几种方法:

  • 渐变实现
  • 使用缩放实现
  • 使用图片实现(base64)
  • 使用SVG实现(嵌入 background url)

Retina 屏幕下 1px 线的实现

 

图片适配及优化

图像一般占据了网页上下载资源绝的大部分。优化图像一般能够最大限度地减小从网站下载的字节数以及提升网站性能。

一般能够,有一些通用的优化手段:

  1. 消除多余的图像资源
  2. 尽量利用 CSS3\SVG 矢量图像替代某些光栅图像
  3. 谨慎使用字体图标,使用网页字体取代在图像中进行文本编码
  4. 选择正确的图片格式
  5. 为不一样 DPR 屏幕提供最适合的图片尺寸

本文重点关注如何在不一样的 dpr 屏幕下,让图片看起来都不失真。

首先就是上述的第二点,尽量利用 CSS3\SVG 矢量图像替代某些光栅图像。某些简单的几何图标,能够用 CSS3 快速实现的图形,都应该尽可能避免使用光栅图像。这样可以保证它们在任何尺寸下都不会失真。

其次,实在到了必须使用光栅图像的地步,也是有许多方式能保证图像在各类场景下都不失真。

 

无脑多倍图

在移动端假设咱们须要一张 CSS 像素为 300 x 200 的图像,考虑到如今已经有了 dpr = 3 的设备,那么要保证图片在 dpr = 3 的设备下也正常高清展现,咱们最大可能须要一张 900 x 600 的原图。

这样,无论设备的 dpr 是否为 3,咱们统一都使用 3 倍图。这样即便在 dpr = 1,dpr = 2 的设备上,也能很是好的展现图片。

固然这样并不可取,会形成大量带宽的浪费。现代浏览器,提供了更好的方式,让咱们可以根据设备 dpr 的不一样,提供不一样尺寸的图片。

  

srcset 配合 1x 2x 像素密度描述符

简单来讲,srcset 能够根据不一样的 dpr 拉取对应尺寸的图片:

<div class='illustration'>
  <img src='illustration-small.png'
       srcset='images/illustration-small.png 1x,
               images/illustration-big.png 2x'
       style='max-width: 500px'/>
</div>

上面 srcset 里的 1x,2x 表示 像素密度描述符,表示

  • 当屏幕的 dpr = 1 时,使用 images/illustration-small.png 这张图
  • 当屏幕的 dpr = 2 时,使用 images/illustration-big.png 这张图

 

srcset 属性配合 sizes 属性 w 宽度描述符

上面 1x,2x 的写法比较容易接受易于理解。

除此以外,srcset属性还有一个 w 宽度描述符,配合 sizes 属性一块儿使用,能够覆盖更多的面。

如下面这段代码为例子:

<img 
        sizes = “(min-width: 600px) 600px, 300px" 
        src = "photo.png" 
        srcset = “photo@1x.png 300w,
                       photo@2x.png 600w,
                       photo@3x.png 1200w,
>

解析一下:

sizes = “(min-width: 600px) 600px, 300px" 的意思是,若是屏幕当前的 CSS 像素宽度大于或者等于 600px,则图片的 CSS 宽度为 600px,反之,则图片的 CSS 宽度为 300px。

也就是 sizes 属性声明了在不一样宽度下图片的 CSS 宽度表现。这里能够理解为,大屏幕下图片宽度为 600px,小屏幕下图片宽度为 300px。(具体的媒体查询代码由 CSS 实现)

这里的 sizes 属性只是声明了在不一样宽度下图片的 CSS 宽度表现,而具体使图片在大于600px的屏幕上展现为600px宽度的代码须要另外由 CSS 或者 JS 实现,有点绕。

srcset = “photo@1x.png 300w, photo@2x.png 600w, photo@3x.png 1200w 里面的 300w,600w,900w 叫宽度描述符。怎么肯定当前场景会选取哪张图片呢?

1. 当前屏幕 dpr = 2 ,CSS 宽度为 375px。

当前屏幕 CSS 宽度为 375px,则图片 CSS 宽度为 300px。分别用上述 3 个宽度描述符的数值除以 300。

  1. 300 / 300 = 1
  2. 600 / 300 = 2
  3. 1200 / 300 = 4

上面计算获得的 一、 二、 4 便是算出的有效的像素密度,换算成和 x 描述符等价的值 。这里 600w 算出的 2 即知足 dpr = 2 的状况,选择此张图。 

2. 当前屏幕 dpr = 3 ,CSS 宽度为 414px。

当前屏幕 CSS 宽度为 414px,则图片 CSS 宽度仍为 300px。再计算一次:

  1. 300 / 300 = 1
  2. 600 / 300 = 2
  3. 1200 / 300 = 4

由于 dpr = 3,2 已经不知足了,则此时会选择 1200w 这张图。

3. 当前屏幕 dpr = 1 ,CSS 宽度为 1920px。

当前屏幕 CSS 宽度为 1920px,则图片 CSS 宽度变为了 600px。再计算一次:

  1. 300 / 600 = .5
  2. 600 / 600 = 1
  3. 1200 / 600 = 2

由于 dpr = 1,因此此时会选择 600w 对应的图片。

具体的能够试下这个 Demo:CodePen Demo -- srcset属性配合w宽度描述符配合sizes属性

此方案的意义在于考虑到了响应性布局的复杂性与屏幕的多样性,利用上述规则,能够一次适配 PC 端大屏幕和移动端高清屏,一箭多雕。

了解更多细节,推荐看看:

 

字体适配方案

字体大小

字体是不少前端开发同窗容易忽略的一个点,可是其中也是有不少小知识点。

首先要知道,浏览器有最小字体限制:

  • PC上最小 font-size=12px
  • 手机上最小 font-size=8px

若是小于最小字体,那么字体默认就是最小字体。

其次,不少早期的文章规范都建议不要使用奇数级单位来定义字体大小(如 13px,15px...),容易在一些低端设备上形成字体模糊,出现锯齿。

 

字体的选择展现

在字体适配上面,咱们须要从性能和展现效果两个维度去考虑。

完整的一个字体资源实在太大了,因此咱们应该尽量的使用用户设备上已有的字体,而不是额外去下载字体资源,从而使加载时间明显加快。

而从展现效果层面来讲,使用系统字体能更好的与当前操做系统使用的相匹配,获得最佳的展现效果。因此咱们在字体使用方面,有一个应该尽可能去遵循的原则,也是如今大部分网站在字体适配上使用的策略:

使用各个支持平台上的默认系统字体。

  

兼顾各个操做系统

常见的操做系统有 Windows、Windows Phone、Mac OS X、iPhone、Android Phone、Linux。固然对于普通用户而言,无须关注 Linux 系统。

下面就以 CSS-Trick 网站最新的 font-family 为例,看看他们是如何在字体选择上作到适配各个操做系统的

{
  font-family: 
    system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,
    Helvetica,Arial,
    sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;
}

 

font-family 关键字

对于 CSS 中的 font-family 而言,它有两类取值。

  1. 一类是相似这样的具体的字体族名定义:font-family: Arial 这里定义了一个具体的字体样式,字体族名为 Arial;

  2. 一类是通用字体族名,它是一种备选机制,用于在指定的字体不可用时给出较好的字体,相似这样:font-family: sans-serif 。

其中,sans-serif 表无衬线字体族,例如, "Open Sans", "Arial" "微软雅黑" 等等。

关于通用字体族名,在 CSS Fonts Module Level 3 -- Basic Font Properties 中,定义了 5 个,也就是咱们熟知的几个通用字体族名:

  1. serif 衬线字体族
  2. sans-serif 非衬线字体族
  3. monospace 等宽字体,即字体中每一个字宽度相同
  4. cursive 草书字体
  5. fantasy 主要是那些具备特殊艺术效果的字体

 

新增通用字体族关键字

而在 CSS Fonts Module Level 4 -- Generic font families 中,新增了几个关键字:

  • system-ui 系统默认字体
  • emoji 用于兼容 emoji 表情符号字符
  • math 适用于数学表达式
  • fangsong 此字体系列用于中文的(仿宋)字体。

咱们看看用的最多的 system-ui

 

system-ui

简单而言,font-family: system-ui 的目的就是在不一样的操做系统的 Web 页面下,自动选择本操做系统下的默认系统字体。

默认使用特定操做系统的系统字体能够提升性能,由于浏览器或者 webview 没必要去下载任何字体文件,而是使用已有的字体文件。 font-family: system-ui 字体设置的优点之处在于它与当前操做系统使用的字体相匹配,对于文本内容而言,它能够获得最恰当的展现。

 

San Francisco Fonts

OK,简单了解了 system-ui 字体族。可是像 -apple-systemBlinkMacSystemFont 没有在最新的标准里出现。它们又表明什么意思呢?

在此以前,先了解下 San Francisco Fonts 。

San Francisco Fonts 又叫旧金山字体,是一款西文字体。随着 iOS 9 更新面世,在 WatchOS 中随 Apple Watch 一块儿悄然发售,而且还将在 Apple TV 上的新 tvOS 中使用。

San Francisco Fonts 在 iOS 系统上用于替代升级另一款西文字体 Helvetica Neue。Apple 作了一些重要的改变,使其成为平台上更好的, 甚至是完美的西文字体。

image

 

-apple-system/BlinkMacSystemFont

话说回来。正如每一个前端开发人员都知道的那样,将一个功能归入规范是一回事,将其归入浏览器又是另外一回事。

幸运的是,system-ui 的普及很快。 Chrome 和 Safari 均可以在各类平台上彻底支持它。只有 Mozilla 和 Windows 相对落后。

看看 system-ui 的兼容性,Can i Use -- system-ui(图片截取日 2019-08-13):

image

仔细看上图的最后两行:

  • Supported as the -apple-system value (only on macOS and iOS)
  • Supported as the BlinkMacSystemFont value (only on macOS)

考虑到不一样平台及向后兼容,在 macOS 和 iOS 上,咱们须要使用 -apple-system 及 BlinkMacSystemFont 来兼容适配 system-ui 标准。

 

Segoe UI

Segoe UI 是 Windows 从 Vista 开始的默认西文字体族,只有西文,不支持汉字,属于无衬线体。

它也表示一个系列而不是某一款单一字体。使用 font-family: Segoe UI 能够在 Windows 平台及 Windows Phone 上选取最佳的西文字体展现。

 

Roboto

Roboto 是为 Android 操做系统设计的一个无衬线字体家族。Google 描述该字体为“现代的、但平易近人”和“有感情”的。

这个字体家族包含Thin、Light、Regular、Medium、Bold、Black六种粗细及相配的斜体。

 

总结一下

到此,咱们能够总结一下了。以 CSS-Tricks 网站的 font-family 定义为例子:

{
  font-family: 
    system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,
    Helvetica,Arial,
    sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;
}
  1. system-ui,使用各个支持平台上的默认系统字体
  2. -apple-system, 在一些稍低版本 Mac OS X 和 iOS 上,它针对旧版上的 Neue Helvetica 和 Lucida Grande 字体,升级使用更为合适的 San Francisco Fonts
  3. BlinkMacSystemFont,针对一些 Mac OS X 上的 Chrome 浏览器,使用系统默认字体
  4. segoe ui,在 Windows 及 Windows Phone 上选取系统默认字体
  5. Roboto,面向 Android 和一些新版的的 Chrome OS
  6. Helvetica,Arial,在针对不一样操做系统不一样平台设定采用默认系统字体后,针对一些低版本浏览器的降级方案
  7. sans-serif,兜底方案,保证字体风格统一,至少也得是无衬线字体

上述 5 个字体族定义,优先级由高到底,能够看到,它们 5 个都并不是某个特定字体,基本的核心思想都是选择对应平台上的默认系统字体。

涵盖了 iOS、MAC OS X、Android、Windows、Windows Phone 基本全部用户常用的主流操做系统。

使用系统默认字体的主要缘由是性能。字体一般是网站上加载的最大/最重的资源之一。若是咱们可使用用户机器上已有的字体,咱们就彻底不须要再去获取字体资源,从而使加载时间明显加快。

而且系统字体的优势在于它与当前操做系统使用的相匹配,所以它的文本展现必然也是一个让人温馨展现效果。

固然,上述 font-family 的定义不必定是最佳的。譬如天猫移动端在 font-family 最前面添加了 "PingFang SC",miui,..一定也有他们的业务上的考虑。可是一些 fallback 方案向后兼容的思想都是一致的,值得参考学习。

更多的关于字体方面的细节知识,能够看看这几篇文章:

 

前端布局的兼容适配

前端工程师的一大工做内容就是页面布局。不管在PC端仍是移动端,页面布局的兼容适配都是重中之重。在整个前端发展的历程中,布局的方法也在不断的推陈出新。

布局发展历程

简单来讲,前端的布局发展历程经历了下面几个过程:

表格布局 --> 定位布局 --> 浮动布局 --> flexbox布局 --> gridbox布局

每一种布局在特定时期都发挥了重要的做用,而每一种新的布局方式的出现,每每都是由于现有的布局方式已经在该时期已经没法很好的知足开发者的需求,没法知足愈来愈潮流的页面布局的方式。

以 Flexbox 的出现为例子,在 Flexbox 被你们广为接受使用以前。咱们一直在使用定位+浮动的布局方式。像下面这个布局:

flexbox

容器宽度不定,内部三个元素,均分排列且占满整个空间,而且垂直居中。若是使用定位+浮动的布局方式,你没法很快想到最佳的解决方式。三个元素并排那么必然须要浮动或者绝对定位,容器宽度不定且中间元素始终居中,须要顾虑的方面就不少了。也许使用 text-align: justufy 能够 hack 实现,等等等等。

然而,使用 flexbox 布局的话,只须要: 

.container {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

flexbox 的出现,一次性解决了流动布局,弹性布局,排列方式等多个问题。而且它是简洁的,可控的。

再来看一个例子,水平垂直居中一个元素。使用 flexbox 也许是最便捷的:

.container {
    display: flex;
}

.item {
    margin: auto;
}

最便捷的垂直居中方式

 

CSS Grid Layout

OK,flexbox 已经足够优秀了,为何 gird 网格布局的出现又是为何?它解决了什么 flex 布局没法很好解决的问题?

看看下面这张图:

css grid layout

flexbox 是一维布局,他只能在一条直线上放置你的内容区块;而grid是一个二维布局。它除了能够灵活的控制水平方向以外,还能轻易的控制垂直方向的布局模式。对于上图那样的九宫格布局,它就能够垂手可得的完成。

一图以蔽之,flexbox:

flexbox

gridbox:

gridbox

图片截取自陈慧晶老师在 2019 第五届 CSS 大会上的分享 -- 新时代CSS布局

在现阶段,移动端布局应当更多使用 flexbox 去完成(相对那些还在使用 float 布局的),而考虑到将来页面布局的推陈出新。对于 Grid 布局咱们应当像前几年对待 flexbox 同样,重视起来,随着兼容性的普及,Grid 布局也会慢慢成为主流。

 

最后

好了,本文到此结束,但愿对你有帮助 :)

更多精彩技术文章汇总在个人 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

若是还有什么疑问或者建议,能够多多交流,原创文章,文笔有限,才疏学浅,文中如有不正之处,万望告知。

相关文章
相关标签/搜索