Khai thác sức mạnh của truy vấn vùng chứa CSS: bài học từ nhóm Netflix

Jeremy Weeks
Jeremy Weeks
Stefan Heymanns
Stefan Heymanns

Truy vấn vùng chứa đã cách mạng hoá cách nhà phát triển tiếp cận thiết kế thích ứng, và nhóm Netflix đã trực tiếp trải nghiệm tác động sâu sắc mà các truy vấn này có thể mang lại đối với việc đơn giản hoá quá trình phát triển, cải thiện tính linh hoạt và nâng cao hiệu suất. Bài đăng này trình bày các lợi ích chính của việc sử dụng truy vấn vùng chứa, so sánh các truy vấn này với các phương thức cũ, đặc biệt là các phương thức dựa vào JavaScript để kiểm soát bố cục. Bài viết này bao gồm các ví dụ về mã để minh hoạ từng điểm, cho thấy cách truy vấn vùng chứa có thể giúp cuộc sống của bạn trở thành nhà phát triển trở nên dễ dàng hơn nhiều.

1. Thiết kế thành phần đơn giản, "từ dưới lên" so với "từ trên xuống"

Một trong những thay đổi quan trọng nhất mà nhóm Netflix trải qua là chuyển từ phương pháp thiết kế "từ trên xuống" sang phương pháp "từ dưới lên". Trước khi truy vấn vùng chứa, vùng chứa mẹ phải nắm rõ các yêu cầu về bố cục của vùng chứa con. Với truy vấn vùng chứa, logic này được đảo ngược, cho phép các thành phần con kiểm soát bố cục dựa trên kích thước của vùng chứa của chính chúng. Điều này giúp đơn giản hoá vai trò của thành phần mẹ và giảm lượng logic bố cục trong mã.

Ví dụ: Truy vấn vùng chứa so với truy vấn nội dung đa phương tiện và JavaScript

Trước (cần JavaScript):

/* Layout with media queries */
.card {
    width: 100%;
}

