Cải thiện tính năng dự phòng phông chữ

Katie Hempenius
Katie Hempenius

Tóm tắt

Bài viết này trình bày chi tiết về phông chữ dự phòng cũng như các API size-adjust, ascent-override, descent-overrideline-gap-override. Các API này cho phép sử dụng phông chữ cục bộ để tạo mặt phông chữ dự phòng khớp gần như chính xác hoặc chính xác với kích thước của phông chữ web. Điều này giúp giảm hoặc loại bỏ sự thay đổi bố cục do việc hoán đổi phông chữ gây ra.

Nếu bạn muốn bỏ qua việc đọc bài viết này, dưới đây là một số công cụ bạn có thể sử dụng để bắt đầu sử dụng các API này ngay lập tức:

Công cụ khung:

  • @next/font: Kể từ Next 13, next/font sẽ tự động sử dụng các chỉ số ghi đè phông chữ và size-adjust để cung cấp phông chữ dự phòng phù hợp.
  • @nuxtjs/fontaine: Kể từ Nuxt 3, bạn có thể sử dụng nuxt/fontaine để tự động tạo và chèn phông chữ dự phòng phù hợp vào các tệp định kiểu mà ứng dụng Nuxt sử dụng.

Công cụ không phải khung:

  • Fontaine: Fontaine là một thư viện tự động tạo và chèn phông chữ dự phòng sử dụng các chỉ số phông chữ ghi đè.
  • Kho lưu trữ này chứa cơ chế ghi đè chỉ số phông chữ cho tất cả phông chữ do Google Fonts lưu trữ. Bạn có thể sao chép và dán các giá trị này vào biểu định kiểu của mình.

Thông tin khái quát

Phông chữ dự phòng là một kiểu phông chữ được dùng khi kiểu phông chữ chính chưa được tải hoặc thiếu ký tự cần thiết để hiển thị nội dung trang. Ví dụ: CSS bên dưới cho biết bạn nên sử dụng bộ phông chữ sans-serif làm phông chữ dự phòng cho "Roboto".

font-family: "Roboto" , sans-serif;

Bạn có thể dùng phông chữ dự phòng để hiển thị văn bản nhanh hơn (nghĩa là sử dụng font-display: swap). Do đó, nội dung trang có thể đọc được và hữu ích sớm hơn — tuy nhiên, trước đây, điều này sẽ phải đánh đổi sự không ổn định về bố cục: sự thay đổi bố cục thường xảy ra khi phông chữ dự phòng được hoán đổi cho phông chữ trên web. Tuy nhiên, các API mới được thảo luận bên dưới có thể làm giảm hoặc loại bỏ vấn đề này bằng cách cho phép tạo phông chữ dự phòng chiếm cùng một không gian với phông chữ web tương ứng.

Cải thiện tính năng dự phòng phông chữ

Có hai phương pháp có thể dùng để tạo phông chữ dự phòng "cải tiến". Phương pháp đơn giản hơn chỉ sử dụng API ghi đè chỉ số phông chữ. Phương pháp phức tạp hơn (nhưng mạnh mẽ hơn) sẽ sử dụng cả chỉ số phông chữ sẽ ghi đè API và size-adjust. Bài viết này giải thích cả hai phương pháp này.

Cách hoạt động của cơ chế ghi đè chỉ số phông chữ

Giới thiệu

Chế độ ghi đè chỉ số phông chữ cung cấp cách ghi đè độ cao, độ cao và khoảng cách dòng của phông chữ:

  • Chiều cao đo khoảng cách xa nhất mà các ký tự của phông chữ mở rộng phía trên đường cơ sở.
  • Độ dốc đo khoảng cách xa nhất mà các ký tự của phông chữ mở rộng bên dưới đường cơ sở.
  • Khoảng cách dòng (còn gọi là "khoảng cách dòng đầu") đo khoảng cách giữa các dòng văn bản liên tiếp.

Sơ đồ mô tả độ cao, độ dốc và khoảng cách dòng của phông chữ.

Bạn có thể sử dụng thuộc tính ghi đè chỉ số phông chữ để ghi đè độ cao, độ dốc và khoảng cách dòng của phông chữ dự phòng cho phù hợp với độ cao, độ dốc và khoảng cách dòng của phông chữ web. Do đó, phông chữ web và phông chữ dự phòng được điều chỉnh sẽ luôn có cùng kích thước dọc.

Ghi đè chỉ số phông chữ được sử dụng trong biểu định kiểu như sau:

body {
    font-family: Poppins, "fallback for poppins";
}

@font-face {
    font-family: "fallback for poppins";
    src: local("Times New Roman");
    ascent-override: 105%;
    descent-override: 35%;
    line-gap-override: 10%;
}

