💥 Đừng Để Website Của Bạn "Nhảy Múa"! Bí Quyết Fix Lỗi SHAKING "Khó Chịu Với Hình Ảnh" 💥
Chào anh em FrontEnd Devs! 👋
Anh em có bao giờ gặp tình huống này chưa? Khi tạo hóa đơn và hiển thị mã QR lấy từ server, mọi thứ có vẻ smooth. Nhưng khi loading indicator biến mất, cái hình ảnh QR code "nhảy tưng tưng" trên màn hình một cái rồi mới ổn định? 😵💫
Đây chính là hiện tượng layout SHAKING hay Cumulative Layout Shift (CLS) – một nỗi ám ảnh thầm lặng của nhiều Dev. Và hôm nay, chúng ta sẽ mổ xẻ nguyên nhân và tìm ra giải pháp triệt để cho vấn đề "nhức nhối" này!
🧐 Vấn Đề Gốc Rễ: Loading & Rendering Hình Ảnh Không Đồng Bộ
Trong quy trình tạo hóa đơn, chúng ta thường:
- Bắt đầu gọi API để lấy đường dẫn QR code: Set loading = true (hiển thị skeleton).
- Khi API trả về đường dẫn ảnh: Set loading = false (ẩn skeleton), rồi gán đường dẫn vào thẻ <img>.
Nghe có vẻ hợp lý phải không? Nhưng đây chính là lúc vấn đề phát sinh!
Sau khi API trả về URL, trình duyệt cần thêm một khoảng thời gian nhất định để tải, giải mã và hiển thị hình ảnh. Trong khoảng thời gian "chết" này, nếu không có thông tin về kích thước ảnh, trình duyệt sẽ không thể "dự đoán" được chiều cao/chiều rộng của nó. Kết quả là gì? Màn hình co giãn đột ngột (SHAKING) khi ảnh cuối cùng xuất hiện!
🖼️ Trình Duyệt Sẽ Làm Gì Khi Có Thẻ <img>?
Để hiểu rõ hơn, hãy cùng xem lại "hành trình" một bức ảnh được hiển thị:
- Phân tích HTML: Trình duyệt đọc và nhận diện thẻ <img> trong DOM.
- Gửi Yêu Cầu Tải Ảnh: Gửi HTTP GET request tới src để lấy ảnh.
- Nhận Dữ Liệu Ảnh: Server phản hồi dữ liệu (có thể là từng phần).
- Giải Mã Ảnh: Khi nhận đủ dữ liệu, trình duyệt giải mã định dạng ảnh (JPEG, PNG, SVG...).
- Kích Hoạt onload: Toàn bộ dữ liệu được tải và giải mã xong, sự kiện onload trên <img> được bắn.
- Vẽ Ảnh Lên Giao Diện: Trình duyệt đưa ảnh vào cây render và hiển thị lên màn hình.
NHẬN RA CHƯA? Việc ảnh được hiển thị là bước CUỐI CÙNG trong cả một quy trình dài!
🚫 Quy Trình Sai Lầm: Kích Hoạt loading = false Quá Sớm
Đây là chuỗi sự kiện dễ gây ra lỗi SHAKING:
- loading = true (Hiển thị Skeleton)
- Gọi API
- Server trả về đường dẫn ảnh
- loading = false (Skeleton biến mất ngay lập tức!)
- Trình duyệt bắt đầu tải ảnh...
- ...Giải mã ảnh...
- ...Và cuối cùng mới hiển thị ảnh.
Trong khoảng thời gian từ bước 4 đến bước 7, không gian dành cho ảnh bị "trống", skeleton đã biến mất, và khi ảnh xuất hiện, nó "ép" các thành phần khác phải dịch chuyển, gây ra SHAKING.
✅ Quy Trình Chuẩn: Đợi Ảnh Tải Xong Mới Tắt Skeleton!
Để khắc phục, chúng ta cần đảm bảo rằng skeleton chỉ biến mất khi hình ảnh đã SẴN SÀNG để hiển thị, tức là sau khi sự kiện onload của ảnh được kích hoạt.
- loading = true (Hiển thị Skeleton)
- Gọi API
- Server trả về đường dẫn ảnh
- Gán đường dẫn vào thẻ <img>
- Trình duyệt bắt đầu tải ảnh...
- ...Giải mã ảnh...
- **...Kích hoạt sự kiện onload của <img>
- Trong sự kiện onload này: loading = false (Ẩn Skeleton)
- Trình duyệt vẽ ảnh lên giao diện
Bằng cách này, skeleton sẽ "chiếm" chỗ cho hình ảnh cho đến khi ảnh thực sự được tải và sẵn sàng hiển thị, loại bỏ hoàn toàn tình trạng SHAKING khó chịu! ✨
Chỉ một chút tinh chỉnh trong logic xử lý loading và lắng nghe sự kiện onload của <img> là chúng ta đã giải quyết được một vấn đề lớn về trải nghiệm người dùng!
Anh em còn gặp vấn đề gì về FrontEnd nữa không? Cùng chia sẻ với mình qua LinkedIn nhé! 👇