Các phương pháp hay nhất về phông chữ

Tối ưu hoá phông chữ web cho Core Web Vitals.

Katie Hempenius
Katie Hempenius

Bài viết này thảo luận các phương pháp hay nhất về hiệu suất cho phông chữ. Có nhiều cách mà phông chữ trên web ảnh hưởng đến hiệu suất:

Bài viết này được chia thành ba phần: tải phông chữ, phân phối phông chữhiển thị phông chữ. Mỗi phần sẽ giải thích cách hoạt động của khía cạnh cụ thể đó trong vòng đời phông chữ và đưa ra các phương pháp hay nhất tương ứng.

Đang tải phông chữ

Phông chữ thường là tài nguyên quan trọng vì nếu không có phông chữ thì người dùng có thể không xem được nội dung trang. Do đó, các phương pháp hay nhất để tải phông chữ thường tập trung vào việc đảm bảo phông chữ được tải càng sớm càng tốt. Bạn nên đặc biệt chú ý đến các phông chữ được tải từ các trang web của bên thứ ba vì việc tải các tệp phông chữ này xuống cần phải thiết lập kết nối riêng biệt.

Nếu bạn không chắc liệu phông chữ trên trang của mình có được yêu cầu kịp thời hay không, hãy kiểm tra thẻ Thời gian trong bảng điều khiển Mạng trong Công cụ của Chrome cho nhà phát triển để biết thêm thông tin.

Ảnh chụp màn hình thẻ Timing trong Công cụ cho nhà phát triển

Tìm hiểu về @font-face

Trước khi tìm hiểu các phương pháp hay nhất để tải phông chữ, bạn cần hiểu cách hoạt động của @font-face và mức độ ảnh hưởng của chế độ này đến quá trình tải phông chữ.

Việc khai báo @font-face là một phần thiết yếu khi làm việc với mọi phông chữ trên web. Ở mức tối thiểu, tệp này sẽ khai báo tên sẽ được dùng để tham chiếu đến phông chữ và cho biết vị trí của tệp phông chữ tương ứng.

@font-face {
  font-family: "Open Sans";
  src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
}

Có một quan niệm sai lầm phổ biến là phông chữ được yêu cầu khi khai báo @font-face – điều này không đúng. Bản thân việc khai báo @font-face không kích hoạt việc tải phông chữ xuống. Thay vào đó, phông chữ chỉ được tải xuống khi phông chữ đó được tham chiếu theo kiểu được sử dụng trên trang. Chẳng hạn như sau:

@font-face {
  font-family: "Open Sans";
  src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
}

h1 {
  font-family: "Open Sans"
}

Nói cách khác, trong ví dụ trên, Open Sans sẽ chỉ được tải xuống nếu trang có chứa phần tử <h1>.

Do đó, khi suy nghĩ về việc tối ưu hoá phông chữ, điều quan trọng là bạn phải xem xét biểu định kiểu nhiều như chính các tệp phông chữ. Việc thay đổi nội dung hoặc phân phối biểu định kiểu có thể có tác động đáng kể đến thời điểm phông chữ xuất hiện. Tương tự, việc xoá CSS không dùng đến và chia tách biểu định kiểu có thể làm giảm số lượng phông chữ mà một trang tải.

Khai báo phông chữ cùng dòng

Hầu hết các trang web sẽ hưởng lợi rất nhiều từ việc khai báo phông chữ cùng dòng và kiểu quan trọng khác trong <head> của tài liệu chính thay vì đưa vào một biểu định kiểu bên ngoài. Điều này cho phép trình duyệt phát hiện các khai báo phông chữ sớm hơn vì trình duyệt không cần phải đợi tải biểu định kiểu bên ngoài xuống.

<head>
  <style>
    @font-face {
        font-family: "Open Sans";
        src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
    }

    body {
        font-family: "Open Sans";
    }

    ...etc.

  </style>
</head>

Việc chèn CSS quan trọng vào cùng dòng có thể là một kỹ thuật nâng cao hơn mà không phải trang web nào cũng có thể sử dụng được. Các lợi ích về hiệu suất rất rõ ràng, nhưng việc này đòi hỏi các quy trình và công cụ xây dựng bổ sung để đảm bảo CSS cần thiết và lý tưởng là chỉ CSS quan trọng được hiển thị chính xác và bất kỳ CSS bổ sung nào cũng được phân phối theo cách chặn không hiển thị.

