KIếN THứC WEBSITE › PERFORMANCE

aspect-ratio CSS — fix CLS từ image, iframe cho WordPress

aspect-ratio CSS — fix CLS từ image, iframe cho WordPress 2026

CSS aspect-ratio giữ trước không gian cho ảnh và iframe trước khi tải — ngăn dịch chuyển bố cục, cải thiện CLS. Bài hướng dẫn 5 bước triển khai aspect-ratio 2026: width/height, CSS aspect-ratio, phần tử picture, iframe và xác minh CLS pass cho shop WordPress.

aspect-ratio — khái niệm và hỗ trợ trình duyệt

aspect-ratio — khái niệm và hỗ trợ trình duyệt
aspect-ratio — khái niệm và hỗ trợ trình duyệt

CSS aspect-ratio (Chrome 88+, Firefox 89+, Safari 15+) cho phép đặt tỷ lệ chiều rộng:chiều cao cho bất kỳ phần tử nào. Trình duyệt tính chiều cao từ chiều rộng × tỷ lệ trước khi nội dung tải xong — giữ trước không gian đúng kích thước.

Khi ảnh hoặc iframe load xong, phần tử đã chiếm đúng vị trí — không gây dịch chuyển bố cục.

Tại sao dịch chuyển bố cục gây hại CLS?

CLS (Cumulative Layout Shift) đo tổng mức dịch chuyển bố cục không mong muốn trong suốt vòng đời trang. Google tính CLS là 1 trong 3 chỉ số Core Web Vitals quyết định xếp hạng.

Ngưỡng Good: CLS < 0,1. Ảnh không có kích thước định sẵn là nguyên nhân phổ biến nhất gây CLS.

3 cách giữ trước không gian cho media

  • Thuộc tính width + height trên img: cách cũ nhất, trình duyệt hiện đại tự áp dụng aspect-ratio CSS (Chrome 79+).
  • CSS aspect-ratio property: tường minh, hoạt động cho mọi phần tử kể cả div container.
  • Padding hack: kỹ thuật cũ trước 2021, dùng padding-top: 56.25% cho tỷ lệ 16:9. Vẫn hoạt động nhưng aspect-ratio CSS gọn hơn.

Hỗ trợ trình duyệt 2026

Phủ sóng trình duyệt 2026: Chrome 88+, Firefox 89+, Safari 15+ — khoảng 95%+ toàn cầu.

Dùng @supports not (aspect-ratio: 1) để áp dụng fallback padding hack cho số ít trình duyệt cũ còn lại.

Bước 1 — Thuộc tính width + height trên <img>

Bước 1 — Thuộc tính width + height trên <img>
Sơ đồ minh hoạ — Bước 1 — Thuộc tính width + height trên <img>

Cách đơn giản nhất, phù hợp 99% trường hợp ảnh thông thường. Trình duyệt hiện đại tự tính aspect-ratio từ thuộc tính, giữ trước không gian tương ứng — không cần CSS thêm.

Markup chuẩn

<!-- SAI: thiếu kích thước, trình duyệt không giữ trước không gian -->
<img src="/hero.webp" alt="Hero">

<!-- ĐÚNG: đủ thuộc tính width + height -->
<img src="/hero.webp" alt="Hero" width="1920" height="1080">

<!-- Trình duyệt tự áp dụng CSS ngầm:
img[width][height] {
  aspect-ratio: attr(width) / attr(height);
} -->

4 quy tắc khi đặt thuộc tính

  1. Đặt giá trị thật của ảnh (1920×1080), không theo kích thước hiển thị CSS.
  2. CSS có thể override width: 100% + height: auto — aspect-ratio vẫn được giữ.
  3. Ảnh responsive với srcset: lấy thuộc tính từ ảnh lớn nhất, trình duyệt tự scale.
  4. WordPress core 5.5+ tự thêm width + height từ thư viện ảnh — không cần làm thủ công.

WordPress và thuộc tính ảnh

WordPress 5.5+ tự thêm width và height cho ảnh trong nội dung bài viết. Template tùy chỉnh (hero trong single-product.php) cần gọi wp_get_attachment_image() — hàm này trả về markup có đủ thuộc tính.

Theme cũ hard-code thẻ <img> thủ công cần audit thêm thuộc tính riêng.

