web安全字体

 

webfont解剖

  • Unicode字体可以包含数以千计字形
  • 有四个字体格式: WOFF2, WOFF, EOT, TTF
  • 一些字体格式需要使用GZIP压缩 

一个web字体是字形的集合,且每个字形是一个描述了一个字母亦或符号的矢量图。

所以,一个字体文件的大小由两个因素决定:每个字形矢量路径的复杂程度和每个字体所包含的字形数量。

例如,Open Sans, 最流行的web字体之一, 包含了897个字形,包含了拉丁,希腊和古代斯拉夫语字母。

Font glyph table

当选择一个字体的时候,重要的是考虑哪些字符集被支持。

例如, Google’s Noto font family 目标是支持世界上所有的语言. 但是,注意Noto的大小,因为包括了所有的语言,所以压缩后大小是130MB+。

Web字体格式

网上如今四个web字体格式: EOT, TTF, WOFF, 和 WOFF2.

不幸的是,虽然有很多的选择,但是没有一个字体是可以在旧的浏览器和新的浏览器上通用的:EOT只适用于IE,TTP部分被IE支持。WOFF享有最广泛的支持但是在老的浏览器中不必支持,并且对于很多新的浏览器真在添加对于WOFF 2.0的支持。

所以,这意味着我们需要使用多个字体格式来保持良好的用户体验:

  • 在支持WOFF 2.0的浏览器中使用WOFF 2.0 变体
  • 在大多数浏览器中使用WOFF字体
  • 在老的安卓(低于4.4)浏览器中使用TTF变体
  • 在老的IE(低于IE9)中使用EOT变体 

使用压缩来减少字体大小

A font is a collection of glyphs, each of which is a set of paths describing the letter form. The individual glyphs are, of course, different, but they nonetheless contain a lot of similar information that can be compressed with GZIP, or a compatible compressor:

  • EOT, 和 TTF 格式默认没有压缩:确保你的服务器使用了GZIP压缩 
  • WOFF 有内置的压缩 - 确保你的WOFF压缩器使用了最优化的设置。
  • WOFF2 使用了用户预定义和压缩算法来减少相对于其他字体格式约30%的文件大小

值得注意的是一些字体格式包括了额外的信息——比如font hitting和kerning信息,这些可能是不必要的,所以可以进行深入优化。

查看你的字体编译器可操作的选项,如果你可以优化上面的内容,进行优化,并在不同的浏览器中查看效果。

Note

  • 可以使用 Zopfli compression 来压缩EOT, TTF,和 WOFF 字体格式. Zopfli 是一个 zlib兼容的压缩器,压缩的内容比gzip压缩后还要小约5%。

使用 @font-face定义字体

  • 使用format()定义不同的字体格式
  • 使用大量的子集提高性能: 提供大量可选的子集可以让旧的浏览器兼容 
  • 减少样式化的字体变体来提高页面和文字渲染效果 

 css语句@font-face定义特殊的字体资源的位置,字体样式等。

字体样式选择

每个 @font-face 声明提供了font family的名字,字体属性的什么和特殊字体来源地址的声明。

@font-face {font-family: 'Awesome Font';font-style: normal;font-weight: 400;src: local('Awesome Font'),url('/fonts/awesome.woff2') format('woff2'), url('/fonts/awesome.woff') format('woff'),url('/fonts/awesome.ttf') format('ttf'),url('/fonts/awesome.eot') format('eot');
}@font-face {font-family: 'Awesome Font';font-style: italic;font-weight: 400;src: local('Awesome Font Italic'),url('/fonts/awesome-i.woff2') format('woff2'), url('/fonts/awesome-i.woff') format('woff'),url('/fonts/awesome-i.ttf') format('ttf'),url('/fonts/awesome-i.eot') format('eot');
}

 

上面一个 Awesome Font 字体的两个表现形式类型:正常和斜体,每个都提供了一系列的不同字体资源设置。