Kết nối trước với các nguồn quan trọng của bên thứ ba

Nếu trang web của bạn tải phông chữ từ một trang web của bên thứ ba, thì bạn nên sử dụng preconnect gợi ý về tài nguyên để thiết lập(các) kết nối sớm với nguồn gốc của bên thứ ba. Bạn phải đặt gợi ý về tài nguyên trong <head> của tài liệu. Gợi ý về tài nguyên dưới đây thiết lập kết nối để tải biểu định kiểu phông chữ.

<head>
  <link rel="preconnect" href="https://fonts.com">
</head>

Để kết nối trước kết nối dùng để tải tệp phông chữ xuống, hãy thêm một gợi ý về tài nguyên preconnect riêng biệt sử dụng thuộc tính crossorigin. Không giống như biểu định kiểu, tệp phông chữ phải được gửi qua kết nối CORS.

<head>
  <link rel="preconnect" href="https://fonts.com">
  <link rel="preconnect" href="https://fonts.com" crossorigin>
</head>

Khi sử dụng gợi ý về tài nguyên preconnect, hãy lưu ý rằng trình cung cấp phông chữ có thể phân phát biểu định kiểu và phông chữ từ các nguồn gốc riêng biệt. Ví dụ: đây là cách dùng gợi ý về tài nguyên preconnect cho Google Fonts.

<head>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
</head>

Hãy thận trọng khi sử dụng preload để tải phông chữ

Mặc dù preload rất hiệu quả trong việc giúp người dùng dễ dàng tìm thấy phông chữ ở giai đoạn đầu quá trình tải trang, nhưng điều này sẽ khiến người dùng phải lấy đi tài nguyên trình duyệt khỏi việc tải các tài nguyên khác.

Nội tuyến khai báo phông chữ và điều chỉnh biểu định kiểu có thể là một phương pháp hiệu quả hơn. Những điều chỉnh này tiến gần hơn đến việc giải quyết nguyên nhân gốc rễ của các phông chữ phát hiện muộn – thay vì chỉ đưa ra giải pháp.

Ngoài ra, bạn cũng nên cẩn thận khi sử dụng preload làm chiến lược tải phông chữ vì chiến lược này bỏ qua một số chiến lược thương lượng nội dung tích hợp sẵn của trình duyệt. Ví dụ: preload bỏ qua nội dung khai báo unicode-range và nếu được sử dụng một cách thận trọng, thì bạn chỉ nên dùng để tải một định dạng phông chữ duy nhất.

Tuy nhiên, khi sử dụng biểu định kiểu bên ngoài, việc tải trước các phông chữ quan trọng nhất có thể rất hiệu quả vì trình duyệt sẽ không phát hiện liệu có cần phông chữ hay không cho đến sau này.

Phân phối phông chữ

Phân phối phông chữ nhanh hơn giúp hiển thị văn bản nhanh hơn. Ngoài ra, nếu phông chữ được phân phối đủ sớm, điều này có thể giúp loại bỏ sự thay đổi bố cục do hoán đổi phông chữ.

Sử dụng phông chữ tự lưu trữ

Trên giấy tờ, việc sử dụng phông chữ tự lưu trữ sẽ mang lại hiệu suất tốt hơn vì phông chữ này loại bỏ việc thiết lập kết nối với bên thứ ba. Tuy nhiên, trong thực tế, sự khác biệt về hiệu suất giữa 2 lựa chọn này ít rõ ràng hơn. Ví dụ: Niên giám web nhận thấy rằng các trang web sử dụng phông chữ của bên thứ ba có tốc độ hiển thị nhanh hơn so với phông chữ sử dụng phông chữ của bên thứ nhất.

Nếu bạn đang cân nhắc sử dụng phông chữ tự lưu trữ, hãy xác nhận rằng trang web của bạn đang dùng Mạng phân phối nội dung (CDN)HTTP/2. Nếu không sử dụng các công nghệ này, thì phông chữ tự lưu trữ sẽ ít có khả năng mang lại hiệu suất tốt hơn. Để biết thêm thông tin, hãy xem phần Mạng phân phối nội dung.

