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 giúp bạn có thể 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ỏ những thay đổi về bố cục do hoán đổi phông chữ.

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ơ 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 biểu định kiểu mà ứng dụng Nuxt của bạn sử dụng.

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

  • Fontaine: Fontaine là một thư viện tự động tạo và chèn các phông chữ dự phòng sử dụng cơ chế ghi đè chỉ số phông chữ.
  • 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à phông chữ được dùng khi phông chữ chính chưa được tải hoặc thiếu hình tượng khắc cần thiết để hiển thị nội dung trang. Ví dụ: CSS bên dưới cho biết rằng bộ phông chữ sans-serif nên được sử dụng 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 dưới đây có thể giảm bớt hoặc loại bỏ vấn đề này bằng cách cho phép tạo các kiểu phông chữ dự phòng chiếm cùng một lượng không gian so với phông chữ trên web.

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

Có hai cách tiếp cận có thể áp dụng để tạo phông chữ dự phòng "cải thiện". Phương pháp đơn giản hơn chỉ sử dụng chỉ số phông chữ ghi đè API. 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

Cơ chế ghi đè chỉ số phông chữ là cách ghi đè độ cao, độ sâu và khoảng cách dòng của phông chữ:

  • Độ cao đo khoảng cách xa nhất mà ký tự của phông chữ mở rộng phía trên đường cơ sở.
  • Độ 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, độ thấp và khoảng cách của phông chữ.

Bạn có thể sử dụng cơ chế ghi đè chỉ số phông chữ để ghi đè độ cao, độ giãn 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ữ trên 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.

Đang tính toán ghi đè chỉ số phông chữ

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 phải viết các giá trị của cơ chế ghi đè chỉ số phông chữ dưới dạng tỷ lệ 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ụ: dưới đây là ghi đè chỉ số phông chữ 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 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"", "Kiểu chữ in" và "Khoảng trống dòng đánh máy".
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 (Kích thước phông chữ) 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: mở hộp thoại Font Info, chọn trình đơn OS/2, sau đó chọn thẻ Metrics. Để xem UPM: mở hộp thoại Font Info, rồi 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 các hệ điều hành khác nhau sử dụng các phương pháp hiển thị 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 được 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 "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".
Firefox Sử dụng các chỉ số từ bảng "typo" nếu bạn đã đặt "USE_TYPO_METRICS", nếu không thì 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 "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".

Để biết thêm thông tin về cách hoạt động của chỉ số phông chữ trên các hệ điều hành, hãy xem bài viết này về chỉ số ngành 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ống hệt nhau 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

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% tăng tỷ lệ ký tự phông chữ lên gấp đôi kích thước ban đầu; size-adjust: 50% tăng tỷ lệ ký tự phông chữ lên một nửa kích thước ban đầu.

Biểu đồ cho thấy kết quả của việc sử dụng các thuộc tính "size-adjust: 50%" và "size-adjust: 200%".

Bản thân size-adjust có một số ứng dụng giới hạn để 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ữ trên 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.

Đây là cách size-adjust được sử dụng trong biểu định 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 phần ghi đè chỉ số phông chữ tương ứng) sẽ thay đổi tuỳ thuộc vào phông chữ dự phòng nào đượ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 điều chỉnh kích thước và ghi đè chỉ số phông chữ

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

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)

Hầu hết các thông tin đầu vào này (tức là độ cao, độ thấp và khoảng cách dòng) đều có thể đọc được trực tiếp từ siêu dữ liệu của phông chữ trên web. Tuy nhiên, avgCharacterWidth cần phải được tính gần đúng.

Chiều rộng gần đúng của 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 Roboto Daggers

Tuy nhiên, việc sử dụng trọng số cho tất cả các ký tự như nhau có thể sẽ làm giảm trọng số chiều rộng của các chữ cái thường dùng (ví dụ: e) và sẽ tạo quá tải trọng số cho chiều rộng của các chữ cái ít khi được sử 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à xem xét tần suất của chữ cái, rồi tính toán độ rộng trung bình có trọng số theo tần suất là [a-z\s] ký tự. 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 viết chữ cái bằng tiếng Anh.
Tần suất thư bằng tiếng Anh

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

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

  • Việc tự ghi đè chỉ số phông chữ là một phương pháp hay để sử dụng nếu bạn bắt đầu tối ưu hóa các tính năng dự phòng phông chữ. Mặc dù trong 2 phương pháp này đơn giản hơn nhưng thường đủ 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 có độ chính xác cao hơn và sẵn sàng thực hiện nhiều thao tác cũng như kiểm thử hơn, thì bạn nên kết hợp size-adjust. 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ữ trên thiết bị, điều quan trọng cần lưu ý là rất ít phông chữ có thể sử dụng trên diện rộng trên thiết bị và sẽ không có một phông chữ nào 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, cả hai phông chữ này đều không 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 mức độ phù hợp của thiết bị rộng: 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.