每个src描述符包括了一个按照优先顺序排序的,用逗号进行分隔的资源列表:

  • local() 表明我们可以使用哪些本地的字体 
  • url() 指定我们加载哪些外部字体,允许我们使用format()来指代字体的格式 

Note

  • 除非你指向系统的默认资源,除非很少有本地的字体资源,特别是对手机设备而言,不可能在内部安装了额外的字体。所以,你总是需要提供一个额外的字体位置清单。

浏览器按照顺序执行,上例浏览器执行如下:

  1. 浏览器显示页面布局并决定哪个字体变形被需要来渲染指定的字体;
  2. 依次检查local()中的字体是否存在并可使用;  如果本地不存在,依次检查外部字体定义:
  • 如果字体格式存在,在初始化和下载字体之间检查浏览器是否支持,如果不支持,进入下一个外部字体选项检查 
  • 如果字体格式不存在,浏览器下载资源 

Note

  • 外部字体加载的顺序十分重要,因为浏览器是按照这个顺序依次执行的。

Unicode-range 子集

我们可以将一个大的字体设置成小的子集(例如拉丁,希腊和斯拉夫字母等),并且只是加载这个子集来渲染页面上的字体

 

这个 unicode-range descriptor 允许我们指定一个逗号隔开的数据集合, 数据可以是下面三种形式中的任何一种:

  • Single codepoint (e.g. U+416)
  • Interval range (e.g. U+400-4ff): indicates the start and end codepoints of a range
  • Wildcard range (e.g. U+4??): ‘?’ characters indicate any hexadecimal digit

例如我们可以将Awesome Font设置成拉丁和日本语的子集格式,它们只有在浏览器需要的时候才会加载 

@font-face {font-family: 'Awesome Font';font-style: normal;font-weight: 400;src: local('Awesome Font'),url('/fonts/awesome-l.woff2') format('woff2'), url('/fonts/awesome-l.woff') format('woff'),url('/fonts/awesome-l.ttf') format('ttf'),url('/fonts/awesome-l.eot') format('eot');unicode-range: U+000-5FF; /* Latin glyphs */
}@font-face {font-family: 'Awesome Font';font-style: normal;font-weight: 400;src: local('Awesome Font'),url('/fonts/awesome-jp.woff2') format('woff2'), url('/fonts/awesome-jp.woff') format('woff'),url('/fonts/awesome-jp.ttf') format('ttf'),url('/fonts/awesome-jp.eot') format('eot');unicode-range: U+3000-9FFF, U+ff??; /* Japanese glyphs */
}

Note

  • Unicode-range子集设置对于亚洲语言非常重要,因为亚洲语言的字形比西方语言要多得多,一个字形百万字节,而不是亚洲字符的千字节。

使用unicide range子集并将文件分成字体不同样式的变体让我们可以更加迅速和高效的下载——用户只需要下载子集和变体就可以,用户不需要下载永远不会用到的字体。

但是,不是所有的浏览器支持unicode-range字段。一些浏览器忽略了unicode-range字段,并且将下载所有的字体;另一些浏览器压根儿不会执行@font-face声明。所以,我们对于旧的浏览器需要“手动设置子集”。

因为旧的浏览器不够聪明来选择需要的字体子集并且不能合成一个合适的字体,所以我们必须回退来提供一个单一的字体资源,这个字体资源包括了所有必要的子集,并且对浏览器而言隐藏了其他的子集。

例如,如果网页只是使用拉丁文子集。我们可以剥夺其他的字形,并且将一个指定的子集设置成单独的资源。

  1. 我们怎样判断哪些字体子集是我们需要的?
    • 如果unicode-range子集是被浏览器支持的,那么浏览器就会在自动的选择合适的子集,页面只需要提供子集文件和在@font-face指定合适的unicode-ranges
    • 如果unicode-range不是浏览器支持那么页面需要隐藏所有不必要的子集——例如,开发者必须指定需要的子集。
  2. 我们在什么样的情况下创造子集?
    • 使用开源工具 pyftsubset tool 来设置和最优化你的子集.
    • 一些字体提供商允许你在用户自定义参数中手动设置字体子集,你可以通过这个方法来手动的为你的页面创建需要的字体——访问字体提供商的页面!