Nếu sử dụng phông chữ tự lưu trữ, bạn cũng nên áp dụng một số tính năng tối ưu hoá tệp phông chữ mà nhà cung cấp phông chữ của bên thứ ba thường cung cấp tự động, ví dụ: chế độ cài đặt phụ phông chữ và nén WOFF2. Mức độ nỗ lực cần thiết để áp dụng các tối ưu hoá này sẽ tuỳ thuộc một chút vào các ngôn ngữ mà trang web của bạn hỗ trợ. Cụ thể, xin lưu ý rằng việc tối ưu hoá phông chữ cho các ngôn ngữ CJK có thể đặc biệt khó khăn.

Sử dụng WOFF2

Trong số các phông chữ hiện đại, WOFF2 là phông chữ mới nhất, có hỗ trợ trình duyệt rộng nhất và mang lại khả năng nén tốt nhất. Vì sử dụng Brotli, WOFF2 nén tốt hơn 30% so với WOFF, dẫn đến ít dữ liệu tải xuống hơn và do đó hiệu suất nhanh hơn.

Do trình duyệt hỗ trợ, các chuyên gia hiện khuyên bạn chỉ nên sử dụng WOFF2:

Trên thực tế, chúng tôi cho rằng đã đến lúc tuyên bố: Chỉ sử dụng WOFF2 và quên mọi thứ khác.

Điều này sẽ giúp đơn giản hoá CSS và quy trình công việc một cách triệt để, đồng thời ngăn chặn mọi lượt tải phông chữ không chính xác hoặc trùng lặp ngoài ý muốn. WOFF2 hiện được hỗ trợ ở mọi nơi. Vì vậy, trừ khi bạn cần hỗ trợ các trình duyệt thực sự cổ, chỉ cần sử dụng WOFF2. Nếu không thể, bạn hãy xem xét không phân phát bất kỳ phông chữ nào trên web cho các trình duyệt cũ hơn. Điều này sẽ không thành vấn đề nếu bạn có sẵn một chiến lược dự phòng mạnh mẽ. Khách truy cập trên các trình duyệt cũ sẽ chỉ thấy phông chữ dự phòng của bạn.

Bram Stein, trong Niên giám web năm 2022

Tập hợp phông chữ con

Tệp phông chữ thường chứa một số lượng lớn hình chữ nhật cho tất cả các ký tự mà tệp hỗ trợ. Tuy nhiên, bạn có thể không cần tất cả ký tự trên trang mà có thể giảm kích thước tệp phông chữ bằng cách đặt phông chữ phụ.

Phần mô tả unicode-range trong nội dung khai báo @font-face thông báo cho trình duyệt biết những ký tự có thể dùng cho phông chữ đó.

@font-face {
    font-family: "Open Sans";
    src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
    unicode-range: U+0025-00FF;
}

Một tệp phông chữ sẽ được tải xuống nếu trang chứa một hoặc nhiều ký tự khớp với phạm vi Unicode. unicode-range thường dùng để phân phát các tệp phông chữ khác nhau tuỳ thuộc vào ngôn ngữ mà nội dung trang sử dụng.

unicode-range thường được dùng cùng với kỹ thuật cài đặt phụ. Phông chữ tập hợp con bao gồm một phần nhỏ hơn trong số các ký tự có trong tệp phông chữ gốc. Ví dụ: thay vì phân phát tất cả ký tự cho tất cả người dùng, trang web có thể tạo phông chữ tập hợp con riêng cho ký tự Latinh và Chữ Kirin. Số lượng ký tự trên mỗi phông chữ rất khác nhau: phông chữ Latinh thường có độ lớn từ 100 đến 1000 ký tự trên mỗi phông chữ; Phông chữ CJK có thể có hơn 10.000 ký tự. Việc xoá các ký tự không dùng đến có thể làm giảm đáng kể kích thước tệp của phông chữ.

Một số nhà cung cấp phông chữ có thể tự động cung cấp các phiên bản khác nhau của tệp phông chữ với các tập hợp con khác nhau. Ví dụ: Google Fonts thực hiện việc này theo mặc định:

/* devanagari */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiEyp8kv8JHgFVrJJbecnFHGPezSQ.woff2) format('woff2');
  unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* latin-ext */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiEyp8kv8JHgFVrJJnecnFHGPezSQ.woff2) format('woff2');
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiEyp8kv8JHgFVrJJfecnFHGPc.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;
}

Khi chuyển sang chế độ tự lưu trữ, đây là tính năng tối ưu hoá có thể dễ dàng bị bỏ lỡ và dẫn đến các tệp phông chữ lớn hơn trên thiết bị.