Bước 2 — CSS aspect-ratio cho container responsive

Bước 2 — CSS aspect-ratio cho container responsive
Bước 2 — CSS aspect-ratio cho container responsive

Khi ảnh cần chiều rộng 100% container, dùng CSS aspect-ratio thay thuộc tính cố định. Duy trì tỷ lệ khi container thay đổi kích thước, không cần JavaScript.

Ảnh responsive tỷ lệ 16:9

.hero-image {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* Hoặc dạng thập phân */
.hero-image {
  aspect-ratio: 1.7778;  /* 16/9 */
}

Tỷ lệ phổ biến

/* Tỷ lệ thường dùng */
.ratio-16-9 { aspect-ratio: 16 / 9; }   /* video, hero ngang */
.ratio-4-3  { aspect-ratio: 4 / 3; }    /* ảnh, thumbnail blog */
.ratio-1-1  { aspect-ratio: 1 / 1; }    /* vuông, sản phẩm, avatar */
.ratio-3-4  { aspect-ratio: 3 / 4; }    /* ảnh chân dung */
.ratio-21-9 { aspect-ratio: 21 / 9; }   /* hero cực rộng */

/* Fallback padding cho trình duyệt cũ */
@supports not (aspect-ratio: 1) {
  .ratio-16-9 {
    position: relative;
    padding-top: 56.25%;
  }
  .ratio-16-9 > * {
    position: absolute;
    inset: 0;
  }
}

Khi nào dùng CSS aspect-ratio thay thuộc tính?

Dùng CSS aspect-ratio khi ảnh co giãn theo container hoặc khi đặt tỷ lệ cho phần tử không phải ảnh. Thuộc tính width/height phù hợp hơn khi kích thước cố định và biết trước.

Bước 3 — Phần tử picture + aspect-ratio responsive

Phần tử picture phục vụ ảnh khác nhau theo viewport — tỷ lệ có thể khác giữa mobile và desktop. Đặt aspect-ratio theo media query CSS thay vì thuộc tính cố định.

Picture với art direction và tỷ lệ khác nhau

<picture class="hero">
  <source media="(max-width: 480px)"
          srcset="/hero-mobile-portrait.webp">
  <source media="(max-width: 1024px)"
          srcset="/hero-tablet.webp">
  <img src="/hero-desktop.webp"
       alt="Hero"
       width="1920" height="1080">
</picture>

<style>
.hero { width: 100%; }
.hero img { width: 100%; height: auto; }

@media (max-width: 480px) {
  .hero { aspect-ratio: 3 / 4; }   /* dọc mobile */
}
@media (min-width: 481px) and (max-width: 1024px) {
  .hero { aspect-ratio: 4 / 3; }   /* ngang tablet */
}
@media (min-width: 1025px) {
  .hero { aspect-ratio: 16 / 9; }  /* rộng desktop */
}
</style>

Lưu ý khi dùng art direction

Mỗi nguồn ảnh trong picture có thể có tỷ lệ khác nhau. Đặt aspect-ratio trên container theo từng breakpoint — không đặt trực tiếp trên thẻ img trong picture.

Bước 4 — iframe (YouTube, embed)

iframe (YouTube, Vimeo, widget mạng xã hội) không có kích thước tự nhiên — trình duyệt render 0×0 trước khi tải, gây CLS. Phải giữ trước không gian.

YouTube embed responsive

<!-- Container wrapper với aspect-ratio -->
<div class="video-wrapper">
  <iframe src="https://www.youtube.com/embed/xxx"
          loading="lazy"
          title="Video hướng dẫn"
          allow="autoplay; fullscreen; picture-in-picture"
          allowfullscreen></iframe>
</div>

<style>
.video-wrapper {
  width: 100%;
  aspect-ratio: 16 / 9;
}
.video-wrapper iframe {
  width: 100%;
  height: 100%;
  border: 0;
}
</style>

Kỹ thuật lazy load façade cho video

  • Thay iframe YouTube đầy đủ bằng ảnh thumbnail + nút play.
  • Người dùng bấm play → hoán đổi thumbnail thành iframe thật.
  • Giảm dung lượng tải ban đầu từ 500KB-1MB xuống 50KB.
  • Plugin “WP YouTube Lyte” hoặc “Lazy Load for Videos” tự động chuyển đổi.

iframe không phải video

Map Google, widget đánh giá, form nhúng cũng cần giữ trước không gian — đặt min-heightaspect-ratio cho container.

Nếu chiều cao cố định, đặt height tường minh thay vì aspect-ratio.

Bước 5 — Xác minh CLS pass

Sau khi triển khai aspect-ratio, xác minh CLS < 0,1 qua Chrome DevTools tab Performance và extension Web Vitals.

Quy trình xác minh

  1. Mở Chrome DevTools → tab Performance.
  2. F1 → Experiments → tick “Layout Shift Regions”.
  3. Chọn mạng “Slow 4G” + CPU slowdown 4x.
  4. Ghi lại khi tải trang (Ctrl+E).
  5. Dừng ghi sau 5 giây.
  6. Kiểm tra timeline: 0 vùng highlight xanh là pass.
  7. Vùng highlight xanh = CLS issue — bấm vào box để xem phần tử gây ra.

Theo dõi CLS trên người dùng thật

// web-vitals.js — theo dõi CLS từ người dùng thật
import {onCLS} from 'web-vitals';

onCLS((metric) => {
  if (metric.value > 0.1) {
    gtag('event', 'cls_issue', {
      value: metric.value,
      target: metric.attribution?.largestShiftTarget,
    });
  }
});

Xác minh qua PSI và Search Console

Sau khi fix local, chạy PageSpeed Insights để kiểm tra CLS dữ liệu lab. Theo dõi CLS dữ liệu thực tế qua Search Console tab “Core Web Vitals” sau 14-28 ngày.

Checklist aspect-ratio cho shop VN

  1. Audit tất cả thẻ <img> trong theme: có đủ width và height không?
  2. Kiểm tra template tùy chỉnh — dùng wp_get_attachment_image() thay hard-code.
  3. Thêm aspect-ratio CSS cho tất cả container ảnh responsive (hero, banner, thumbnail).
  4. Thêm wrapper với aspect-ratio cho tất cả iframe YouTube/Vimeo.
  5. Đặt min-height cho widget, form nhúng không có kích thước tự nhiên.
  6. Thêm @supports not (aspect-ratio: 1) fallback cho trình duyệt cũ.
  7. Xác minh CLS < 0,1 qua DevTools trước khi triển khai.
  8. Theo dõi CLS dữ liệu thực tế qua Search Console sau 14-28 ngày.
  9. Test trên thiết bị di động thật — mạng chậm thể hiện CLS rõ hơn desktop.
  10. Cân nhắc lazy load façade cho video để giảm tải ban đầu.

Bài liên quan trong cluster Performance

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

Trình duyệt cũ không hỗ trợ aspect-ratio CSS — fallback thế nào?

Dùng padding hack với position: absolute cho trình duyệt cũ. Phủ sóng 2026: Chrome 88+, Firefox 89+, Safari 15+ = 95%+ toàn cầu.

@supports not (aspect-ratio: 1) {
  .container {
    position: relative;
    padding-top: 56.25%; /* 16:9 */
  }
  .container > * {
    position: absolute;
    inset: 0;
  }
}
WordPress tự thêm width/height — có cần làm thủ công không?

WordPress 5.5+ tự thêm cho ảnh trong nội dung bài. Cần kiểm tra thêm với:

  • Template tùy chỉnh: dùng wp_get_attachment_image() — hàm này tự thêm thuộc tính.
  • Theme cũ hard-code <img>: cần audit thêm thủ công.
  • Plugin gallery: kiểm tra xem plugin có thêm thuộc tính không.
aspect-ratio CSS vs padding hack — chọn cái nào?

aspect-ratio CSS gọn hơn và phủ sóng 95%+ năm 2026. Padding hack chỉ cần khi phải hỗ trợ trình duyệt trước 2021.

iframe đã có aspect-ratio nhưng vẫn bị shift — tại sao?

Có thể container chưa khóa chiều cao trước khi iframe tải. Kiểm tra:

  • Container có aspect-ratiowidth: 100% đặt đúng chưa.
  • Trong DevTools: container đã có kích thước đúng trước khi iframe load chưa.
  • Thêm min-height để đảm bảo container không collapse về 0.

Cần kiểm tra và fix CLS cho toàn bộ site? Xem dịch vụ tối ưu Core Web Vitals của Web22.