字体选择和合成

每个字体家族都是包含很多样式的字体变体(例如常规,加粗,斜体等等),并且每一种字体变体都有字体权重设置,所以,这将导致了很多不同的字形——例如,不同空格,字体大小都将导致同一个字形变得不同。

Font weights

例如,上面的图形展示了一个字体在三种不同的权重下的表现:400(普通),700(加粗),900(额外加粗)。

所有的在三个标准之间的权重(灰色显示的)将通过浏览器自动的适应最贴近的三种标准变体。


上述逻辑同样适用于斜体字体,但是要记住,字体变形数量使用越少越好!

@font-face {font-family: 'Awesome Font';font-style: normal;font-weight: 400;src: local('Awesome Font'),url('/fonts/awesome-l.woff2') format('woff2'), url('/fonts/awesome-l.woff') format('woff'),url('/fonts/awesome-l.ttf') format('ttf'),url('/fonts/awesome-l.eot') format('eot');unicode-range: U+000-5FF; /* Latin glyphs */
}@font-face {font-family: 'Awesome Font';font-style: normal;font-weight: 700;src: local('Awesome Font'),url('/fonts/awesome-l-700.woff2') format('woff2'), url('/fonts/awesome-l-700.woff') format('woff'),url('/fonts/awesome-l-700.ttf') format('ttf'),url('/fonts/awesome-l-700.eot') format('eot');unicode-range: U+000-5FF; /* Latin glyphs */
}

 

上面的例子声明了一个 Awesome Font 家族字体,包含了拉丁字形,但是拥有两种不一样的权重:normal(400)和blod(700)。字体不同的形式实现的原理是什么呢?

  • 如果给出的字体权重不是标准的(400,700和900),那么将随浏览器匹配最接近标准的字体形式。
  • 如果字体斜体匹配没有发现(例如,我们没有在上例中声明任何的斜体变形),那么浏览器近合成它的自有的字体变形。

Font synthesis

必须要知道的是,有些字体通过合成的方法合成的字体会十分难看(比如Cyrillic合成斜体),所以最好使用已经存在的斜体,而不是浏览器自动合成。

上面的例子解释了实际斜体和浏览器合成的斜体之间的不同(字体是Open-Sans字体)。

你可以在结果中看见显著的不同,不同的浏览器合成字体不同并且不同的字体之间合成的字体也不同。

Note

  • 为了最好的用户体验,我们应该尽量不要使用字形变体,我们最好指定字体的位置让页面来下载它们。总而言之,使用浏览器合成的变体必须非常小心。

优化下载和渲染

  • 字体加载请求会在渲染树(the render tree)被创建之后,这可能导致字体渲染被延迟。
  • 字体加载API同样也允许我们实现用户自定义的字体加载和渲染政策来重写和替代默认的字体延迟加载
  • Font inlining 允许我们在旧的浏览器中重新书写字体加载形式

一个完整的web字体包含了所有形式的变体,和所有的字形,但是有些字形和字体的变体我们可能不需要,导致下载完整的web字体需要多个百万字节。

所以使用@font-face是我们可以加载指定范围的web字体,使用unicode 子集,独特的字体变形等等。

给出这些申明后浏览器可以加载指定的字体来进行渲染,虽然很方便,但是如果我们不小心的话,会导致在渲染时产生障碍——这些是我们需要避免的!

web字体渲染方式

我们知道字体的渲染必须在浏览器创建了渲染树(就是DOM树和CSSOM树)之后,所以,也就是说字体渲染必须等到所有的资源都被抓取之后

