Technical SEO

Web Fonts Loading Strategy

Chiến lược tải phông chữ (ví dụ: font-display, preload, fallback) nhằm cân bằng giữa khả năng đọc và hiệu suất hiển thị.

4 lượt xem Cập nhật: 29/05/2026

Web Fonts Loading Strategy là gì?

Web Fonts Loading Strategy (chiến lược tải phông chữ trên web) là tập hợp các kỹ thuật kỹ thuật nhằm kiểm soát cách trình duyệt tải, hiển thị và thay thế phông chữ tùy chỉnh — như Google Fonts, Adobe Fonts hay phông tự lưu trữ — sao cho văn bản luôn dễ đọc, không bị nhảy (FOIT/FOUT), đồng thời không làm chậm tốc độ tải trang. Đây không phải là việc chọn phông đẹp, mà là cách điều phối thời điểmcách thức hiển thị phông chữ để cân bằng giữa trải nghiệm người dùng và hiệu suất kỹ thuật.

Tại sao quan trọng trong SEO?

Google xếp hạng trang dựa phần lớn vào trải nghiệm người dùng — đặc biệt là các chỉ số Core Web Vitals: LCP (Largest Contentful Paint), CLS (Cumulative Layout Shift) và FID/INP (Interaction to Next Paint). Web Fonts ảnh hưởng trực tiếp đến cả ba:

  • LCP: Nếu phông chữ tải chậm, trình duyệt có thể trì hoãn hiển thị văn bản chính (nhất là tiêu đề), kéo dài thời gian LCP.
  • CLS: Khi phông chữ tải xong rồi thay thế phông mặc định (fallback), kích thước dòng/khoảng cách có thể thay đổi → nội dung dịch chuyển bất ngờ → tăng CLS.
  • INP: Phông chữ nặng hoặc tải đồng bộ có thể chiếm CPU, làm chậm phản hồi khi người dùng cuộn, nhấn nút hoặc nhập liệu.

Ngoài ra, Google xác nhận rằng trang chậm hơn 3 giây có tỷ lệ thoát cao hơn 32% (theo dữ liệu CrUX 2023). Chiến lược tải phông chữ tốt giúp giữ CLS dưới 0.1, LCP dưới 2.5s — điều kiện cần để đạt trạng thái "Tốt" trong Core Web Vitals.

Cách hoạt động

Trình duyệt xử lý phông chữ theo chuỗi trạng thái: Block → Swap → Failure → Load. Thời gian ở mỗi trạng thái phụ thuộc vào thuộc tính font-display, cách khai báo @font-face, và thứ tự tải (preload vs async). Khi phông chưa sẵn sàng, trình duyệt sẽ:

  1. Dùng phông fallback (ví dụ: font-family: 'Inter', -apple-system, sans-serif) để hiển thị ngay văn bản.
  2. Theo dõi tiến trình tải phông từ mạng hoặc bộ nhớ đệm.
  3. Khi phông tải xong, áp dụng lại lên văn bản — nếu thiết lập đúng, việc này diễn ra mượt, không gây nhảy bố cục.

Hướng dẫn thực hiện

Dưới đây là 5 bước thực tế, tuân thủ tiêu chuẩn W3C và khuyến nghị của Google Developers:

  1. Dùng font-display: swap trong mọi khai báo @font-face. Đây là giá trị an toàn nhất: trình duyệt hiển thị văn bản bằng phông fallback ngay, sau đó thay bằng phông tùy chỉnh khi tải xong. Tránh auto (mặc định, gây FOIT) và block (chặn hiển thị tới 3s).
  2. Preload phông chữ quan trọng (chỉ với phông dùng cho tiêu đề LCP hoặc văn bản đầu trang). Thêm thẻ <link rel="preload" as="font" type="font/woff2" crossorigin href="..."> trong <head>. Lưu ý: crossorigin bắt buộc với phông từ CDN, nếu thiếu sẽ không preload được.
  3. Giới hạn số họ phông và trọng lượng: Mỗi họ phông thêm thường làm tăng yêu cầu mạng. Chỉ tải những trọng lượng thực sự dùng (ví dụ: 400 và 700 — không tải 100, 200, 300, 500, 600, 800, 900 nếu không cần).
  4. Dùng định dạng WOFF2: Là định dạng nén tốt nhất hiện tại, nhẹ hơn WOFF ~30%, hỗ trợ bởi mọi trình duyệt hiện đại (Chrome 36+, Firefox 39+, Edge 14+). Không dùng TTF hoặc OTF trên web trừ khi bắt buộc.
  5. Loại bỏ phông không dùng bằng công cụ như Font Soup hoặc phân tích Coverage qua DevTools > Rendering > Show fonts. Kiểm tra xem phông có bị tải nhưng không xuất hiện trong DOM hay không.