Bạn cũng có thể chọn tập hợp phông chữ theo cách thủ công nếu trình cung cấp phông chữ của bạn cho phép việc này, thông qua một API (Google Fonts hỗ trợ việc này bằng cách cung cấp tham số text) hoặc bằng cách chỉnh sửa thủ công các tệp phông chữ rồi tự lưu trữ. Các công cụ để tạo tập hợp con phông chữ bao gồm subfontDaggeranger. Tuy nhiên, hãy kiểm tra giấy phép cho các phông chữ mà bạn sử dụng cho phép cài đặt phụ và tự lưu trữ.

Dùng ít phông chữ trên web hơn

Phông chữ nhanh nhất để phân phối là phông chữ không được yêu cầu ngay từ đầu. Phông chữ hệ thống và phông chữ thay đổi là hai cách để có thể giảm số lượng phông chữ trên web được sử dụng trên trang web của bạn.

Phông chữ hệ thống là phông chữ mặc định mà giao diện người dùng trên thiết bị của người dùng sử dụng. Phông chữ hệ thống thường khác nhau tùy theo hệ điều hành và phiên bản. Vì phông chữ này đã được cài đặt nên bạn không cần tải phông chữ xuống. Phông chữ hệ thống có thể đặc biệt hiệu quả đối với văn bản nội dung.

Để sử dụng phông chữ hệ thống trong CSS của bạn, hãy liệt kê system-ui làm bộ phông chữ:

font-family: system-ui

Ý tưởng đằng sau phông chữ biến đổi là một phông chữ biến duy nhất có thể được dùng để thay thế cho nhiều tệp phông chữ. Phông chữ biến hoạt động bằng cách xác định một giá trị "mặc định" kiểu phông chữ và cung cấp "axes" (rìu) để điều chỉnh phông chữ. Ví dụ: bạn có thể dùng phông chữ có thể thay đổi với trục Weight để triển khai kiểu chữ mà trước đây yêu cầu các phông chữ riêng biệt cho kiểu chữ sáng, đều, đậm và siêu đậm.

Không phải ai cũng được hưởng lợi khi chuyển sang sử dụng phông chữ đa dạng. Phông chữ thay đổi chứa nhiều kiểu, vì vậy, thường có kích thước tệp lớn hơn các phông chữ riêng lẻ không biến đổi chỉ chứa một kiểu. Trang web sẽ nhận thấy sự cải thiện lớn nhất khi sử dụng phông chữ thay đổi là những trang web sử dụng (và cần sử dụng) nhiều kiểu phông chữ và độ đậm.

Hiển thị phông chữ

Trình duyệt đang gặp phải một tình huống nan giải: có nên trì hoãn hiển thị văn bản cho đến khi phông chữ trên web xuất hiện không? Hay Google sẽ hiển thị văn bản ở phông chữ dự phòng cho đến khi phông chữ trên web xuất hiện?

Các trình duyệt khác nhau sẽ xử lý trường hợp này theo cách khác nhau. Theo mặc định, các trình duyệt dựa trên Chromium và Firefox sẽ chặn hiển thị văn bản trong tối đa 3 giây nếu phông chữ web được liên kết chưa được tải; Safari sẽ chặn hiển thị văn bản vô thời hạn.

Bạn có thể định cấu hình hành vi này bằng cách sử dụng thuộc tính font-display. Lựa chọn này có thể có ý nghĩa đáng kể: font-display có thể ảnh hưởng đến LCP, FCP và độ ổn định của bố cục.

Chọn một chiến lược font-display phù hợp

font-display thông báo cho trình duyệt cách sẽ tiến hành kết xuất văn bản khi phông chữ được liên kết trên web chưa tải. Kích thước này được xác định theo phông chữ.

@font-face {
  font-family: Roboto, Sans-Serif
  src: url(/fonts/roboto.woff) format('woff'),
  font-display: swap;
}

Có thể có 5 giá trị cho font-display:

