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

Tài liệu này thảo luận về 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:

Tài liệu này có 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 giải thích cách hoạt động của một 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.

Tải phông chữ

Phông chữ là những tài nguyên quan trọng. Nếu không có các thẻ 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 kết nối riêng.

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 ở Công cụ của Chrome cho nhà phát triển để biết thêm thông tin.

Thẻ Timing (Thời gian) trong DevTools.

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 rõ cách hoạt động của @font-face và mức độ tác động của phương thức này đến việc tải phông chữ.

Nội dung 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 nhất, tệp này sẽ 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 thường gặp là phông chữ được yêu cầu khi gặp nội dung khai báo @font-face. Điều này là không đúng. Bản thân nội dung 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 khi phông chữ đó được tham chiếu bằng cách định kiểu được sử 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 suy nghĩ về việc tối ưu hoá phông chữ, 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 các tệp kiểu có thể ảnh hưởng đáng kể đến thời điểm phông chữ đến. Tương tự, việc xoá CSS không dùng đến và tách các tệp 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ẽ được hưởng lợi rất nhiều từ việc nội tuyến các nội dung khai báo phông chữ và các kiểu quan trọng khác trong <head> của tài liệu chính thay vì đưa các nội dung đó vào một tệp định kiểu bên ngoài. Điều này cho phép trình duyệt khám phá các nội dung khai báo phông chữ sớm hơn vì trình duyệt không cần phải đợi tải tệp 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ể thực hiện được. Lợi ích về hiệu suất là rõ ràng, nhưng bạn cần thêm các quy trình và công cụ xây dựng để đả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 chính xác và mọi CSS bổ sung được phân phối theo cách không chặn kết xuất.

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 bên thứ ba, bạn nên sử dụng gợi ý tài nguyên preconnect để thiết lập(các) kết nối sớm với nguồn gốc bên thứ ba. Bạn nên đặt gợi ý tài nguyên trong <head> của tài liệu. Gợi ý về tài nguyên sau đây sẽ 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 ý 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, các tệp phông chữ phải được gửi qua kết nối CORS (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 sử dụng gợi ý 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 khám phá phông chữ ngay từ đầu quá trình tải trang, nhưng điều này sẽ làm giảm tài nguyên trình duyệt khi tải các tài nguyên khác.

Việc nội tuyến các nội dung khai báo phông chữ và điều chỉnh các tệp kiểu có thể là một phương pháp hiệu quả hơn. Những điều chỉnh này giúp giải quyết nguyên nhân gốc rễ của phông chữ được phát hiện muộn, thay vì chỉ cung cấp giải pháp.

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

Phân phối phông chữ

Việc phân phối phông chữ nhanh hơn sẽ 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, thì đ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ì loại phông chữ này loại bỏ việc thiết lập kết nối của bên thứ ba. Trong thực tế, sự khác biệt về hiệu suất giữa hai tuỳ chọn này không rõ ràng. Ví dụ: Web Almanac nhận thấy rằng các trang web sử dụng phông chữ bên thứ ba có tốc độ kết xuất nhanh hơn so với các trang web sử dụng phông chữ 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)HTTP/2. Nếu không sử dụng những 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.

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à các nhà cung cấp phông chữ bên thứ ba thường cung cấp tự động. Ví dụ: tạo tập hợp con 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 một phần vào ngôn ngữ mà trang web của bạn hỗ trợ. Cụ thể, hãy lưu ý rằng việc tối ưu hoá phông chữ cho 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 việc tải ít dữ liệu hơn và do đó hiệu suất nhanh hơn.

Do tính năng hỗ trợ trình duyệt, các chuyên gia hiện chỉ đề xuất 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.

Việc này sẽ giúp đơn giản hoá CSS và quy trình làm việc của bạn một cách đáng kể, đồng thời ngăn chặn mọi trường hợp tải phông chữ không chính xác hoặc tải hai lần 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 phông chữ web nào cho những trình duyệt cũ đó. Điều này sẽ không thành vấn đề nếu bạn có một chiến lược dự phòng mạnh mẽ. Khách truy cập trên trình duyệt cũ sẽ thấy phông chữ dự phòng của bạn.

Bram Stein, trong cuốn Web Almanac 2022

Phông chữ con

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

Chỉ số mô tả unicode-range trong phần khai báo @font-face sẽ cho trình duyệt biết phông chữ có thể dùng cho ký tự nào.

@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 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 kết hợp với kỹ thuật tạo tập hợp con. Phông chữ con bao gồm một phần nhỏ hơn của 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, một trang web có thể tạo phông chữ con riêng biệt cho ký tự La tinh và ký tự 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ó số lượng ký tự từ 100 đến 1.000 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 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 tự lưu trữ, đây là một phương pháp 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 máy.

