Yugen UI

Màn chờ khởi động

Màn chờ toàn trang chỉ nên có khi trang chưa có gì để hiện. Đã dùng thì tiến độ phải đo từ việc tải thật, đóng ngay khi trang sẵn sàng và có lối ra khi lỗi.

Khi nào cần

Màn chờ toàn trang che mọi thứ, nên chỉ đáng dùng khi phía sau nó thật sự trống. Trang đã có nội dung thì để người dùng đọc luôn; phần còn đang tải dùng skeleton hoặc chỉ báo tại chỗ (xem Trải nghiệm chờ).

Tình huống trên site docsMàn chờVì sao
Trang prerender (bản build)KhôngHTML đã có nội dung ở lần vẽ đầu; che lại chỉ làm chậm LCP.
Prerender bị ẩn (khác ngôn ngữ, RTL)Códata-pending ẩn #root tới khi React render xong.
404.htmlCóKhung trống, React tự render theo URL.
npm run devCóKhông có prerender; Vite trả từng module (~280 file) trước lần render đầu.

Phòng thử concept

Hai bộ bố cục: Kanji (gồm concept đang dùng) và Latin cho sản phẩm không dùng chữ Hán. Mọi concept chạy cùng một lần tải mô phỏng để so ở cùng tiến độ, xong thì giữ ở khung cuối. Đổi tốc độ, bật giảm chuyển động, hoặc xem toàn màn hình (vẫn chạy lại được từ thanh điều khiển).

Đã tải 0%

Tategaki nét cọ

Đang dùng. Nét cọ ở giữa chạy theo tiến độ, số Hán viết dọc ở mép, logo vẽ bằng mực ở góc và nở hoa khi xong.

Tategaki

Số viết dọc ở mép, vạch mực chảy xuống theo tiến độ.

Enso mực

Bản trước. Mực chạy theo nét enso ở giữa, số Hán ở góc.

Nét cọ

Một nét cọ ngang thay thanh tiến độ, số đi theo đầu bút.

Hoa nở

Mỗi 20% nở một cánh; đủ năm cánh thì nhị hiện.

Tiến độ đo thật

Thanh tiến độ giả (chạy theo đồng hồ) sẽ sai ở máy nhanh lẫn máy chậm. Màn chờ của docs đếm file thật: số file JS và CSS đã tải xong, so với số file của lần mở trước (lưu trong localStorage). Lần đầu chưa có số đo thì dùng một con số ước lượng.

// Đếm file JS / CSS cùng origin đã tải xong
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) if (sameOrigin(entry)) count++;
}).observe({ type: "resource", buffered: true });

// So với số file của lần tải trước; nhiều hơn thì nới mẫu số — thanh chậm lại chứ không lùi
const measured = Math.min(0.95, count / Math.max(expected, count / 0.95));

// App render xong (html[data-docs-ready]) mới chạy nốt 95% → 100% trong 400 ms
if (document.documentElement.hasAttribute("data-docs-ready")) finish();

Số dừng ở 95% tới khi trang render xong, nên không bao giờ báo xong sớm hơn thực tế. 15 giây không có file mới thì đổi sang thông báo lỗi kèm link Tải lại, thay vì quay mãi.

Bố cục, số Hán & chữ

Giữa khung là một nét cọ chạy theo tiến độ, chữ “Đang tải” ngay dưới. Số tiến độ viết dọc ở mép trên (tategaki) bằng số Hán cho hợp với logo enso, font Mincho nếu máy có (Yu Mincho, Hiragino Mincho, Noto Serif JP), không có thì serif. Logo ở góc dưới vẽ bằng mực cùng nhịp và nở hoa khi đủ 100. Không cần dấu %: số chỉ là nhịp, con số chính xác đi qua thuộc tính ARIA.

SốViết
0〇
7七
10十
12十二
40四十
99九十九
100百

Chữ “Đang tải” giãn rộng và mờ tỏ chậm; trang tiếng Anh hiện “Loading”. Ở RTL, nét cọ chạy từ phải sang, số và logo đổi bên. Khi lỗi, thông báo thay chỗ chữ và nét cọ dừng ở chỗ treo.

Giảm chuyển động

Khi hệ điều hành bật giảm chuyển động (prefers-reduced-motion: reduce), mực (nét cọ và logo) không chạy theo nét bút mà đậm dần tại chỗ, chữ “Đang tải” đứng yên, và màn chờ đóng ngay thay vì mờ dần. Tiến độ vẫn hiện đầy đủ, chỉ bỏ phần chuyển động.

Khả năng tiếp cận

Màn chờ là role="progressbar" có aria-label và aria-valuenow bằng số thường; số Hán để aria-hidden vì trình đọc màn hình đọc “四十一” không giúp gì. Khi xong, màn chờ đặt aria-hidden rồi rời khỏi DOM.

Ở dev, lớp phủ lỗi biên dịch của Vite luôn nằm trên màn chờ. Ở chế độ tương phản cao của Windows, màn chờ dùng màu hệ thống (Canvas, CanvasText).

Nên & không nên

Nên
  • Chỉ hiện màn chờ khi trang chưa có gì để hiện.
  • Đo tiến độ từ việc tải thật và chỉ tới 100 khi trang đã render.
  • Đợi ~200 ms rồi mới hiện logo, để lần tải nhanh không bị chớp.
  • Có thông báo lỗi và cách thử lại khi việc tải dừng hẳn.
Không nên
  • Che trang prerender đã có nội dung chỉ để chạy hiệu ứng.
  • Cho thanh tiến độ chạy theo đồng hồ rồi đứng ở 99%.
  • Giữ màn chờ thêm sau khi trang đã sẵn sàng.
  • Để trình đọc màn hình đọc số trang trí thay cho giá trị tiến độ.