Các công cụ được liệt kê ở đầu bài viết này có thể tạo ra các giá trị ghi đè chỉ số phông chữ chính xác. Tuy nhiên, bạn cũng có thể tự tính các giá trị này.

Tính toán các chỉ số phông chữ ghi đè

Các phương trình sau đây tạo ra cơ chế ghi đè chỉ số phông chữ cho một phông chữ nhất định trên web. Bạn nên viết các giá trị ghi đè chỉ số phông chữ dưới dạng phần trăm (ví dụ: 105%) thay vì số thập phân.

ascent-override = ascent/unitsPerEm
descent-override = descent/unitsPerEm
line-gap-override = line-gap/unitsPerEm

Ví dụ: đây là các chỉ số phông chữ ghi đè cho phông chữ Poppins:

/*
Poppins font metrics:
ascent = 1050
descent = 350
line-gap = 100
UPM: 1000
*/

ascent-override: 105%;  /* = 1050/1000 */
descent-override: 35%;  /* = 350/1000 */
line-gap-override: 10%; /* = 100/1000 */

Các giá trị của ascent, descent, line-gapunitsPerEm đều được lấy từ siêu dữ liệu của phông chữ trên web. Phần tiếp theo của bài viết này giải thích cách lấy các giá trị này.

Đọc bảng phông chữ

Siêu dữ liệu của phông chữ (cụ thể là bảng phông chữ) chứa tất cả thông tin mà bạn cần để tính toán các giá trị ghi đè chỉ số phông chữ.

Ảnh chụp màn hình hộp thoại Font Information (Thông tin phông chữ) trong FontForge. Hộp thoại này hiển thị các chỉ số phông chữ như "Typo Ascent" (Độ cao của kiểu chữ), "Typo Descent" (Độ dốc của kiểu chữ) và "Typo Line Gap" (Khoảng cách giữa các dòng của kiểu chữ).
Sử dụng FontForge để xem siêu dữ liệu về phông chữ

Dưới đây là một số công cụ bạn có thể sử dụng để đọc siêu dữ liệu của phông chữ:

  • fontkit là một công cụ phông chữ được tạo cho Node.js. Đoạn mã này cho biết cách sử dụng bộ phông chữ để tính toán ghi đè chỉ số phông chữ.
  • Capsize là một thư viện bố cục và định cỡ phông chữ. Kích thước cung cấp API để nhận thông tin về nhiều chỉ số phông chữ.
  • fontdrop.info là một trang web cho phép bạn xem các bảng phông chữ và các thông tin khác liên quan đến phông chữ trên trình duyệt.
  • Font Forge là một trình chỉnh sửa phông chữ phổ biến trên máy tính. Để xem ascent, descentline-gap: hãy mở hộp thoại Font Info, chọn trình đơn OS/2, sau đó chọn thẻ Metrics. Để xem UPM: hãy mở hộp thoại Font Info, sau đó chọn trình đơn General.

Tìm hiểu về bảng phông chữ

Bạn có thể nhận thấy rằng các khái niệm như "độ lên" được đề cập đến qua nhiều chỉ số, ví dụ: có các chỉ số hheaAscent, typoAscentwinAscent. Đây là kết quả của việc các hệ điều hành sử dụng các phương pháp kết xuất phông chữ khác nhau: các chương trình trên thiết bị OSX thường sử dụng chỉ số phông chữ hhea*, trong khi các chương trình trên thiết bị Windows thường sử dụng chỉ số phông chữ typo* (còn gọi là sTypo*) hoặc win*.

Tuỳ thuộc vào phông chữ, trình duyệt và hệ điều hành, phông chữ sẽ hiển thị bằng các chỉ số hhea, typo hoặc win.

Mac Windows
Chromium Sử dụng các chỉ số từ bảng "hhea". Sử dụng các chỉ số từ bảng "typo" nếu bạn đã đặt "USE_TYPO_METRICS", nếu không, hãy sử dụng các chỉ số từ bảng "win".
Firefox Sử dụng các chỉ số từ bảng "typo" nếu bạn đã đặt "USE_TYPO_METRICS", nếu không, hãy sử dụng các chỉ số từ bảng "hhea". Sử dụng các chỉ số từ bảng "tiêu chuẩn" nếu bạn đã đặt "USE_TYPO_METRICS", nếu không thì sử dụng các chỉ số từ bảng "giành chiến thắng".
Safari Sử dụng các chỉ số từ bảng "hhea". Sử dụng các chỉ số từ bảng "typo" nếu bạn đã đặt "USE_TYPO_METRICS", nếu không, hãy sử dụng các chỉ số từ bảng "win".

Để biết thêm thông tin về cách hoạt động của các chỉ số phông chữ trên các hệ điều hành, hãy xem bài viết này về các chỉ số dọc.