Font critical rendering path

  1. 浏览器情趣HTML2文档
  2. 浏览器开始解析HTML响应和构造DOM
  3. 浏览器你发现CSS,JS和其他的资源并且分配请求  当所有的css内容都被接受并且将其和DOM树结合在一起之后构建CSSOM。
  • 当树DOM树被渲染的时候字体被请求,说明了字体变体被渲染到指定的文本上。
浏览器将布局展现在屏幕上面
  • 如果浏览器不可以获得字体吗,那么将不会渲染任何的文本像素
  • 一旦浏览器可以获得字体,浏览器将会渲染文本像素

不同的浏览器在渲染的时候执行的操作不一样:

  • Safari 在文本下载全部完成之后才进行文本渲染
  • Chrome 和 Firefox 在你使用一个回退字体时,进行三秒钟的字体渲染, 并且一旦字体下载完成,浏览器用刚下载的字体再次进行渲染
  • IE马上渲染回退字体如果请求的字体不可获得,并且一旦字体加载全部完成之后在进行再次渲染 。

不同的人有不同的喜好——有些人喜欢马上进行渲染有些人喜欢在回退字体加载后进行再次渲染——我们不做任何的评论,但是我们关注的是在布局加载时进行的字体渲染怎样才能进行优化?

使用字体下载API来优化字体渲染

Font Loading API 提供了一个编程脚本来定义和操作CSS字体,追踪字体的下载进程和重写字体的懒加载行为(懒加载是指在DOM树和CSSOM树加载完成之后才进行字体加载渲染的行为)。

例如,如果我们确保一个特殊的字体变形会被请求,我们可以定义它并且告诉浏览器来初始化即时加载字体资源行为:

var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});font.load(); // don't wait for render tree, initiate immediate fetch!font.ready().then(function() {// apply the font (which may rerender text and cause a page reflow)// once the font has finished downloadingdocument.fonts.add(font);document.body.style.fontFamily = "Awesome Font, serif";// OR... by default content is hidden, and rendered once font is availablevar content = document.getElementById("content");content.style.visibility = "visible";// OR... apply own render strategy here... 
});

 

而且,因为我们可以检查字体的状态(font status)通过check()方法,并且追踪下载的速度,我们同样可以定义一个自定义的策略来在我们的页面上渲染文本,

  • 我们可以知道字体可以使用时才渲染所有文本 
  • 我们可以对于每一个字体设置定时器timeout 

我们可以在不同的页面上使用不同的策略。

Note

  • 字体加载API在某些浏览器中还尚在开发中,可考虑使用FontLoader polyfill, 或者 webfontloader library, 来产生相同的效果

使用inlining来优化渲染字体

  • 在构建CSSOM对象的时候,css样式中匹配设备的查询将作为首选自动加载 
  • 将字体数据嵌入css样式表中将强制浏览器来加载字体,并且以高优先级进行不用等到渲染树的完成

但是 inlining策略不够灵活并且不允许针对不同个页面我们来定义用户自定义的定时器和渲染策略。为了最好的效果,将你的嵌入字体数据的css独立成css文件,并且加载的时候设置max-age属性,这样当你更新css文件的时候不用强迫你的用于再次下载你的字体。

Note

  • 使用inlining策略! 记得上面说的懒加载么?浏览器通常都是在加载DOM和形成CSSOM对象之后,形成渲染树之后在渲染数据内容到屏幕上的!将字体数据放在CSS中,也就是放在CSSOM对象形成之时!

使用HTTP缓存优化你的字体再使用

字体资源是静止的资源,所以可以再次使用,使用http缓存,为字体设置较长时间的max-age。没有必要将字体存储在localStorage中,这会影响性能。

优化总结列表

