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 sẽ đi sâu vào phông chữ dự phòng và các API size-adjust, ascent-override, descent-overrideline-gap-override. Các API này cho phép bạn sử dụng phông chữ cục bộ để tạo phông chữ dự phòng khớp hoặc khớp chính xác với kích thước của phông chữ trên 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ụ mà 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ơ chế ghi đè chỉ số phông chữ và size-adjust để cung cấp các 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ác chỉ số phông chữ ghi đè 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 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ể sử dụng phông chữ dự phòng để hiển thị văn bản nhanh hơn (tức là bằng cách sử dụng font-display: swap). Nhờ đó, 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 đã gây ra sự bất ổn 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ữ 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ử dụng cả API ghi đè chỉ số phông chữ 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

Các cơ chế ghi đè chỉ số phông chữ cung cấp cách ghi đè độ cao, độ dốc 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ở.
  • Độ phân giải gốc đo khoảng cách xa nhất mà 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 được gọi là "hàng đầu", đo lường 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 cơ chế ghi đè chỉ số phông chữ để ghi đè độ cao, khoảng cách của phông chữ gốc và khoảng cách dòng của phông chữ dự phòng cho phù hợp với độ lên, xuống 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 đã điều chỉnh sẽ luôn có cùng kích thước theo chiều dọc.

Các chỉ số phông chữ ghi đè được sử dụng trong một tệp đị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 toán 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 lấy từ siêu dữ liệu của phông chữ 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 Thông tin phông chữ trong FontForge. Hộp thoại hiển thị các chỉ số về phông chữ như "Kiểu chữ in trên Google", "Kiểu chữ in" và "Khoảng trống dòng đánh máy".
Sử dụng FontForge để xem siêu dữ liệu phông chữ

Sau đâ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 (Kích thước phông chữ) là một thư viện bố cục và định cỡ phông chữ. Capsize cung cấp một API để lấy thông tin về nhiều chỉ số phông chữ.
  • fontdrop.info là một trang web cho phép bạn xem bảng phông chữ và các thông tin khác liên quan đến phông chữ từ 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 hầu hết phông chữ (ví dụ: ~90% phông chữ do Google Fonts lưu trữ), bạn có thể sử dụng tính năng 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 các phông chữ này, giá trị của 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 bạn đang sử dụng phông chữ yêu cầu sử dụng các nhóm 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 các ghi đè chỉ số phông chữ và size-adjust nếu có thể thay đổi các kiểu phông chữ 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 chỉ số ghi đè phông chữ được tính toán bằng cách sử dụng các phép đo từ siêu dữ liệu của phông chữ web (chứ không phải phông chữ dự phòng), nên các chỉ số này sẽ không thay đổi bất kể phông chữ nào được 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

Phần mô tả CSS size-adjust điều chỉnh chiều rộng và chiều cao của ký tự phông chữ theo tỷ lệ tương ứng. 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ác chỉ số phông chữ ghi đè cho phép bạn tạo hai phông chữ khớp với nhau cả theo 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

Nói chung, chiều rộng ký tự trung bình chỉ có thể gần đúng. Tuy nhiên, có một số trường hợp có thể tính chính xác giá trị này: ví dụ như khi sử dụng phông chữ đơn sắc hoặc khi biết trước nội dung của chuỗi văn bản.

Ví dụ về phương pháp đơn thuầ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à một tài liệu tham khảo phù hợp về tần suất viết chữ và độ dài trung bình của từ trong 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 phương pháp tiếp cận

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ả các thay đổi 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ó bất kỳ phản hồi nào về trải nghiệm của mình khi sử dụng các chế độ ghi đè chỉ số phông chữ và size-adjust.