@media (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@media (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}
// JavaScript to detect parent container size
const container = document.querySelector('.container');
const card = document.querySelector('.card');

function adjustLayout() {
    if (window.innerWidth >= 900) {
        card.style.width = '33.33%';
    } else if (window.innerWidth >= 600) {
        card.style.width = '50%';
    } else {
        card.style.width = '100%';
    }
}

window.addEventListener('resize', adjustLayout);
adjustLayout();

Sau:

/* Container Query */
.container {
    container-type: inline-size;
}

.card {
    width: 100%;
}

@container (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@container (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

Ví dụ này cho thấy cách vùng chứa mẹ không cần quản lý bố cục con nữa. Quy tắc @container cho phép .card phản ứng với kích thước của vùng chứa ngay lập tức, đơn giản hoá logic bố cục và không cần JavaScript.

2. Khả năng thích ứng mà không cần truy vấn nội dung đa phương tiện phức tạp

Nhóm Netflix đã khám phá cách truy vấn vùng chứa đơn giản hoá khả năng thích ứng, đặc biệt là đối với thiết kế ưu tiên thiết bị di động. Thay vì viết các truy vấn nội dung đa phương tiện phức tạp, bạn có thể tạo các thành phần có thể sử dụng lại và điều chỉnh dựa trên kích thước của vùng chứa, cho phép bố cục linh động trên nhiều kích thước màn hình và thiết bị. Điều này đặc biệt hữu ích đối với các ứng dụng như Netflix, nơi lưu lượng truy cập trên thiết bị di động chiếm ưu thế.

Ví dụ: Khả năng phản hồi của thành phần với truy vấn vùng chứa

Trước:

/* Desktop versus Mobile
this only works if.sidebar is directly contained by a viewport-width element */
.sidebar {
    width: 300px;
}

@media (max-width: 768px) {
    .sidebar {
        width: 100%;
    }
}

Sau:

/* Responsive sidebar based on container,
.sidebar can be placed in any element of any width */
.container {
    container-type: inline-size;
}

.sidebar {
    width: 100%;
}

@container (min-width: 768px) {
    .sidebar {
        width: 300px;
    }
}

Thay vì phụ thuộc vào truy vấn nội dung đa phương tiện dựa trên khung nhìn, .sidebar hiện phản hồi kích thước vùng chứa, cho phép vùng chứa này thích ứng một cách tự nhiên hơn với bố cục động mà không cần biết kích thước của khung nhìn hoặc vùng chứa mẹ.

3. Giảm phần phụ thuộc vào JavaScript để quản lý bố cục

Trước khi có truy vấn vùng chứa, nhiều nhóm, bao gồm cả Netflix, phải dựa vào JavaScript cho bố cục động. Bằng cách truy vấn kích thước cửa sổ, JavaScript sẽ kích hoạt các thay đổi về bố cục, làm tăng cả độ phức tạp và khả năng xảy ra lỗi. Truy vấn vùng chứa giúp loại bỏ nhu cầu này bằng cách cho phép CSS xử lý khả năng thích ứng của bố cục dựa trên kích thước vùng chứa.

Ví dụ: Xoá logic bố cục dựa trên JavaScript

Trước:

const cardContainer = document.querySelector('.card-container');
const cards = cardContainer.children;

function adjustLayout() {
    if (cardContainer.offsetWidth > 900) {
        cards.forEach(card => card.style.width = '33.33%');
    } else if (cardContainer.offsetWidth > 600) {
        cards.forEach(card => card.style.width = '50%');
    } else {
        cards.forEach(card => card.style.width = '100%');
    }
}

window.addEventListener('resize', adjustLayout);
adjustLayout();

Sau:

.card-container {
    container-type: inline-size;
}

.card {
    width: 100%;
}

@container (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@container (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

Phương pháp này không chỉ làm giảm lượng JavaScript cần thiết mà còn cải thiện hiệu suất bằng cách tránh các phép tính thời gian chạy.

4. Ít mã hơn, ít lỗi hơn

Nhóm Netflix nhận thấy việc sử dụng truy vấn vùng chứa giúp giảm số dòng mã và giảm số lỗi liên quan đến bố cục. Bằng cách di chuyển logic bố cục từ JavaScript sang CSS và loại bỏ nhu cầu về các truy vấn nội dung đa phương tiện phức tạp, nhà phát triển có thể viết mã dễ bảo trì hơn.

Ví dụ: Giảm mã bố cục

Nhóm Netflix nhận thấy rằng sau khi sử dụng truy vấn vùng chứa, họ nhận thấy lượng mã CSS giảm đáng kể – lên đến 30% đối với một số thành phần nhất định. Đồng thời, nhóm nghiên cứu có thể đơn giản hoá nhiều truy vấn nội dung đa phương tiện phức tạp và đôi khi dễ xung đột bằng cách loại bỏ logic kiểm soát các thành phần con, đạt được mức độ phân tách vấn đề cao hơn. Việc giảm thiểu này không chỉ giúp tăng tốc quá trình phát triển mà còn giảm thiểu các điểm có thể xảy ra lỗi, từ đó giảm thiểu lỗi.

Trước:

/* Before with complex media queries */
.card {
    width: 100%;
}

@media (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@media (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

Sau

.container {
    container-type: inline-size;
}

.card {
    width: 100%;
}

@container (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@container (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

5. Cải thiện trải nghiệm của nhà phát triển

bq. "điều này giúp cuộc sống của tôi dễ dàng hơn gấp trăm lần"

Có lẽ một trong những lợi ích ít được đánh giá cao nhất của truy vấn vùng chứa là cải thiện trải nghiệm của nhà phát triển. Bằng cách giúp CSS hoạt động theo cách trực quan hơn, tập trung vào thành phần, nhà phát triển có thể tập trung vào việc xây dựng các thành phần linh hoạt, có thể sử dụng lại mà không phải lo lắng về cách các thành phần này hoạt động trong mọi trường hợp bố cục có thể xảy ra.

Như một thành viên trong nhóm Netflix đã nói: "Đây là cách CSS nên hoạt động ngay từ đầu".

6. Phương thức dự phòng polyfill

Mặc dù truy vấn vùng chứa hiện có trong tất cả các trình duyệt chính, nhưng vẫn có mối lo ngại về việc các phiên bản trình duyệt cũ vẫn đang được sử dụng. Phương án dự phòng rất quan trọng, nhóm Netflix sử dụng JavaScript polyfill này do các cộng tác viên trong cộng đồng web tạo ra. Việc triển khai rất đơn giản với tính năng phát hiện tính năng:

if (! CSS.supports("container-type:size")) {
  /*use polyfill from
  https://www.npmjs.com/package/container-query-polyfill */
 }

Kết luận

Truy vấn vùng chứa là một bước tiến lớn trong CSS, giúp nhà phát triển dễ dàng tạo các thành phần linh hoạt, thích ứng và có thể sử dụng lại trên nhiều phần của trang web. Bằng cách giảm sự phụ thuộc vào JavaScript cho bố cục, loại bỏ các truy vấn nội dung đa phương tiện phức tạp và đẩy nhanh quá trình phát triển, các thành phần này mang lại nhiều lợi thế đáng kể về cả hiệu suất và khả năng bảo trì. Hiện tại, hầu hết các trường hợp sử dụng đều nằm trên các trang Tudum của Netflix, với kế hoạch tiềm năng là sử dụng truy vấn vùng chứa trong các phần khác của Netflix. Nhóm Netflix coi truy vấn vùng chứa là một công cụ hạng nhất trong bộ công cụ dành cho nhà phát triển và việc sử dụng các truy vấn này sẽ chỉ mở rộng khi có nhiều nhà phát triển hơn đón nhận sự linh hoạt và sức mạnh mà các truy vấn này mang lại. Cho dù là để cải tiến các thành phần hiện có hay thiết kế các thành phần hoàn toàn mới, truy vấn vùng chứa đều cung cấp một lộ trình đơn giản và rõ ràng hơn cho thiết kế thích ứng.

Nếu chưa từng thử, hãy dùng thử truy vấn vùng chứa. Bạn có thể sẽ thấy rằng truy vấn này giúp đơn giản hoá quy trình làm việc theo những cách mà bạn không ngờ tới.