Tối ưu hoá phông chữ web cho Core Web Vitals.
Tài liệu này trình bày các phương pháp hay nhất về hiệu suất cho phông chữ. Phông chữ trên web ảnh hưởng đến hiệu suất theo nhiều cách:
- Kết xuất văn bản bị trì hoãn: Nếu phông chữ trên web chưa tải, thì trình duyệt thường trì hoãn việc kết xuất văn bản. Trong nhiều trường hợp, điều này làm chậm Nội dung đầu tiên hiển thị (FCP). Trong một số trường hợp, điều này sẽ làm chậm Nội dung lớn nhất hiển thị (LCP).
- Mức thay đổi bố cục: Việc thay thế phông chữ có thể gây ra mức thay đổi bố cục và ảnh hưởng đến Mức thay đổi bố cục tích luỹ (CLS). Những thay đổi về bố cục này xảy ra khi một phông chữ trên web và phông chữ dự phòng của phông chữ đó chiếm một lượng không gian khác nhau trên trang.
Tài liệu này có 3 phần: tải phông chữ, phân phối phông chữ và kết xuất phông chữ. Mỗi phần giải thích cách hoạt động của khía cạnh cụ thể đó trong vòng đời của phông chữ và cung cấp các phương pháp hay nhất tương ứng.
Đang tải phông chữ
Phông chữ là tài nguyên quan trọng. Nếu không có các cookie này, 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 rằng phông chữ được tải sớm nhất có thể. Bạn cầ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 đòi hỏi phải thiết lập các kết nối riêng biệt.
Nếu bạn không chắc chắn liệu các phông chữ trên trang của mình có được yêu cầu đúng hạn hay không, hãy kiểm tra thẻ Thời gian trong Bảng điều khiển mạng Mạng trong Chrome DevTools để biết thêm thông tin.