Khả năng tương thích trên nhiều thiết bị

Đối với phần lớn phông chữ (ví dụ: ~90% phông chữ do Google Fonts lưu trữ), bạn có thể sử dụng chế độ ghi đè chỉ số phông chữ một cách an toàn mà không cần biết hệ điều hành của người dùng: nói cách khác, đối với những phông chữ này, các giá trị ascent-override, descent-overridelinegap-override vẫn giữ nguyên bất kể chỉ số hhea, typo hay win có áp dụng hay không. Kho lưu trữ này cung cấp thông tin về việc chấp nhận và không áp dụng phông chữ này.

Nếu đang sử dụng phông chữ yêu cầu sử dụng các tập hợp ghi đè chỉ số phông chữ riêng biệt cho thiết bị OSX và Windows, bạn chỉ nên sử dụng ghi đè chỉ số phông chữ và size-adjust nếu có thể thay đổi biểu định kiểu của mình dựa trên hệ điều hành của người dùng.

Sử dụng ghi đè chỉ số phông chữ

Vì các cơ chế ghi đè chỉ số phông chữ được tính toán bằng cách sử dụng các phép đo đến từ siêu dữ liệu của phông chữ trên web (chứ không phải phông chữ dự phòng), nên các chế độ ghi đè chỉ số phông chữ vẫn giữ nguyên bất kể phông chữ nào được sử dụng làm phông chữ dự phòng. Ví dụ:

body {
  font-family: "Poppins", "fallback for Poppins", "another fallback for Poppins";
}

@font-face {
  font-family: "fallback for Poppins";
  src: local("Arial");
  ascent-override: 105%;
  descent-override: 35%;
  line-gap-override: 10%;
}

@font-face {
  font-family: "another fallback for Poppins";
  src: local("Roboto");
  ascent-override: 105%;
  descent-override: 35%;
  line-gap-override: 10%;
}

Cách hoạt động của tính năng điều chỉnh kích thước

Giới thiệu

Chỉ số mô tả CSS size-adjust điều chỉnh tỷ lệ chiều rộng và chiều cao của các ký tự phông chữ. Ví dụ: size-adjust: 200% điều chỉnh tỷ lệ phông chữ thành gấp đôi kích thước ban đầu; size-adjust: 50% điều chỉnh tỷ lệ phông chữ thành một nửa kích thước ban đầu.

Sơ đồ cho thấy kết quả của việc sử dụng "size-adjust: 50%" và "size-adjust: 200%".

Bản thân size-adjust có các ứng dụng hạn chế để cải thiện phông chữ dự phòng: trong hầu hết các trường hợp, phông chữ dự phòng cần được thu hẹp hoặc mở rộng một chút (thay vì điều chỉnh theo tỷ lệ) để khớp với phông chữ web. Tuy nhiên, việc kết hợp size-adjust với cơ chế ghi đè chỉ số phông chữ giúp bạn có thể làm cho 2 phông chữ bất kỳ khớp với nhau cả chiều ngang và chiều dọc.

Sau đây là cách sử dụng size-adjust trong các tệp kiểu:

@font-face {
  font-family: "fallback for poppins";
  src: local("Arial");
  size-adjust: 60.85099821%;
  ascent-override: 164.3358416%;
  descent-override: 57.51754455%;
  line-gap-override: 16.43358416%;
}

Do cách tính size-adjust (được giải thích trong phần tiếp theo), giá trị của size-adjust (và các chỉ số phông chữ tương ứng sẽ ghi đè) thay đổi tuỳ thuộc vào phông chữ dự phòng được sử dụng:

body {
  font-family: "Poppins", "fallback for Poppins", "another fallback for Poppins";
}

@font-face {
  font-family: poppins-fallback;
  src: local("Arial");
  size-adjust: 60.85099821%;
  ascent-override: 164.3358416%;
  descent-override: 57.51754455%;
  line-gap-override: 16.43358416%;
}

@font-face {
  font-family: poppins-fallback-android;
  src: local("Roboto");
  size-adjust: 55.5193474%:
  ascent-override: 180.1173909%;
  descent-override: 63.04108683%;
  line-gap-override: 18.01173909%;
}

Tính toán các chỉ số ghi đè về điều chỉnh kích thước và phông chữ

Sau đây là các phương trình để tính toán size-adjust và các chỉ số phông chữ được ghi đè:

size-adjust = avgCharacterWidth of web font / avgCharacterWidth of fallback font
ascent-override = web font ascent / (web font UPM * size-adjust)
descent-override = web font descent / (web font UPM * size-adjust)
line-gap-override = web font line-gap / (web font UPM * size-adjust)