Bạn có thể tạo nhóm con phông chữ theo cách thủ công nếu nhà cung cấp phông chữ cho phép việc này, bằng 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 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 phông chữ bao gồm subfonters rồi.

Luôn kiểm tra giấy phép phông chữ để xác nhận rằng chúng cho phép chế độ cài đặt phụ và tự lưu trữ.

Sử dụng ít phông chữ 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 của thiết bị của 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ữ của hệ thống trong CSS, hãy liệt kê system-ui làm font-family:

font-family: system-ui

Ý tưởng đằng sau phông chữ biến là bạn có thể sử dụng một phông chữ biến để thay thế nhiều tệp phông chữ. Phông chữ biến thể 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 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 phông chữ riêng biệt cho các màu sáng, đều, đậ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ữ 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 biến chỉ chứa một kiểu. Những trang web sẽ thấy sự cải thiện lớn nhất khi sử dụng phông chữ biến thể là những trang web sử dụng (và cần sử dụng) nhiều kiểu và độ đậm phông chữ.

Kết xuất phông chữ

Khi gặp một phông chữ web chưa tải, trình duyệt sẽ phải đối mặt với một vấn đề nan giải: có nên tạm hoãn việc hiển thị văn bản cho đến khi phông chữ web đã tải xong hay không? Hay có nên hiển thị văn bản bằng phông chữ dự phòng cho đến khi phông chữ web đến không?

Các trình duyệt 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 quá trình kết xuất văn bản trong tối đa 3 giây nếu phông chữ trên web được liên kết chưa được tải. Safari chặn việc 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ể tác động đến LCP, FCP và độ ổn định của bố cục.

Chọn 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 kết xuất văn bản khi phông chữ web được liên kết chưa tải. Giá trị này được xác định cho từng 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ể có 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 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ữ web. Trong khoảng thời gian chặn, nếu không có phông chữ web, phông chữ sẽ được hiển thị bằng phông chữ dự phòng vô hình, do đó, người dùng sẽ không thấy văn bản. Nếu không có phông chữ vào cuối khoảng thời gian chặn, phông chữ sẽ được hiển thị 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ữ web có sẵn trong khoảng thời gian hoán đổi, thì phông chữ đó sẽ được "hoán đổi".

Các chiến lược font-display phản ánh nhiều 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ì nó 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ữ web đối với trang và thương hiệu, cũng như mức độ khó chịu của phông chữ đến muộn khi được hoán đổi.

Đố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: việc hiển thị văn bản bị trễ không quá 100 mili giây và có thể đảm bảo rằng không có sự thay đổi bố cục nào liên quan đến hoán đổi phông chữ. Nhược điểm là phông chữ web sẽ không được sử dụng nếu đến muộn.

  • Hiển thị nhanh văn bản và vẫn sử dụng phông chữ web: Sử dụng font-display: swap như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 tuỳ chọn này là sự thay đổi đột ngột khi phông chữ đến trễ.

  • Văn bản hiển thị ở dạng phông chữ trên web: Dùng font-display: block nhưng nhớ phân phối phông chữ đủ sớm để giảm thiểu độ trễ của văn bản. Nội dung hiển thị văn bản ban đầu bị trễ. Mặc dù có độ trễ này, nhưng nó 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 để đặt trước không gian. Sau khi phông chữ web tải, thao tác này có thể yêu cầu không gian khác, do đó, sẽ có sự dịch chuyển. Đây có thể là sự thay đổi ít khó chịu hơn so với font-display: swap, vì bản thân văn bản sẽ không bị chuyển đổi.

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 thương hiệu và các thành phần trang khác có hình thức khác biệt. Sử dụng font-display: optional cho phông chữ dùng trong nội dung văn bản.

Phông chữ biểu tượng

Các chiến lược font-display hoạt động tốt với phông chữ web thông thường nhưng lại không hoạt động tốt với phông chữ biểu tượng. Phông chữ dự phòng cho 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ữ này 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 sự thay đổi đáng kể về bố cục.

Ngoài ra, việc sử dụng 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. Phông chữ này cũng phù hợp hơn với 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 Font AwesomeBiểu tượng Material.

Giảm sự khác biệt giữa phông chữ dự phòng và phông chữ 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ữ web vẫn là nút thắt cổ chai về hiệu suất, nhưng chúng ta có một loạt các tuỳ chọn ngày càng tăng để cho phép tối ưu hoá phông chữ nhằm giảm thiểu nút thắt cổ chai này nhiều nhất có thể.