Tìm hiểu @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 @font-face hoạt động và cách điều này ảnh hưởng đến việc tải phông chữ.
Khai báo @font-face là một phần thiết yếu khi làm việc với bất kỳ phông chữ web nào. Tối thiểu, tệp này khai báo tên 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");
}
Một quan niệm sai lầm phổ biến là phông chữ được yêu cầu khi gặp phải một khai báo @font-face. Điều này là sai. Bản thân khai báo @font-face không kích hoạt quá trình tải phông chữ xuống. Thay vào đó, phông chữ chỉ được tải xuống nếu được tham chiếu bằng kiểu được dùng trên trang. Ví dụ:
@font-face {
font-family: "Open Sans";
src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
}
h1 {
font-family: "Open Sans"
}
Trong ví dụ này, Open Sans sẽ chỉ được tải xuống nếu trang chứa phần tử <h1>.
Do đó, khi nghĩ đến việc tối ưu hoá phông chữ, bạn cần cân nhắc kỹ lưỡng các biểu định kiểu cũng như các tệp phông chữ. Việc thay đổi nội dung hoặc cách phân phối biểu định kiểu có thể ảnh hưở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 nhỏ biểu định kiểu có thể 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ẽ được hưởng lợi rất nhiều từ việc khai báo phông chữ nội tuyến và các kiểu quan trọng khác trong <head> của tài liệu chính thay vì đưa chúng 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 đợ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 nội tuyến CSS quan trọ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ể đạt được. Lợi ích về hiệu suất là rất rõ ràng, nhưng bạn cần có thêm các quy trình và công cụ tạo để đảm bảo CSS cần thiết (và lý tưởng nhất là chỉ CSS quan trọng) được nội tuyến đúng cách và mọi CSS bổ sung đều được phân phối theo cách không chặn hiển thị.
Kết nối trước với các nguồn gốc 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 bên thứ ba, bạn nên sử dụng gợi ý về tài nguyên preconnect để thiết lập(các) kết nối sớm với nguồn gốc của bên thứ ba.
Gợi ý về tài nguyên nên được đặt trong <head> của tài liệu. Gợi ý tài nguyên sau đây thiết lập một 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 ý riêng về tài nguyên preconnect 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 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 riêng biệt. Ví dụ: đây là cách sử 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 các phông chữ được phát hiện sớm trong quá trình tải trang, nhưng điều này sẽ làm mất đi tài nguyên trình duyệt từ việc tải các tài nguyên khác.
Việc khai báo phông chữ nội tuyến 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 gần như giải quyết được căn nguyên của vấn đề về phông chữ được phát hiện muộn, thay vì chỉ cung cấp một giải pháp tạm thời.
Ngoài ra, bạn cũng nên sử dụng preload một cách cẩn thận 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 các khai báo unicode-range và nếu được sử dụng một cách thận trọng, thì 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 được liệu phông chữ có cần thiết hay không cho đến khi muộn hơn nhiều.
Phân phối phông chữ
Việc phân phối phông chữ nhanh hơn sẽ giúp kết xuất văn bản nhanh hơn. Ngoài ra, nếu một phông chữ được phân phối đủ sớm, điều này có thể giúp loại bỏ các thay đổi về bố cục do việc hoán đổi phông chữ gây ra.
Sử dụng phông chữ tự lưu trữ
Trên lý thuyế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ì việc này giúp loại bỏ chế độ thiết lập kết nối với bên thứ ba. Trên thực tế, sự khác biệt về hiệu suất giữa hai lựa chọn này không rõ ràng. Ví dụ: Web Almanac nhận thấy rằng những trang web sử dụng phông chữ của bên thứ ba có tốc độ kết xuất nhanh hơn so với những 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 sử dụng Mạng phân phối nội dung (CDN) và HTTP/2. Nếu không sử dụng các công nghệ này, thì khả năng phông chữ tự lưu trữ mang lại hiệu suất tốt hơn là rất thấp.
Nếu sử dụng phông chữ tự lưu trữ, bạn cũng nên áp dụng một số biện pháp tối ưu hoá tệp phông chữ mà các nhà cung cấp phông chữ bên thứ ba thường cung cấp tự động. Ví dụ: chia nhỏ phông chữ và nén WOFF2. Mức độ nỗ lực cần thiết để áp dụng các biện pháp tối ưu hoá này phụ thuộc phần nào vào những ngôn ngữ mà trang web của bạn hỗ trợ. Đặc biệt, hãy 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 nhiều trình duyệt hỗ trợ nhất và có 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 việc tải xuống ít dữ liệu hơn và do đó hiệu suất nhanh hơn.
Do trình duyệt có hỗ trợ WOFF2, nên các chuyên gia hiện chỉ khuyên dùng WOFF2:
Trên thực tế, chúng tôi cho rằng cũng đã đến lúc tuyên bố: Chỉ sử dụng WOFF2 và quên mọi thứ khác.
Bram Stein, từ Web Almanac 2022
Thao tác này sẽ đơn giản hoá đáng kể CSS và quy trình làm việc của bạn, đồng thời ngăn chặn mọi trường hợp tải phông chữ xuống hai lần hoặc tải phông chữ không chính xác do nhầm lẫn. WOFF2 hiện được hỗ trợ ở mọi nơi. Vì vậy, trừ phi bạn cần hỗ trợ các trình duyệt thực sự cũ, hãy chỉ sử dụng WOFF2. Nếu không thể, hãy cân nhắc việc không phân phát bất kỳ phông chữ nào trên web cho những trình duyệt cũ đó. Đây sẽ không phải là vấn đề nếu bạn có một chiến lược dự phòng mạnh mẽ. Khách truy cập sử dụng trình duyệt cũ sẽ thấy các phông chữ dự phòng của bạn.
Phông chữ con
Các tệp phông chữ thường chứa một số lượng lớn ký tự đồ hoạ cho tất cả các ký tự mà chúng hỗ trợ. Nhưng bạn có thể không cần tất cả các ký tự trên trang của mình và có thể giảm kích thước của tệp phông chữ bằng cách chia nhỏ phông chữ.
Bộ mô tả unicode-range trong khai báo @font-face cho trình duyệt biết những ký tự mà một phông chữ có thể dùng.
@font-face {
font-family: "Open Sans";
src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
unicode-range: U+0025-00FF;
}
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 dải unicode. unicode-range thường được 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 kết hợp với kỹ thuật chia thành tập hợp con.
Phông chữ con bao gồm một phần nhỏ hơn của các glyph có trong tệp phông chữ gốc. Ví dụ: thay vì phân phát tất cả các ký tự cho tất cả người dùng, một trang web có thể tạo các phông chữ riêng biệt cho các ký tự Latinh và Cyrillic.
Số lượng glyph trên mỗi phông chữ rất khác nhau:
- Phông chữ Latinh thường có từ 100 đến 1.000 glyph cho mỗi phông chữ.
- CJK có thể có hơn 10.000 ký tự.
Việc xoá các glyph không dùng đến có thể giảm đáng kể kích thước tệp của một phông chữ.
Một số nhà cung cấp phông chữ có thể tự động cung cấp nhiều phiên bản tệp phông chữ với nhiều tập hợp con. 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 tự lưu trữ, đây là một điểm tối ưu hoá có thể 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ó thể tự tạo tập hợp con phông chữ nếu nhà cung cấp phông chữ cho phép, bằng API (Google Fonts hỗ trợ việc này bằng cách cung cấp một tham số text) hoặc bằng cách chỉnh sửa tệp phông chữ theo cách thủ công rồi tự lưu trữ. Các công cụ để tạo tập hợp con của phông chữ bao gồm subfont và glyphanger.
Luôn kiểm tra giấy phép phông chữ để xác nhận rằng giấy phép cho phép tạo tập hợp con và tự lưu trữ.
Sử dụng ít phông chữ web hơn
Phông chữ được phân phối nhanh nhất là phông chữ không được yêu cầu ngay từ đầu. Phông chữ hệ thống và phông chữ có thể thay đổi là hai cách có thể giúp giảm số lượng phông chữ trên web được 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 của thiết bị người dùng sử dụng. Phông chữ hệ thống thường khác nhau tuỳ theo hệ điều hành và phiên bản. Vì phông chữ đã đượ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ể hoạt động đặ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, hãy liệt kê system-ui làm họ phông chữ:
font-family: system-ui
Ý tưởng đằng sau phông chữ biến đổi là bạn có thể dùng một phông chữ biến đổi duy nhất để thay thế cho nhiều tệp phông chữ. Phông chữ có thể thay đổi hoạt động bằng cách xác định kiểu phông chữ "mặc định" và cung cấp "trục" để thao tác với phông chữ.
Ví dụ: bạn có thể dùng một phông chữ biến đổi có trục Weight để triển khai kiểu chữ mà trước đây cần có các phông chữ riêng biệt cho kiểu chữ sáng, thông thường, đậm và siêu đậm.
Không phải ai cũng được hưởng lợi khi chuyển sang phông chữ biến đổi. Phông chữ có thể thay đổi chứa nhiều kiểu, vì vậy, thường có kích thước tệp lớn hơn so với các phông chữ riêng lẻ không thay đổi chỉ chứa một kiểu. Những trang web sẽ có sự cải thiện lớn nhất khi sử dụng phông chữ có thể thay đổi là những trang web sử dụng (và cần sử dụng) nhiều kiểu và độ đậm của phông chữ.
Kết xuất phông chữ
Khi gặp phải một phông chữ trên web chưa tải, trình duyệt sẽ phải đối mặt với một tình huống khó xử: liệu trình duyệt có nên trì hoãn việc hiển thị văn bản cho đến khi phông chữ trên web xuất hiện hay không? Hay nên hiển thị văn bản bằng một phông chữ dự phòng cho đến khi phông chữ trên web xuất hiện?
Mỗi trình duyệt sẽ xử lý tình huống này theo cách riêng. Theo mặc định, các trình duyệt dựa trên Chromium và Firefox sẽ chặn quá trình kết xuất văn bản trong tối đa 3 giây nếu phông chữ web được liên kết chưa tải. Safari chặn quá trình 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ó những tác động đáng kể: font-display có khả năng ả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 tiếp tục hiển thị văn bản khi phông chữ web được liên kết chưa tải. Thuộc tính này được xác định cho mỗi phông chữ.
@font-face {
font-family: Roboto, Sans-Serif
src: url(/fonts/roboto.woff) format('woff'),
font-display: swap;
}
Có 5 giá trị có thể cho font-display:
| Giá trị | Khoảng thời gian chặn | Khoảng thời gian hoán đổi |
|---|---|---|
| Tự động | Tuỳ theo trình duyệt | 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 một phông chữ web. Trong khoảng thời gian chặn, nếu phông chữ trên web không có sẵn, phông chữ sẽ được kết xuất trong một phông chữ dự phòng vô hình và do đó, người dùng sẽ không thấy văn bản. Nếu phông chữ không có sẵn vào cuối khoảng thời gian chặn, thì phông chữ đó sẽ được kết xuất bằng phông chữ dự phòng.
- Khoảng thời gian hoán đổi: Khoảng thời gian hoán đổi diễn ra sau khoảng thời gian chặn. Nếu phông chữ trên web có sẵn trong thời gian thay thế, thì phông chữ đó sẽ được "thay thế".
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ó để đề xuất một phương pháp vì điều này phụ thuộc vào lựa chọn ưu tiên của từng cá nhân, mức độ 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ữ xuất hiện muộn khi được thay thế.
Đối với hầu hết các trang web, đây là 3 chiến lược phù hợp nhất, dựa trên mức độ ưu tiên hàng đầu của bạn:
Hiệu suất: Sử dụng
font-display: optional. Đây là phương pháp "hiệu quả" nhất: quá trình kết xuất văn bản bị trì hoãn không quá 100 mili giây và đảm bảo rằng không có sự thay đổi bố cục liên quan đến việc hoán đổi phông chữ. Nhược điểm là phông chữ trên web sẽ không được dùng nếu đến muộn.Hiển thị văn bản nhanh chóng và vẫn sử dụng phông chữ trên web: Sử dụng
font-display: swapnhưng nhớ phân phối phông chữ đủ sớm để không gây ra sự thay đổi bố cục. Nhược điểm của lựa chọn này là sự thay đổi đột ngột khi phông chữ xuất hiện muộn.Văn bản hiển thị bằng phông chữ trên web: Sử dụng
font-display: blocknhưng hãy đảm bảo phân phối phông chữ đủ sớm để giảm thiểu độ trễ của văn bản. Việc hiển thị văn bản ban đầu bị chậm trễ. Mặc dù có độ trễ này, nhưng điều đó vẫn có thể gây ra sự thay đổi bố cục vì văn bản thực sự được vẽ ở chế độ ẩn và do đó, không gian phông chữ dự phòng được dùng để dành trước không gian. Sau khi phông chữ trên web tải, điều này có thể yêu cầu khoảng cách khác, do đó sẽ có sự thay đổi. Đây có thể là một thay đổi ít gây khó chịu hơn so vớifont-display: swap, vì bản thân văn bản sẽ không bị dịch chuyển.
Ngoài ra, hãy lưu ý rằng bạn có thể kết hợp hai phương pháp này: ví dụ: sử dụng font-display: swap cho việc xây dựng thương hiệu và các phần tử trang khác biệt về mặt hình ảnh.
Sử dụng font-display: optional cho phông chữ được dùng trong văn bản nội dung.
Phông chữ biểu tượng
Các chiến lược font-display phù hợp với phông chữ web thông thường lại không phù hợp với phông chữ biểu tượng. Phông chữ dự phòng cho một phông chữ biểu tượng thường trông khác biệt đáng kể so với phông chữ biểu tượng và các ký tự của phông chữ dự phòng có thể truyền tải một ý nghĩa hoàn toàn khác. Do đó, phông chữ biểu tượng có nhiều khả năng gây ra các thay đổi đáng kể về bố cục.
Ngoài ra, việc sử dụng một phông chữ dự phòng có thể không thực tế. Khi có thể, hãy thay thế phông chữ biểu tượng bằng SVG. Điều này cũng giúp tăng khả năng hỗ trợ tiếp cận. Các phiên bản mới hơn của phông chữ biểu tượng phổ biến thường hỗ trợ SVG. Để biết thêm thông tin về cách chuyển sang SVG, hãy xem trang của Font Awesome về SVG Sprites và Hướng dẫn về biểu tượng Material.
Giảm sự thay đổi giữa phông chữ dự phòng và phông chữ trên web
Để giảm tác động của CLS, bạn có thể sử dụng các thuộc tính size-adjust.
Kết luận
Phông chữ trên web vẫn là một điểm nghẽn về hiệu suất, nhưng chúng ta có nhiều lựa chọn hơn bao giờ hết để tối ưu hoá phông chữ nhằm giảm thiểu điểm nghẽn này.