font-family
一、认识
二、语法
2.1 内置字体
2.2 自定义字体
-
下载对应字体至项目
-
通过
@font-face
声明自定义字体@font-face{
font-family: "DejaVuSansMNerdFont";
src: url("DejaVuSansMNerdFont.ttf");
}
@font-face{
font-family: "HeavyDataNerdFont";
src: url("HeavyDataNerdFont.ttf");
} -
通过
font-family
应用自定义字体.text1{
font-family: "DejaVuSansMNerdFont";
}
.text2{
font-family: "HeavyDataNerdFont";
} -
完整示例如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>自定义字体</title>
<style>
@font-face{
font-family: "DejaVuSansMNerdFont";
src: url("DejaVuSansMNerdFont.ttf");
}
@font-face{
font-family: "HeavyDataNerdFont";
src: url("HeavyDataNerdFont.ttf");
}
.text1{
font-family: "DejaVuSansMNerdFont";
}
.text2{
font-family: "HeavyDataNerdFont";
}
</style>
</head>
<body>
<div class="text1">DejaVuSansMNerdFont 字体</div>
<div class="text2">HeavyDataNerdFont 字体</div>
</body>
</html>
三、优化
3.1 动态加载字体文件 font-face
需求描述
: 字体包体积巨大, 基本上都在几M
左右。 所以,在以下场景需要考虑按需加载字体:
- 场景一: 实时编辑一个
DOM
元素, 可以切换字体。如果直接将全部字体写入到样式文件中,IE
浏览器首先会下载全部注册声明的字体,即使未使用该字体。谷歌等浏览器实现了按需加载字体文件的功能。但是我们在使用html2-canvas
或者dom-to-image
第三方DOM
转Image
的时候, 会下载完全部字体,然后再开始解析、转化, 增加了DOM
转Image
的时间。
解决方案: 当需要加载字体时,向 DOM
添加 @font-face
,动态加载字体。
实现如下:
const lazyLoadFontFamily = (fontFamily: string) => {
if (!fontFamily) {
return;
}
const documentStyle = document.createElement('style');
const fontFace = `
@font-face{
font-family: ${fontFamily};
src: url(${currentCdnUrl}custom-course-cover/fonts/${fontFamily}.ttf);
}
`;
documentStyle.appendChild(document.createTextNode(fontFace));
document.head.appendChild(documentStyle);
};
但是这里存在一个问题,由于请求接口需要一定的时间,文字会出现先空白一段时间后显示的现象。这种现象被称之为 FOIT (Flash Of Invisible Text)
。我们需要寻找优化办法。 font-display
属性在 CSS
层面上提供了此类问题的解决方法。使用 font-display: swap
我们可以采用先使用系统默认字体,在中文字体下载完成后替换。
3.2 动态加载字体文件 FontFace
解决方案: 在 Javascript
层面,浏览器也提供了 CSS Font Loading API
来操作字体。它在大部浏览器中已经得到了支持。通过 JS API
可以比较方便的控制页面的呈现。可以在字体加载前做些交互上的优化等
具体实现
const lazyLoadFontFamily = (fontFamily: string) => {
if (!fontFamily) {
return;
}
const newFont = new FontFace(fontFamily, `url("${currentCdnUrl}custom-course-cover/fonts/${fontFamily}.ttf")`);
document.fonts.add(newFont);
};
3.3 动态加载具体字体 font-face
解决方案: 当需要加载字体时,向 DOM
添加 @font-face
,动态加载字体。
实现如下:
- Web
- Node
const lazyLoadFontFamily = (fontFamily: string) => {
if (!fontFamily) {
return;
}
const documentStyle = document.createElement('style');
const fontFace = `
@font-face{
font-family: ${fontname};
src: url("http://xxxx:8080/api/webfont?font=${fontname}&text=${encodeURIComponent(text)}`;
documentStyle.appendChild(document.createTextNode(fontFace));
document.head.appendChild(documentStyle);
};
通过 JavaScript
添加一个 CSS
样式。浏览器会自行解析并在下载完成字体后显示中文字体。
var Fontmin = require('fontmin');
const path = require('path');
module.exports = function(req, res, next) {
// 字体源文件
var srcPath = path.join(__dirname, '../../static/huiwenmingchao.otf');
var text = req.query.text;
// 文字去重
var textArr = Array.from(new Set(text.split('')));
text = textArr.join('');
// 初始化
var fontmin = new Fontmin().src(srcPath).use(
// 字型提取插件
Fontmin.glyph({
text: text // 所需文字
})
);
fontmin.run(function(err, files, stream) {
if (err) {
// 异常捕捉
console.error(err);
}
res.send(files[0].contents);
});
};
基于express
框架实现一个API
,动态字体从参数传入,路由中使用fontmin
模块对字体进行抽取,抽取后的buffer
直接返回给前端。
3.4 动态加载具体字体 FontFace
解决方案: 在 Javascript
层面,浏览器也提供了 CSS Font Loading API
来操作字体。它在大部浏览器中已经得到了支持。通过 JS API
可以比较方便的控制页面的呈现。可以在字体加载前做些交互上的优化等
实现如下:
- Web
- Node
const lazyLoadFontFamily = (fontFamily: string) => {
if (!fontFamily) {
return;
}
const newFont = new FontFace(fontFamily, `url("http://xxxx:8080/fontmin?font=${fontname}&text=${encodeURIComponent(text)}")`);
document.fonts.add(newFont);
};
通过 JavaScript
添加一个 CSS
样式。浏览器会自行解析并在下载完成字体后显示中文字体。
var Fontmin = require('fontmin');
const path = require('path');
module.exports = function(req, res, next) {
// 字体源文件
var srcPath = path.join(__dirname, '../../static/huiwenmingchao.otf');
var text = req.query.text;
// 文字去重
var textArr = Array.from(new Set(text.split('')));
text = textArr.join('');
// 初始化
var fontmin = new Fontmin().src(srcPath).use(
// 字型提取插件
Fontmin.glyph({
text: text // 所需文字
})
);
fontmin.run(function(err, files, stream) {
if (err) {
// 异常捕捉
console.error(err);
}
res.send(files[0].contents);
});
};
基于express
框架实现一个API
,动态字体从参数传入,路由中使用fontmin
模块对字体进行抽取,抽取后的buffer
直接返回给前端。