documents

# CSS 或 <style> 嵌入字体的正确示例

  • 概述
  • 中文字体通常提供一个名为 result.css 的文件,这是中文字体引入和按需加载的关键文件,应使用 @import 方式声明或 <link> 标签引入 ,例如:

    @import url('https://static.zeoseven.com/cn/1/main/result.css')

    这实际上等同于 <link> 引入了一个 CSS 文件,这个 CSS 文件中已使用 @font-face 声明了所有子集 WOFF2 文件,只需要在一个 CSS 类中正确设置 font-family 即可引入。

  • 定义
  • 正确的 font-family 名称应展示在字体详情页的 “嵌入字体” 模块,除非那是错误的,那么就需要打开 result.css 文件查看 @font-face 声明的 font-family 来正确使用。

    而英文字体因为直接提供了 WOFF2 文件,所以可以直接使用 @font-face 声明,并自定义 font-family。


    中文字体固定 font-display: swap;

    英文字体提供源 WOFF2 文件可自定义 font-display 。

  • 使用 CSS 代码正确嵌入
  • /* 中文字体使用 @import 引入 */
    @import url('https://static.zeoseven.com/cn/1/main/result.css');
    
    /* 英文字体使用 @font-face 引入并实现冗余
    @font-face {
        font-family: "ZSFT-a";
        src: url('https://static.zeoseven.com/en/a/main.woff2'),
        * 当 CDN 不可用时直接由源服务器提供文件
        url('https://static-host.zeoseven.com/en/a/main.woff2');
        font-display: swap; /* 设置字体加载期间的显示规则,如 auto, swap, block, fallback, optional。 */
    } */
    
    /* 选择器除了 html 也可以是 :root, body, div, p, .class, #id 等任何一切标签、类或 ID。 */
    html {
        /* 在这里定义一切可能的 CSS 属性。属性的值作用不做描述。 */
        font-family: "JinzisheTongfang"; /* 设置字体家族,推荐而非必需。 */
        font-weight: normal; /* 设置字体的粗细,如 normal, bold, 或 100 至 900 之间的数值。 */
        font-style: normal; /* 设置字体样式,如 normal, italic, oblique。 */
        font-variant: normal; /* 设置字体变体,如 normal, small-caps。 */
        font-size: 16px; /* 设置字体大小,可以是 绝对大小(如 px, pt) ,或 相对大小 (如 %, em, rem, vw, vh) ,但不推荐在 html 根元素使用相对大小。 */
        line-height: normal; /* 设置行高,可以是数值、百分比、关键字 (如 normal) ,或 相对单位 (如 em, rem) 。 */
        text-decoration: none; /* 设置文本装饰,如 none, underline, overline, line-through ,也可以是复合值。 */
        text-align: left; /* 设置文本对齐方式,如 left, right, center, justify。 */
        text-transform: none; /* 控制文本的大小写,如 none, uppercase, lowercase, capitalize。 */
        letter-spacing: normal; /* 设置字符之间的间距。 */
        word-spacing: normal; /* 设置单词之间的间距。 */
        white-space: normal; /* 设置如何处理元素中的空白符,如 normal, nowrap, pre, pre-wrap, pre-line, break-spaces。 */
        direction: ltr; /* 设置文本方向,如 ltr (左到右), rtl (右到左)。 */
        text-shadow: none; /* 设置文本阴影效果,可以包含多个值,每个值有偏移量、模糊半径和颜色。 */
        color: #000; /* 设置字体颜色,可以是 十六进制、RGB、RGBA、HSL、HSLA、颜色关键字 等。 */
        /* ...... 更多属性 */
    }
  • 避免和 fonts.googleapis.com 的使用方式混淆
  • ZeoSeven Fonts (ZSFT) 的目的是打造一个在中国大陆还没有的公益独立字体 CDN 、在线预览和介绍服务, ZSFT 是绝对独立的,不提供 fonts.googleapis.com 或 fonts.gstatic.com 中的资源代理,不同于也并不兼容 fonts.googleapis.com ,不支持查询字符串来定义字体属性(因为一切资源由静态的方式提供,可减少因算力导致的成本), CSS 文件中没有定义任何属性,只有按需加载的字符集定义,所以一切属性值应在自己的 CSS 代码中设置,如上方的 “使用 CSS 代码正确嵌入” 例子,而不是使用 static.zeoseven.com/cn/1/main/result.css?family=JinzisheTongfang:wght@400display=swap 类似的方式来定义字体属性,虽然也可以正确工作,但没有实际意义。这并不是否定国际的公益字体 CDN 、在线预览和介绍服务,而是 ZeoSeven 看到很多使用查询字符串设置字体属性后反馈错误的用户。

    # 中文字体使用 JavaScript 引入实现冗余

  • 概述
  • 实际上,每个字体详情页中都有对应的可选的 JS 代码,因为引入 CSS 文件并没有直接像 @font-face 引入一样的后备 URL ,而使用 JS 引入字体不仅实现了冗余,还实现了异步加载和更好的扩展性。

  • 代码解释
  • /* 使用 IIFE 表达式避免污染全局命名空间 */
    (() => {
        function a (b,c) {
            /* 创建一个新的 link 元素来加载样式表 */
            var d = document.createElement('link');
            d.rel = 'stylesheet';
            /* 设置 link 元素的 href 属性为传入的 CSS 文件 URL */
            d.href = b;
            /* 当加载样式表失败时触发 onerror 事件处理器 */
            d.onerror = function() {
                if (typeof c==='function') {
                    c();
                }
            };
            /* 将创建的 link 标签添加到 head 标签 */
            document.head.appendChild(d);
            /* 设置根元素的字体属性,当然, JS 是灵活的,也可以将字体设置到其它元素 */
            document.documentElement.style.fontFamily = 'LXGW ZhenKai';
            document.documentElement.style.fontWeight = 'normal';
        }
        /* 尝试从 CDN 加载样式表,如果失败,则调用回调函数 */
        a ('https://static.zeoseven.com/cn/2/main/result.css', function () {
        /* 当 CDN 不可用时直接由源服务器提供文件 */
        a ('https://static-host.zeoseven.com/cn/2/main/result.css');
        });
    })();
  • 扩展
  • 源服务器和 CDN 提供域的路径一致,可以用于一切具有 https://static.zeoseven.com 的路径,都可以修改为 https://static-host.zeoseven.com 实现后备。

    # ZeoSeven 通过 Referer 回访看到的错误示例

  • 将 CSS 错误的使用 @font-face 引入
  • @font-face {
        font-family: "自定义名称";
        src: url('https://static.zeoseven.com/cn/2/main/result.css');
    }

    这将导致无法正确引入字体, @font-face 只能引入 ttf, otf, eot, woff, woof2 等字体源文件, CSS 文件需要使用 link 标签或 @import 引入。

  • 按需加载的痛
  • @font-face {font-family: "自定义名称";src:local("自定义名称"),url("https://static.zeoseven.com/cn/2/main/0601a1cb4a9f56b374f91d612855ddad.woff2") format("woff2");font-style: normal;font-weight: 400;font-display: swap;}
    @font-face {font-family: "自定义名称";src:local("自定义名称"),url("https://static.zeoseven.com/cn/2/main/5e12300c47a34e65160bae82763f87e6.woff2") format("woff2");font-style: normal;font-weight: 400;font-display: swap;}
    /* 此处省略很多 @font-face */
    html {
        font-family: "自定义名称";
    }

    当我看到这样的引入方式时,我首先认为站长实际上非常有耐心,愿意去修改 url 和 font-family 并同时去除 unicode-range 字符集定义,但这当然可以正确引入,但是加载了所有字体源文件,这导致了按需加载直接失效。如果说要加载所有字体源文件, ZeoSeven 其实可以直接提供完整的 WOFF2 文件,而直接复制字体详情页的 CSS 代码才是最佳实践。

    # 旧的 API 域修改到新的专用域

    旧的 api.zeoseven.com 域因为子域很特殊,也不知道我之前怎么想的,将 CDN 提供域设置在 api.zeoseven.com/zsft/ ,当然,趁现在使用者并不多,抓紧修改到专用域。

    要嵌入的字体编号
    2 (中文)https://api.zeoseven.com/zsft/cn/2/main/result.csshttps://static.zeoseven.com/cn/2/main/result.css
    ai (英文)https://api.zeoseven.com/zsft/en/ai/main.woff2https://static.zeoseven.com/en/ai/main.woff2

    具体:去除了 /zsft/ 也就是,将 api.zeoseven.com 修改为 static.zeoseven.com 之后,也需要删除 /zsft/ 这一段,其余不变。

    # 字体收录规则

  • 字重定义
  • 字体文件在 10 MB 左右的大字库字体如果有多种字重, ZeoSeven 在服务器资源考虑下可能会只收录 Regular/400W 这一常规字重,可通过 font-weight 进行非原生字重调整,除非这类字体拥有 OpenType 字体变化 特性, ZeoSeven 除分包和转换格式,不会改变字体文件本身,所以 ZeoSeven 更鼓励多字重字体的设计师采用 OpenType 的高级特性 Variable Fonts (VF) ,虽然这明显需要更多的工作量和时间的同时需要设计师有着更现代的字体设计知识,但这的确可以让字体文件体积成倍缩小,并且集中到 1 个字体文件中,更流畅的使用任意原生字重,当然,也利于 CDN 分发和用户嵌入字体的体验。


    ZeoSeven 发现即便收录了近 300 款中文字体后仍有较大的空间来存储源,这证明之前 ZeoSeven 的平均化每个字体的占用的考虑并非维持可持续发展,而是在阻拦可持续发展,并且是错误的推断,现在已经弃用了 字重定义 并逐步补全曾经受到此限制的字体。

  • 详情页定义
  • 最初,我将字重独立出来一个编号,对应一个详情页,就像是, XX字体 Bold 的编号是 1 ,而 XX字体 Light 的编号是 2 ,之后就出现了问题,(发动无中生友)因为我有个朋友,会认为这款字体只有这一种字重,其它字重也不会去主动使用查找功能, BETA 版本的查找功能并不成熟,甚至不支持匹配作者的全部字体,所以,思源宋体就是很好的例子,正式的收录规则如下:

  • 思源宋体有很多版本,其中就有 TCSC ,并且每个版本都有 7 种字重,按照曾经的收录规则,它们两个的编号是 1-14 共 14 个详情页,但新的收录规则只需要 2 个详情页,对应 TC 和 SC 。
  • 如 Bold, Light, Medium, Italic 这样的,粗、细、中、斜 等以及其它字重,都会在一个字体详情页中并且只分配一个编号。只要不是另一个版本,比如 Mono, p, 圆体变体, 更多或更少像素, 衍生字体 等以及其它版本字形不一的,就会分配独立的编号和独立的字体详情页。