Lỗi thường gặp

Lỗi Dấu hiệu Cách khắc phục
FOIT (Flash of Invisible Text) Văn bản trắng hoặc trống vài giây trước khi hiện Thay font-display: auto hoặc block bằng swap; kiểm tra xem có đang chặn render bằng @import trong CSS hay không.
FOUT (Flash of Unstyled Text) Văn bản hiện bằng phông hệ thống rồi nhảy sang phông tùy chỉnh Không phải lỗi — đây là hành vi mong muốn với swap. Để giảm cảm giác nhảy: chọn phông fallback có metrics gần giống (giống chiều cao dòng, khoảng cách chữ), dùng size-adjust hoặc font-size-adjust (hỗ trợ từ Chrome 106+).
Preload thừa hoặc sai Console cảnh báo "preload request ignored", hoặc phông bị tải 2 lần Chỉ preload phông dùng trong LCP; đảm bảo href trùng chính xác với src trong @font-face; không preload phông đã được nén trong CSS (inline).

Ví dụ thực tế

Một trang tin tức sử dụng phông Roboto cho tiêu đề và Roboto Slab cho bài viết. Trước khi tối ưu:

  • Tải 6 trọng lượng Roboto từ Google Fonts qua @import trong CSS → gây chặn render.
  • Không dùng font-display → FOIT rõ rệt trên mạng 3G.
  • LCP trung bình: 4.2s, CLS: 0.24.

Sau tối ưu:

  • Dùng <link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>.
  • Chỉ preload Roboto:wght@400;700 dạng WOFF2.
  • Khởi tạo @font-face với font-display: swap, kèm size-adjust: 95% để khớp chiều cao dòng với system-ui.
  • Kết quả: LCP giảm còn 1.8s, CLS về 0.06, tỷ lệ thoát giảm 22% (theo GA4 sau 30 ngày).

Câu hỏi thường gặp

font-display: optional có nên dùng?

Có thể dùng nếu ưu tiên hiệu suất tuyệt đối và chấp nhận khả năng phông không bao giờ hiển thị (trình duyệt có thể quyết định không tải nếu mạng chậm). Tuy nhiên, Google khuyến cáo không dùng cho văn bản chính vì ảnh hưởng đến khả năng đọc — chỉ phù hợp với yếu tố trang trí (ví dụ: nhãn badge, icon text). Hành vi cụ thể tùy trường hợp.

Có nên nén phông thành một file duy nhất?

Không nên. Gộp nhiều họ/phông vào một file WOFF2 làm mất khả năng cache hiệu quả và tăng kích thước tải không cần thiết. Mỗi phông nên tách riêng, kèm preload có chọn lọc. Việc nén chung chỉ hữu ích trong môi trường ứng dụng đóng (app shell), không phải website mở.

Phông tự lưu trữ (self-hosted) có lợi hơn Google Fonts không?

Có lợi về kiểm soát và hiệu suất — vì tránh DNS lookup, preconnect và giảm số request ngoài miền. Nhưng cần đảm bảo: (1) máy chủ hỗ trợ HTTP/2 hoặc HTTP/3, (2) bật Brotli/Gzip, (3) cấu hình cache headers đúng (Cache-Control: public, max-age=31536000, immutable). Nếu không đáp ứng đủ, lợi ích có thể bị triệt tiêu. Kết quả cụ thể tùy trường hợp.