Bạn có thể đọc trực tiếp hầu hết các dữ liệu đầu vào này (tức là độ cao, độ dốc và khoảng cách dòng) từ siêu dữ liệu của phông chữ web. Tuy nhiên, bạn cần phải ước chừng avgCharacterWidth.

Xác định gần đúng chiều rộng ký tự trung bình

Nhìn chung, bạn chỉ có thể ước chừng chiều rộng ký tự trung bình, nhưng có một số trường hợp bạn có thể tính toán chính xác chiều rộng này: ví dụ: khi sử dụng phông chữ một kiểu hoặc khi biết trước nội dung của một chuỗi văn bản.

Ví dụ về phương pháp đơn giản để tính avgCharacterWidth là lấy chiều rộng trung bình của tất cả ký tự [a-z\s].

 Biểu đồ so sánh chiều rộng của từng ký tự Roboto [a-zs].
Chiều rộng của ký tự Roboto

Tuy nhiên, việc cân bằng tất cả các ký tự có thể sẽ làm giảm chiều rộng của các chữ cái thường dùng (ví dụ: e) và làm tăng chiều rộng của các chữ cái ít dùng (ví dụ: z).

Một phương pháp phức tạp hơn giúp cải thiện độ chính xác là tính đến tần suất chữ cái và tính chiều rộng trung bình theo trọng số tần suất của các ký tự [a-z\s]. Bài viết này là tài liệu tham khảo hữu ích về tần suất chữ cái và độ dài từ trung bình của văn bản tiếng Anh.

Biểu đồ cho thấy tần suất xuất hiện chữ cái trong tiếng Anh.
Tần suất chữ cái trong tiếng Anh

Chọn một phương pháp

Hai phương pháp được thảo luận trong bài viết này đều có ưu và nhược điểm riêng:

  • Bạn nên sử dụng tính năng ghi đè chỉ số phông chữ nếu mới bắt đầu tối ưu hoá phông chữ dự phòng. Mặc dù đây là phương pháp đơn giản hơn trong hai phương pháp, nhưng thường thì phương pháp này đủ mạnh để giảm đáng kể mức độ thay đổi bố cục liên quan đến phông chữ.

  • Mặt khác, nếu bạn muốn độ chính xác cao hơn và sẵn sàng làm thêm một chút công việc và kiểm thử, thì việc kết hợp size-adjust là một phương pháp hay để sử dụng. Khi được triển khai đúng cách, phương pháp này có thể loại bỏ hiệu quả việc dịch chuyển bố cục liên quan đến phông chữ.

Chọn phông chữ dự phòng

Các kỹ thuật được mô tả trong bài viết này dựa vào việc sử dụng cơ chế ghi đè chỉ số phông chữ và size-adjust để chuyển đổi các phông chữ cục bộ có sẵn rộng rãi – thay vì cố gắng tìm phông chữ cục bộ gần đúng với phông chữ trên web. Khi chọn phông chữ cục bộ, điều quan trọng là bạn phải lưu ý rằng rất ít phông chữ có sẵn trên nhiều thiết bị và không có phông chữ nào tồn tại trên tất cả thiết bị.

Arial là phông chữ dự phòng được đề xuất cho phông chữ sans-serif và Times New Roman là phông chữ dự phòng được đề xuất cho phông chữ serif. Tuy nhiên, không có phông chữ nào trong số này có trên Android (Roboto là phông chữ hệ thống duy nhất trên Android).

Ví dụ bên dưới sử dụng 3 phông chữ dự phòng để đảm bảo phạm vi sử dụng rộng rãi trên thiết bị: phông chữ dự phòng nhắm đến thiết bị Windows/Mac, phông chữ dự phòng nhắm đến thiết bị Android và phông chữ dự phòng sử dụng bộ phông chữ chung.

body {
  font-family: "Poppins", poppins-fallback, poppins-fallback-android, sans-serif;
}

/*
Poppins font metrics:
- ascent = 1050
- descent = 350
- line-gap = 100
- UPM: 1000
AvgCharWidth:
- Poppins: 538.0103768
- Arial: 884.1438804
- Roboto: 969.0502537
*/

@font-face {
  font-family: poppins-fallback;
  src: local("Arial");
  size-adjust: 60.85099821%;
  ascent-override: 164.3358416%;
  descent-override: 57.51754455%;
  line-gap-override: 16.43358416%;
}

@font-face {
  font-family: poppins-fallback-android;
  src: local("Roboto");
  size-adjust: 55.5193474%:
  ascent-override: 180.1173909%;
  descent-override: 63.04108683%;
  line-gap-override: 18.01173909%;
}

Yêu cầu phản hồi

Vui lòng liên hệ nếu bạn có ý kiến phản hồi về trải nghiệm sử dụng tính năng ghi đè chỉ số phông chữ và size-adjust.