• CSS – Font Family


    前言

    font-family 虽然只是一个 CSS 属性, 但是牵连许多东西, 所以独立一篇来讲.

    网站一般上会使用 Google Fonts 作为 font-family, 下面会以一个 Google Fonts 为例子. 逐步解析它背后的 CSS 知识.

    Pick a Google Font

    到官网 fonts.google.com, 随便选一个 font 作为 font-family.

    我选了 material 的 Roboto.

    Select font-style and font-weight

    知识点

    1. 不是每个字体都有支持 Italic

    2. 不是每个字体都支持 100 – 900 的 weight

    3. 网站有使用到的才选择. 每一个 style 和 weight 都是一份字体文件, 下载越多越慢.

    4. 常用的 weight 300, 400, 500, 700, Italic 尽量就别用了

    作为示范, 我选了 normal 300, 400, 500, 700 和 Italic 400

    右边点击 select, 就可以看见 selected 的 style 和 weight 了

    Import CSS

    它有 2 种 import 的 way.

    第一是在 HTML 放 <link>

    第二是在 CSS 放 @import, 我个人喜好是用这个

    它其实就是一个去加载 CSS 的 URL

    知识点

    1. 以前是 css, 现在是 css2 版本不同了, Google 对字体做了一次改版, 如果你切换到 css 会拿到旧版本的字体

    2. selected font-style

    3. selcted font-weight

    4. font-display 这个下面会详解讲它的作用.

    如果有多个字体的话, 它的 URL 长这样

    我加多了一个字体 Open Sans, 没有什么特别的. 只是 query param 多了 1 set family 而已 (相同 query param key 不常见, 但其实是符合规范的. 题外话: ASP.NET Core 获取 same query param key)

    Set font-family Style

    下方有声明如何使用在 Style

    sans-serif 是 Roboto 的 fallback 字体.

    效果

    Import 的 CSS 做了什么?

    上面有一个关键就是 Import CSS, 它做了啥?

    用 DevTools 可以看到, 它加载了一个 CSS Style, 里面有 @font-face

    @font-face

    @font-face 是 CSS 语法. 用来 define 一个字体. 来看看它的属性.

    @font-face {
      font-family: 'Roboto';
      font-style: italic;
      font-weight: 400;
      font-display: swap;
      src: url(https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2) format('woff2');
      unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
    }

    font-family, style, weight 就不多说了.

    src 

    字体文件 URL. 之前在 W3Schools 学习笔记 (3) – CSS Web Fonts 中有提过.

    字体要渲染需要 TTF/OTF, WOFF 或者 WOFF2 文件.

    所以, @font-face 只是定义了加载路径, 游览器会依据这个路径再去加载字体文件, 才能渲染.

    另外, Google Fonts 是可以 self host 的哦, 通过 google-webfonts-helper 下载字体, 或者到官网下载 (but 官网的是 TTF, helper 是 WOFF2), 然后把 .woff2 或 .ttf 文件放到自己 server, src 改成 link to 自己 server 路径就可以了.

    font-display

    参考:

    页面字体闪一下?这两个标准能帮到你

    CSS-Tricks – font-display

    它有好几个值

    auto: 依据游览器行为, 一般是 block

    block: 上面说了游览器需要加载 .woff 文件, 这段期间字体要如何展现呢? 

    block 就是不显示. 直接给一个白色, 完全看不到字, 直到字体下载完成渲染后才显示. 这个体验叫 FOIT (Flash Of Invisible Text), 很少人这样做的, 体验不好

    swap: 在等待加载的时候, 先显示 fallback 字体, 等加载完成才显示最终字体. 这个体验叫 FOUT (Flash Of Unstyled Text), 大部分人都这样做 (虽然体验也不是 100% 的好)

    fallback: block 和 swap 的折中方案, 会先 block 100ms 左右, 然后 3秒 swap, 如果 3 秒后还没有加载成功, 那么就一直用 fallback 的. 考虑到 3 秒后用户已经开始阅读内容了, 这时切换字体会很明显跳一下, 体验扣很多分

    optional: 和 fallback 类似. 只是把权力交给游览器依据下载速度决定是否去加载字体.

    block, swap, fallback, optional 可以理解为你多在意自定义字体. block 就是一定要用自定义字体, 其它的连看都不可以. swap 就是可以先看 fallback 但最后一定要看到自定义

    fallback 就不一定要看到自定义, 加载快才看. optional 顾名思义, 更加不注重了. 大部分人都会用 swap.

    unicode-range 没有认真研究. 从 Google Fonts 的 @font-face 可以看到, 同一个 family, style, weight 会有很多版本的 unicode-range.

    提醒:

    不同 font-family, 不同 style, 不同 weight, 不同 unicode 都需要新的一个 @font-face 哦. 所以 @font-face 会有很多很多的.

    CSS Font Loading API

    参考:

    stackoverflow – How to be notified once a web font has loaded

    Medium – Getting started with CSS Font Loading

    上面说到, @font-face 定义了 .woff2 的加载路径, 然后游览器去加载文件后渲染.

    font-display swap 会先显示 fallback 的字体, 然后切换, 所以字体的 size 会改变.

    如果我们依赖这个字体的 width 怎么办呢? 虽然可以用 ResizeObserver 监听, 但它不是最好的. 更好的是用 document.fonts

    document.fonts 是一个 iterable 对象. 它记入了所以 @font-face 的内容.

    for (const font of document.fonts) {
      console.log("font", font);
    }

    遍历后可以看到所以 @font-face 定义的字体

    下面 2 个监听方式

    document.fonts.ready.then(() => {
      console.log("all loaded");
    });
    
    [...document.fonts][0].loaded.then(() => {
      console.log("specify font loaded");
    });

    第一个是监听所以 font 加载完毕

    第二个是指定某一个 font 加载完毕

    JS 动态加载 font-face

    上面都是靠 CSS @font-face 去加载的. JavaScript 也是有 API 可以动态加载 font 的哦.

    注释 CSS

    /*
      @font-face {
        font-family: "Roboto";
        font-style: normal;
        font-weight: 400;
        font-display: swap;
        src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2)
          format("woff2");
        unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
          U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
          U+FEFF, U+FFFD;
      }
    */

    JavaScript

    document.querySelector("button")!.addEventListener("click", () => {
      // define
      const robotoFontFace = new FontFace(
        "Roboto",
        `url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2)
      format("woff2")`,
        {
          display: "swap",
          style: "normal",
          weight: "400",
          unicodeRange: `U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
          U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
          U+FEFF, U+FFFD`,
        }
      );
    
      // load
      robotoFontFace.load().then(() => {
        // add to document.fonts
        document.fonts.add(robotoFontFace);
    
        // set style
        document.querySelector("h1")!.style.fontFamily = `Roboto`;
      });
    });

    new FontFace 类似 CSS 的 @font-face. 照搬而已.

    定义好 FontFace 把它添加到 document.fonts 里面去. 然后就可以使用了.

    我上面调用 load 只是一个示范而已. 其实只要添加进了 document.fonts 它就会自动去加载了.

    和 font-family 有关的文章

    Figma 学习笔记 – Text

    webpack – postcss-font-magician

    总结

    1. font-family 需要 .woff2 文件 (.woff2 文件就是 font 的设计文档, 有些是版权的哦, 不可以随便用)

    2. CSS Style @font-face 只定义了加载路径

    3. 游览器加载 font 时, font-display 控制体验

    4. JS 也有 API 可以设置 font-face 和监听 font rendered.

  • 相关阅读:
    怎么分辨是eclipse还是 android studio开发的
    一个帖子学会Android开发四大组件
    Android Studio ADB响应失败解决方法
    500 OOPS: could not read chroot() list file:/etc/vsftpd/chroot_list
    理解 with递归调用 Sqlserver 树查询
    SQLServer树查询
    数字证书原理【转】
    linux 基础命令
    项目经验分享[转自min.jiang]
    ios
  • 原文地址:https://www.cnblogs.com/keatkeat/p/16365081.html
Copyright © 2020-2023  润新知