使用web字体除了会进行下载和下载不必要的资源之外,不会影响页面的渲染和性能!所以放心大胆使用,下面是一些优化建议:

  1. 审查和监听你的字体: 每个网页中不要使用太多的字体,每个字体都要简化它们的变体数量。
  2. 使用字体资源中的子集: 没有必要下载整个字体资源,使用特定的字体子集。特别是对于亚裔字体而言,一定要加载子集。
  3. 对每个浏览器而言使用最优化的字体格式: 每个字体都应该提供 WOFF2, WOFF, EOT, 和 TTF的字体格式. 确保对 EOT 和 TTF进行GZIP压缩,因为默认它们是没有进行压缩的
  4. 使用缓存策略: 字体资源是静态的,所以记得使用max-age来设置http缓存
  5. 使用字体加载API来制定字体渲染方式: 默认的加载方式是字体最后渲染,字体加载API允许我们重写对于特定字体的渲染行为,对于不同的网页我们可以自定义渲染方式亦或设置一个定时器策略。对于旧的不支持字体加载API的浏览器,我们可以使用webfontloader的js库亦或使用css嵌入策略。
原文:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization?hl=en

转载于:https://www.cnblogs.com/RachelChen/p/5452870.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/403880.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue如何引入ant部分组件

官网ant 在marn.js下 import Vue from vue; import { Button, message } from ant-design-vue; import App from ./App;Vue.config.productionTip false;/* v1.1.2 */ Vue.component(Button.name, Button); Vue.component(Button.Group.name, Button.Group);/* v1.1.3 自动注…

各个行业纷纷瞅准了这块大蛋糕

今年以来,新疆民生工程和各援疆项目不断加大建设力度,钢材、石料等建筑上必不可少的材料需求见涨,钢铁行业和砂石行业纷纷进驻新疆市场,建厂投资,使新疆展现出一派向着繁荣发展的热火景象。黎明重工是矿山机械行业的领…

关于头文件中的 static inline函数

关于头文件中的 static inline函数头文件中常见static inline函数,于是思考有可能遇到的问题,如头文件经常会被包含会不会产生很多副本?网上说法不一。于是自己验证。经过arm-none-eabi-gcc下测试后得出结论。inline 关键字实际上仅是建议内联…

sql中问号是干什么的??

第一次在后台 程序中遇到sql语句中的问号: /*** * 方法描述 : 通过账号id更新该账号状态* param state 状态* param id 账号id*/ModifyingQuery("update LabAccount t set t.userState ?1 where t.userAcctId ?2")void updateState(String state, Stri…

linux下挂载windows上的共享目录,并设置所有者为非root用户

参考了很多文章,这里总结下我得出来的最优答案(针对我的需求而言)吧,但是还是存在bug,稍后指出! 以下是我的bash脚本,防止多次重复挂载,相信看了就能明白: [zcmvm-fedora20 share]$ cat m.sh #…

vue项目登录及token验证 vue-ant

在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下: 1、第一次登录的时候,前端调后端的登陆接口,发送用户名和密码 2、后端收到请求,验证用户名和密码,验证成功,就给前端返回一个…

广告狂人 第1季

《Mad Men/广告狂人》是由American Movie Classics公司出品的美剧。故事背景设定在上世纪六十年代的纽约,大胆地描述了美国广告业黄金时代残酷的商业竞争。该剧曾获得第65届、第66届、第67届美国电影电视金球奖最佳电视剧。并连续四年夺得艾美奖剧情类最佳电视剧奖。…

设置Clover默认进入Windows,按快捷键F8可选择不同的引导

系统情况: Win7 Mac10.9.5 Clover 我要达到的目标是:默认进入Windows系统,如果有需要,可以选择进入其他系统,如Mac OS X 我原以为可以在clover中配置,达到这个目标,可是我经过多次实践&am…

适配器和外观模式

结构型:Adapter与Facade(适配器和外观模式)   一般作为阅读材料,首先想要明确的是我现在了解的设计模式的初衷,即为了解决什么问题。 适配器,如果有买过港版Iphone在内地使用的人应该会有三角大插头必须接…

js获取cookie获取不到问题 vue获取cookie以及获取不到问题

1.下载依赖包 npm i js-cookie -S2.在使用cookie的页面上进行引入 import Cookies from js-cookie3.使用 创建一个在整个网站上有效的CookieCookies.set(name, value);创建一个从现在起7天后过期的cookie,在整个站点上有效:Cookies.set(name, value, …

smarty二维foreach示例[顺代一维数组],再次加强版

2019独角兽企业重金招聘Python工程师标准>>> smarty二维foreach示例[顺代一维数组],再次加强版 WEB2.0 root 2009-4-9 10:46 评论(0) 阅读(682) 大 | 中 | 小 WEB2.0 | 评论(0) | 引用(0) | 阅读(682) view plain print ? {foreach itemrec from$result…

linux 函数学习--kzalloc()

使用include <linux/slab.h>void *kmalloc(size_t size, int flags);static inline void *kzalloc(size_t size, gfp_t flags) { return kmalloc(size, flags | __GFP_ZERO); } 123456说明给 kmalloc 的第一个参数是要分配的块的大小. 第 2 个参数, 分配标志 用kza…

动态链接库和静态链接库

From: http://blog.163.com/zhangjie_0303/blog/static/99082706201081105654484/ 动态链接库dll&#xff0c;静态链接库lib, 导入库lib 目前以lib后缀的库有两种&#xff0c;一种为静态链接库(Static Libary&#xff0c;以下简称“静态库”)&#xff0c;另一种为动态连接库(…

div与div区别小结

两者之间的区别:例如div span得到的是div下所有的span元素&#xff0c;而div>span则是取得的div下第一级的span元素。 示例代码如下&#xff1a; <!DOCTYPE html><html lang"en" xmlns"http://www.w3.org/1999/xhtml"> <head><met…

url的特殊字符编码 encodeURI编码

参考&#xff1a; 编码解码 前沿&#xff1a; 例如上传资源视频图片&#xff0c;针对一些特殊的字符&#xff01;#&#xffe5;%……&*&#xff08;&#xff09;&#xff1f;《{[,./’~ 不做转码的时候url识别会错&#xff0c;图片就不会显示出来&#xff0c;这时候就需要对…

Linux设备驱动之Kobject、Kset

LDD3中说&#xff0c;Kobject的作用为&#xff1a;1、sysfs 表述&#xff1a;在 sysfs 中出现的每个对象都对应一个 kobject, 它和内核交互来创建它的可见表述。2、热插拔事件处理 &#xff1a;kobject 子系统将产生的热插拔事件通知用户空间。 3、数据结构关联&#xff1a;…

40个新鲜出炉的 jQuery 插件和免费教程【上篇】 转载自:梦想天空

40个新鲜出炉的 jQuery 插件和免费教程【上篇】 转载于:https://www.cnblogs.com/chenjunLovefan/archive/2012/07/23/2605003.html

vector, list, map在遍历时删除符合条件的元素

直接看源码&#xff0c;内有详细解释 /*测试vector, list, map遍历时删除符合条件的元素本代码测试环境: ubuntu12 win7_x64*/#include <iostream>#include <vector>#include <list>#include <map>#include <iterator>using namespace std;void…

图片不显示问题 图片url监测改变问题

问题&#xff1a;点击按钮换一换的时候&#xff0c;后台返回的三张小图片的地址还是原来的地址&#xff0c;但是三张小图确实是变了&#xff1b;这时候如果一开始头图是图3&#xff0c;点击换一换后&#xff0c;三张小图变了&#xff0c;此时还是想选择图3为头图&#xff1b;却…

linux设备:cdev和kobj_map

先看kobj_map相关的代码涉及到的文件<linux/kobj_map.h><drivers/base/map.c>[objc] view plaincopyprint?typedef struct kobject *kobj_probe_t(dev_t, intint *, voidvoid *); struct kobj_map; int kobj_map(struct kobj_map *, dev_t, unsigned long, stru…