Giá trị Khoảng thời gian chặn Khoảng thời gian hoán đổi
Tự động Thay đổi tuỳ theo trình duyệt Thay đổi tuỳ theo trình duyệt
Chặn 2-3 giây Vô hạn
Hoán đổi 0 mili giây Vô hạn
Dự phòng 100 mili giây 3 giây
Không bắt buộc 100 mili giây Không có
  • Khoảng thời gian chặn: Khoảng thời gian chặn bắt đầu khi trình duyệt yêu cầu phông chữ trên web. Trong khoảng thời gian chặn, nếu không có phông chữ trên web, phông chữ đó sẽ hiển thị bằng phông chữ dự phòng ẩn và do đó văn bản sẽ không hiển thị với người dùng. Nếu không có phông chữ ở cuối khoảng thời gian chặn, thì phông chữ đó sẽ hiển thị bằng phông chữ dự phòng.
  • Thời gian hoán đổi: Thời gian hoán đổi sẽ đến sau giai đoạn chặn. Nếu phông chữ trên web có sẵn trong khoảng thời gian hoán đổi, phông chữ đó sẽ được "hoán đổi" trong năm

Các chiến lược font-display phản ánh các quan điểm khác nhau về sự đánh đổi giữa hiệu suất và tính thẩm mỹ. Do đó, rất khó để đưa ra một phương pháp đề xuất vì nó phụ thuộc vào các lựa chọn ưu tiên của từng cá nhân, tầm quan trọng của phông chữ trên web đối với trang và thương hiệu cũng như mức độ khó chịu của phông chữ hiển thị trễ khi hoán đổi.

Đối với hầu hết các trang web, sau đây là ba chiến lược sẽ áp dụng nhiều nhất:

  • Nếu hiệu suất là ưu tiên hàng đầu: Hãy sử dụng font-display: optional. Đây là biến thể "có hiệu suất" cao nhất phương pháp tiếp cận: hiển thị văn bản bị trễ không quá 100 mili giây và có thể đảm bảo rằng sẽ không có thay đổi bố cục liên quan đến hoán đổi phông chữ. Tuy nhiên, nhược điểm ở đây là phông chữ trên web sẽ không được sử dụng nếu sách đến trễ.

  • Nếu việc hiển thị văn bản nhanh chóng là ưu tiên hàng đầu, nhưng bạn vẫn muốn đảm bảo phông chữ web đã được sử dụng: Hãy dùng font-display: swap nhưng nhớ phân phối phông chữ đủ sớm để không làm thay đổi bố cục. Nhược điểm của tùy chọn này là sự thay đổi khó chịu khi phông chữ đến trễ.

  • Nếu việc đảm bảo văn bản hiển thị ở dạng phông chữ trên web là ưu tiên hàng đầu: Hãy dùng font-display: block nhưng hãy nhớ phân phối phông chữ đủ sớm để giảm thiểu độ trễ của văn bản. Nhược điểm của phương pháp này là việc hiển thị văn bản ban đầu sẽ bị trễ. Xin lưu ý rằng mặc dù việc tắt chế độ này vẫn có thể gây ra sự thay đổi bố cục vì văn bản thực sự bị ẩn đi và do đó, không gian phông chữ dự phòng được dùng để đặt trước khoảng trống. Khi phông chữ trên web tải, điều này có thể yêu cầu không gian khác biệt và do đó phải chuyển đổi. Tuy nhiên, đây có thể là một sự thay đổi ít gây khó chịu hơn so với font-display: swap vì văn bản sẽ không thay đổi.

Ngoài ra, xin lưu ý rằng bạn có thể kết hợp hai phương pháp này với nhau: chẳng hạn như sử dụng font-display: swap để xây dựng thương hiệu và các thành phần khác biệt của trang; sử dụng font-display: optional cho phông chữ dùng trong văn bản nội dung.

Giảm sự thay đổi giữa phông chữ dự phòng và phông chữ web

Để giảm tác động đến CLS (Mức thay đổi bố cục tích luỹ), bạn có thể sử dụng các thuộc tính size-adjust mới. Để biết thêm thông tin, hãy xem bài viết về CSS size-adjust. Đây là một nội dung bổ sung rất mới cho bộ công cụ của chúng tôi, vì vậy hiện tại, đây là nội dung nâng cao hơn và thủ công hơn một chút. Nhưng chắc chắn là bạn nên thử nghiệm và theo dõi những cải tiến về công cụ trong tương lai!

Kết luận

Phông chữ trên web vẫn là một nút thắt cổ chai về hiệu suất, nhưng chúng tôi có nhiều lựa chọn hơn để cho phép tối ưu hoá chúng nhằm giảm nút thắt này nhiều nhất có thể.