一、 font-face基本用法

font-face的基本用法想必大家都是知道的,基本上就是类似这样:@font-face {

font-family: Lato;

src: url('font-lato/lato-regular-webfont.woff2') format('woff2'),

url('font-lato/lato-regular-webfont.woff') format('woff'),

url(font-lato/lato-regular-webfont.ttf) format("opentype");

}

p { font-family: Lato, serif; }

复制代码

这样就可以使我们的网页用上自定义字体了。 除了font-family 和 src属性之外,还拥有font-style以及font-weight属性。 src可以指定多种字体,会按顺序依次适用,比如上面的示例中会先加载woff2字体,如果失败再加载woff字体,否则加载opentype字体。 src所支持的字体可以有以下类型:

src参数带不带引号都可以,参数的格式不同含义也不尽相同,比如下面:src: url(fonts/simple.woff); /* 加载simple.woff,地址相对于样式表的地址 */

src: url(/fonts/simple.woff); /* 加载simple.woff,地址是网站的绝对地址 */

src: url(fonts/coll.otc#foo); /* 从coll.otc字符集中加载foo字体 */

src: url(fonts/coll.woff2#foo); /* 从coll.woff2字符集中加载foo字体 */

src: url(fonts.svg#simple); /* 加载id 为'simple'的SVG字体 */

复制代码

src中加载的字体地址受跨域的约束,如果想跨域加载字体,需要设置CORS。

这就是font-face的最基础的用法。 接下来我们会进一步分析font-face的用法,并尽可能的找出优化策略。

二、 什么时候会下载字体?

上面讲了字体的基本知识,那你有没有想过,字体是在什么时候下载的呢?当我们仅仅在CSS中定义如下样式的时候, 页面加载,字体会自动下载吗?@font-face {

font-family: Lato;

src: url('font-lato/lato-regular-webfont.woff2') format('woff2'),

url('font-lato/lato-regular-webfont.woff') format('woff'),

url(font-lato/lato-regular-webfont.ttf) format("opentype");

}

复制代码

很遗憾,字体并不会下载。 通常情况下,只有当我们的页面元素用到了font-face中定义的字体的情况下,才会下载对应的字体。注意: 这里我们说了是通常情况,这是因为,IE8在只要是定义了font-face,即使页面元素没有使用对应的字体,也会下载。

在其它浏览器中也不尽相同,

比如在Firefox 和 IE 9+ 中,遇到如下情况也会下载字体:

html

复制代码#test {

font-family: Lato;

}

复制代码

有什么特别之处呢? 你可能注意到了,这个元素虽然使用到了font-family: Lato样式,但是这个元素并没有任何文本啊!!!。 按照我们的理想情况,应该是,只有有文字内容才会去下载字体嘛。 而这就是Chrome, Safari (WebKit/Blink 等)浏览器的行为。

Chrome, Safari (WebKit/Blink 等)浏览器只有在如下类似情况才会去下载字体:

html

这里是有文本的哦

复制代码

css#test {

font-family: Lato;

}

复制代码

所以总结一下,不同浏览器下载字体的策略:IE8 只要定义了font-face,就会去下载字体,不论实际有没有应用该字体。

Firefox, IE 9+ 只有定义了font-face 并且页面有元素应用了该字体,就会去下载,不论该元素是否有文本内容。

Chrome, Safari 只有定义了font-face 并且页面有元素应用了该字体,并且该元素有文本内容,才会去下载字体。

那你可能会问了,如果我们的DOM元素是通过动态插入的呢?比如:var el = document.createElement('div');

el.style.fontFamily = 'open_sansregular';

document.body.appendChild(el);

el.innerHTML = 'Content.';

复制代码

答案是一样的,它的下载策略如下:var el = document.createElement('div');

el.style.fontFamily = 'open_sansregular';

/* 到这里,IE8就会开始下载字体 */

document.body.appendChild(el);

/* 只有到这里,Firefox, IE 9+ 才会开始下载字体 */

el.innerHTML = 'Content.';

/* 只有到这里,Chrome, Safari 才会开始下载字体 */

复制代码

三、 FOIT(Flash of Invisible Text)

FOIT是浏览器在加载字体的时候的默认表现形式,也就是在字体加载过程中,页面是看不到文本内容的。在现代浏览器中,FOIT会导致这种现象出现至多3秒。FOIT会导致很差的用户体验,这是我们需要尽量去避免的。

四、 FOUT(Flash of Unstyled Text) 与 font-display属性

FOUT意思是在字体加载过程中使用默认的系统字体,字体加载完后显示加载的字体,如果超过了FOIT(3s)字体还没加载,则继续使用默认的系统字体。

IE浏览器和Edge不会等待FOIT超时才显示默认字体,会立即显示默认字体。FOUT比FOIT好,但是需要注意它引起的reflow.

那么要想使浏览器有FOUT行为,我们需要在设置@font-face的时候给它加一个属性:font-display。 font-display默认是auto, 可选属性与含义如下:auto. The font display policy is user-agent-defined.

block. Gives the font face a short block period (3s is recommended in most cases) and an infinite swap period.

swap. Gives the font face an extremely small block period (100ms or less is recommended in most cases) and an infinite swap period.

fallback. Gives the font face an extremely small block period (100ms or less is recommended in most cases) and a short swap period (3s is recommended in most cases).

optional. Gives the font face an extremely small block period (100ms or less is recommended in most cases) and a 0s swap period.

一般设置成fallback和optional即可。

五、 preload

在页面加入下面这个代码以便更快的加载字体:

复制代码

通常和最基本的字体用法配合使用

六、 字体转 BASE64URI

这种方法就是将@font-face中定义字体时的路径直接改为字体的base64编码。

优点: 这种做法的优点是不会产生FOIT和FOUT。所以也不会有reflow和repaint. 缺点: 字体转成base64也会很大,会影响页面首次加载速度。不支持逗号分隔的形式加载多种格式的字体,只能加载一种格式字体。这导致你为了尽可能保证所有浏览器都可以兼容,通常会指定为woff格式,因为woff格式兼容性好,但是却没法使用更小体积的woff2格式,因为woff2格式兼容性差点。

七、异步加载BASE64格式URI字体

这种方法就是通过异步的方式插入带有BASE64格式URI字体的CSS链接。

八、使用Font Load API + FOUT + class切换

这种方式是期初并不使用用到@font-face的class,然后用Font Load API加载我们想用的字体,然后切换相应的CSS即可。Font Load API是原生的API:document.fonts.load('1em open_sansregular')

.then(function() {

var docEl = document.documentElement;

docEl.className += ' open-sans-loaded';

});

.open-sans-loaded h1 {

font-family: open_sansregular;

}

复制代码

当然这种方法需要考虑浏览器兼容性的问题。

九、 FOFT(Flash of Faux Text)

FOFT会把字体的加载分成多个部分,首先加载罗马网络字体,然后会在加载真实的粗体和斜体的时候立即使用font-synthesis属性渲染粗体和斜体的变体。

这种方法是基于[使用Font Load API + FOUT + class切换]这种方式的,非常适合加载同一种字体但是不同粗细,字形的场景,比如罗马、粗体、斜体、粗斜体等。我们将这些字体分成2阶段: 第一阶段是罗马字体,然后立即渲染人造粗体和斜体,最后(第二阶段)用真实字体替代。这里面还可以使用sessionStorage优化访问重复视图的场景。

十、CRITICAL FOFT

CRITICAL FOFT和标准的FOFI的唯一区别就在于第一阶段罗马字体的加载,CRITICAL FOFT不会加载罗马字体的全集,只会加载它的一个子集(比如A-Za-z0-9),全集会在第二阶段加载。

十一、CRITICAL FOFT WITH DATA URI

这个和CRITICAL FOFT的唯一区别就是罗马子集字体的加载方式,前面是用Font Load API完成了,这里会将马子集字体硬编码成BASE64 URI的形式加载。

十二、 CRITICAL FOFT WITH PRELOAD

这个同上面的唯一区别还是第一阶段罗马子集字体的加载方式,它采用的是preload的形式加载。

结论

总的字体加载的策略可以用这个图总结如下:

参考文献

本文主要翻译自如下博客文章https://www.zachleat.com/web/comprehensive-webfonts/#font-display

https://dev.opera.com/articles/better-font-face/

html字体加载太慢,字体加载CSS @font-face性能优化的常用策略相关推荐

  1. 首屏加载从11s到1s,详解前端性能优化

    作者:夜雪暮歌 https://juejin.cn/post/6949896020788690958 全文共6511字/词,阅读大概需要13分钟,太长不看党请直接移步

  2. 手游特效太多怎么办?这里有一份性能优化方案可参考

    导语专家坐诊栏目,是腾讯游戏学院专家团打造的新栏目.面向行业中小团队,分享腾讯学院专家团在过往指导中所提炼的共性问题总结. 本期分享嘉宾:KM,图形图像优化渲染方面专家. 在ACT游戏中华丽的特效是不 ...

  3. 前端性能优化:使用媒体查询加载指定大小的背景图片

    日期:2013-7-8  来源:GBin1.com 直到CSS @supports被广泛支持,CSS媒体查询的使用接近于CSS中写逻辑控制.我们经常用CSS媒体查询来根据设备调整CSS属性(通常根据屏 ...

  4. css引入外部字体的压缩方法,解决网页加载太慢

    最近在做网站的时候,发现大多都是常见字体,想用@font-face引入一些特殊的字体,发现文件太大,动不动几十兆,影响网页加载速度,在网上找了半天,发现大多都是使用一款名字为字蛛的字体压缩器,http ...

  5. 前端页面性能优化 - 字体加载优化

    相比于英文的字库来说,中文字库的体积非常之大,小则1M,动辄几十 M 的体积非常常见.所以在前端页面性能优化中,字体加载的优化就显得尤为重要.阅读了相关的知识和文章,在研究了市面上字体加载方案之后,我 ...

  6. 需要某个字体包才能正确显示此页面_[三分钟小文]前端性能优化-页面加载速度优化...

    本期内容请记住一个核心:JavaScript很快,DOM很慢 阅读本文您将收获: 从用户输入URL到看得到页面的过程 页面渲染过程 在页面加载层级的性能优化 用户看到页面之前都经历了什么 这一部分是面 ...

  7. Web 性能优化:使用 CSS font-display 控制字体加载和替换

    作者 | 张旭乾       责编 | 欧阳姝黎 出品 | 峰华前端工程师 在编写网站的时候,或多或少都会用到一些网络上的字体,CSS 3 中虽然加入了对 Web Fonts(网络字体)的支持,但是浏 ...

  8. python默认字体大小_如何设置PIL加载的默认字体的大小,使其适合我的8x8矩阵?...

    我正在8x8矩阵显示器上显示文本,并且我没有一个方便使用我的BeagleBone的.ttf文件.如何设置PIL加载的默认字体的大小,使其适合我的8x8矩阵? 根据示例here,我应该能够说font = ...

  9. 小程序分包加载不同项目字体图标引用问题

    小程序分包加载不同项目字体图标引用问题 问题描述: 当主项目中使用了字体图标样式 子项目中也使用了字体图标样式,如果2个项目的字体图标不来自同一个地址的引用,会存在字体图标乱码现象 如 商城中分包加载 ...

  10. java 找不到字体_从Java中的TTF文件加载一些TrueType字体会导致FontFormatException:找不到字体名称...

    我试图从我的系统上的TTF文件创建一个 java.awt.Font实例,但只有一些字体能够加载而不会出错.下面的代码是我在网上找到的一些测试代码.在我的系统上运行时,它能够成功加载285种字体(例如A ...

最新文章

  1. JVM调优之实战案例(六)(转载)
  2. Spring Cloud Gateway(限流)
  3. 大数据:从入门到XX(一)
  4. 学长毕业日记 :本科毕业论文写成博士论文的神操作20160317
  5. C++Builder如何响应消息及自定义消息
  6. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1083:计算星期几
  7. linux之setsid命令
  8. python画图隐藏画笔_python画图
  9. Python学习笔记:目录与文件操作
  10. Oracle数据库块的物理损坏与逻辑损坏
  11. oracle典型安装配置,Oracle的安装配置一些有关问题
  12. oracle 表查询(1)
  13. 剖析Disruptor:为什么会这么快?(二)神奇的缓存行填充
  14. 字符串拆分成泛型列表
  15. 我的NVIDIA开发者之旅——Caffe教程(2)[Jetson TK1]Caffe工具环境(Linux)搭建实例
  16. 123321是一个非常特殊的数,它从左边读和从右边读是一样的。输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n 。
  17. 英国essay与澳洲essay写作区别以及注意事项
  18. 此数据库处于单用户模式,当前某个用户已与其连接。 ALTER DATABASE 语句失败。 (Microsoft SQL Server,错误: 5064)...
  19. 北京市地震灾后规划信息化分析
  20. UCT树用于四子棋对抗实验

热门文章

  1. 【ViPER音效插件】,完美提升电脑音乐播放效果
  2. 使用U盘全新安装Mac OS X EI Capitan
  3. CDH运维常见问题-cloudera-scm-agent 已死,但 pid 文件存在
  4. UNIX环境高级编程(第2版)第11-17章
  5. 模式识别+Matlab 最大似然分类(MLC)【贝叶斯(Bayes)分类法】
  6. C# 使用VS建立数据库并使用
  7. python计算三角函数的计算器_一个工具箱 之 三角函数计算器
  8. gbase里的分布表与复制表
  9. 文章自动采集重新组合工具
  10. 如何在IDEA上创建一个JSP项目【亲测有效】