fontaine
基于字体度量的自动字体回退
基于字体度量的自动字体回退
功能特性
- 💪 通过使用精心设计的字体度量本地字体回退,减少 CLS。
- ✨ 自动生成字体度量和覆盖规则。
- ⚡️ 纯 CSS,零运行时开销。
在演示项目中,启用/禁用 fontaine
会使 /
的渲染产生以下差异,无需任何自定义
之前 | 之后 | |
---|---|---|
CLS | 0.24 | 0.054 |
性能 | 92 | 100 |
安装
使用 pnpm
pnpm add -D fontaine
或者,使用 npm
npm install -D fontaine
或者,使用 yarn
yarn add -D fontaine
用法
import { FontaineTransform } from 'fontaine'
// Astro config - astro.config.mjs
import { defineConfig } from 'astro/config'
const options = {
fallbacks: ['BlinkMacSystemFont', 'Segoe UI', 'Helvetica Neue', 'Arial', 'Noto Sans'],
// You may need to resolve assets like `/fonts/Roboto.woff2` to a particular directory
resolvePath: id => `file:///path/to/public/dir${id}`,
// overrideName: (originalName) => `${name} override`
// sourcemap: false
// skipFontFaceGeneration: (fallbackName) => fallbackName === 'Roboto override'
}
// Vite
export default {
plugins: [FontaineTransform.vite(options)]
}
// Next.js
export default {
webpack(config) {
config.plugins = config.plugins || []
config.plugins.push(FontaineTransform.webpack(options))
return config
},
}
// Docusaurus plugin - to be provided to the plugins option of docusaurus.config.js
// n.b. you'll likely need to require fontaine rather than importing it
const fontaine = require('fontaine')
function fontainePlugin(_context, _options) {
return {
name: 'fontaine-plugin',
configureWebpack(_config, _isServer) {
return {
plugins: [
fontaine.FontaineTransform.webpack(options),
],
}
},
}
}
// Gatsby config - gatsby-node.js
const { FontaineTransform } = require('fontaine')
exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
const config = getConfig()
config.plugins.push(FontaineTransform.webpack(options))
actions.replaceWebpackConfig(config)
}
export default defineConfig({
integrations: [],
vite: {
plugins: [
FontaineTransform.vite({
fallbacks: ['Arial'],
resolvePath: id => new URL(`./public${id}`, import.meta.url), // id is the font src value in the CSS
}),
],
},
})
注意 如果您正在使用 Nuxt,请查看 nuxt-font-metrics,它在底层使用了
fontaine
。
如果您的自定义字体是通过 CSS 变量机制使用的,您需要对您的 CSS 变量进行微调,以帮助 fontaine。Docusaurus 就是一个例子,它使用 --ifm-font-family-base
变量来引用自定义字体。为了让 fontaine 能够将变量与字体关联起来,我们需要在该变量后面添加一个 {字体名称} override
后缀。这看起来像什么?想象一下,我们正在使用自定义字体 Poppins,它通过 --ifm-font-family-base
变量引用,我们将进行如下调整:
:root {
/* ... */
- --ifm-font-family-base: 'Poppins';
+ --ifm-font-family-base: 'Poppins', 'Poppins override';
在幕后,fontaine 会创建一个“Poppins override” @font-face
规则。通过手动将此覆盖字体家族添加到我们的 CSS 变量中,我们可以使我们的网站使用 fontaine 生成的具有正确字体度量的回退 @font-face
规则。
工作原理
fontaine
将扫描您的 @font-face
规则并生成具有正确度量的回退规则。例如
@font-face {
font-family: 'Roboto';
font-display: swap;
src: url('/fonts/Roboto.woff2') format('woff2'), url('/fonts/Roboto.woff')
format('woff');
font-weight: 700;
}
/* This additional font-face declaration will be added to your CSS. */
@font-face {
font-family: 'Roboto override';
src: local('BlinkMacSystemFont'), local('Segoe UI'), local('Helvetica Neue'),
local('Arial'), local('Noto Sans');
ascent-override: 92.7734375%;
descent-override: 24.4140625%;
line-gap-override: 0%;
}
然后,无论何时您使用 font-family: 'Roboto'
,fontaine
都会将覆盖规则添加到字体家族中。
:root {
font-family: 'Roboto';
/* This becomes */
font-family: 'Roboto', 'Roboto override';
}
💻 开发
- 克隆此仓库
- 使用
corepack enable
启用 Corepack(Node.js < 16.10 版本请使用npm i -g corepack
) - 使用
pnpm install
安装依赖项 - 使用
pnpm dev
运行交互式测试;使用pnpm demo:dev
启动一个 Vite 服务器。
致谢
这离不开以下贡献:
- capsizecss 提供的出色工具和生成的度量
- 来自 Google Aurora 团队的 Katie Hempenius 和 Kara Erickson 的建议和算法 - 参见 字体度量覆盖计算说明
- 来自 @clemcode 的包名建议
许可
用 ❤️ 制作
根据 MIT 许可证 发布。