content-Visibility: thuộc tính CSS mới giúp tăng hiệu suất hiển thị

Cải thiện thời gian tải ban đầu bằng cách bỏ qua quá trình kết xuất nội dung ngoài màn hình.

Thuộc tính content-visibility (ra mắt trong Chromium 85) có thể là một trong những thuộc tính CSS mới có tác động lớn nhất trong việc cải thiện hiệu suất tải trang. content-visibility cho phép tác nhân người dùng bỏ qua công việc kết xuất của một phần tử, bao gồm cả bố cục và tô màu, cho đến khi cần thiết. Vì quá trình kết xuất bị bỏ qua, nên nếu phần lớn nội dung của bạn nằm ngoài màn hình, thì việc tận dụng thuộc tính content-visibility sẽ giúp người dùng ban đầu tải nhanh hơn nhiều. API này cũng cho phép tương tác nhanh hơn với nội dung trên màn hình. Khá gọn gàng.

bản minh hoạ có các hình thể hiện kết quả mạng
Trong bản minh hoạ bài viết của chúng tôi, việc áp dụng content-visibility: auto cho các vùng nội dung được chia nhỏ giúp tăng hiệu suất kết xuất 7 lần trong lần tải đầu tiên. Hãy đọc tiếp để tìm hiểu thêm.

Hỗ trợ trình duyệt

Hỗ trợ trình duyệt

  • 85
  • 85
  • 124

Nguồn

content-visibility dựa vào các dữ liệu nguyên gốc trong Thông số kỹ thuật về vùng chứa CSS. Mặc dù hiện tại content-visibility chỉ được hỗ trợ trong Chromium 85 (và được coi là "đáng giá trị để tạo nguyên mẫu" cho Firefox), nhưng Thông số vùng chứa được hỗ trợ trong các trình duyệt hiện đại nhất.

Vùng chứa CSS

Mục tiêu chính và mục tiêu bao quát của tính năng ngăn chặn CSS là cho phép cải thiện hiệu suất hiển thị của nội dung web bằng cách cung cấp cách dự đoán khả năng tách biệt một cây con DOM với phần còn lại của trang.

Về cơ bản, nhà phát triển có thể cho trình duyệt biết những phần nào của trang được đóng gói dưới dạng một nhóm nội dung, cho phép các trình duyệt suy luận về nội dung mà không cần xem xét trạng thái bên ngoài cây con. Việc biết được bit nội dung nào (cây con) chứa nội dung riêng biệt có nghĩa là trình duyệt có thể đưa ra quyết định tối ưu hoá cho việc hiển thị trang.

Có 4 loại vùng chứa CSS, mỗi loại là một giá trị tiềm năng cho thuộc tính CSS contain. Bạn có thể kết hợp các thành phần này trong một danh sách các giá trị được phân tách bằng dấu cách:

  • size: Vùng chứa kích thước trên một phần tử đảm bảo rằng hộp của phần tử có thể được bố trí mà không cần kiểm tra các thành phần con cháu. Điều này có nghĩa là chúng ta có thể bỏ qua bố cục của các thành phần con nếu tất cả những gì chúng ta cần là kích thước của phần tử.
  • layout: Vùng chứa bố cục có nghĩa là các thành phần con không ảnh hưởng đến bố cục bên ngoài của các hộp khác trên trang. Điều này cho phép chúng ta có thể bỏ qua bố cục của các thành phần con nếu tất cả những gì chúng ta muốn làm là bố trí các hộp khác.
  • style: Vùng chứa kiểu đảm bảo rằng các thuộc tính có thể có ảnh hưởng đến nhiều phần tử con khác không được thoát khỏi phần tử (ví dụ: bộ đếm). Điều này cho phép chúng ta có thể bỏ qua việc tính toán kiểu cho các thành phần con cháu nếu tất cả những gì chúng ta muốn là tính toán kiểu trên các phần tử khác.
  • paint: Vùng chứa hiển thị đảm bảo rằng các thành phần con cháu của hộp chứa không hiển thị bên ngoài giới hạn của hộp. Không có phần tử nào có thể làm tràn phần tử một cách rõ ràng và nếu một phần tử nằm ngoài màn hình hoặc không hiển thị, thì các thành phần con cháu của nó cũng sẽ không hiển thị. Điều này cho phép chúng ta có thể bỏ qua việc vẽ phần tử con nếu phần tử đó nằm ngoài màn hình.

Bỏ qua công việc kết xuất bằng content-visibility

Có thể bạn sẽ khó tìm ra giá trị vùng chứa nào cần sử dụng, vì tính năng tối ưu hoá cho trình duyệt chỉ có thể bắt đầu khi chỉ định một nhóm phù hợp. Bạn có thể khám phá các giá trị để xem giá trị nào hoạt động hiệu quả nhất, hoặc bạn cũng có thể dùng một thuộc tính CSS khác có tên là content-visibility để tự động áp dụng vùng chứa cần thiết. content-visibility đảm bảo rằng bạn với tư cách là nhà phát triển, sẽ đạt được hiệu suất cao nhất mà trình duyệt có thể làm với mức tối thiểu.

Thuộc tính chế độ hiển thị nội dung chấp nhận một số giá trị, nhưng auto là giá trị giúp cải thiện hiệu suất tức thì. Một phần tử có content-visibility: auto sẽ có vùng chứa layout, stylepaint. Nếu phần tử nằm ngoài màn hình (và không liên quan đến người dùng, các phần tử có liên quan sẽ là những phần tử được lấy làm tâm điểm hoặc được lựa chọn trong cây con), thì phần tử đó cũng sẽ nhận được vùng chứa size (và ngừng vẽ cũng như kiểm thử nhấn vào nội dung của nó).

Điều này có nghĩa là gì? Tóm lại, nếu phần tử nằm ngoài màn hình, thì các thành phần con cháu của nó sẽ không được hiển thị. Trình duyệt xác định kích thước của phần tử mà không cần xem xét bất kỳ nội dung nào của phần tử và sẽ dừng ở đó. Hầu hết quá trình kết xuất, chẳng hạn như tạo kiểu và bố cục của cây con của phần tử đều bị bỏ qua.

Khi phần tử này tiến gần đến khung nhìn, trình duyệt không còn thêm thành phần chứa size nữa và bắt đầu vẽ cũng như kiểm thử nhấn nội dung của phần tử đó. Điều này giúp công việc kết xuất hoàn tất đúng thời điểm mà người dùng có thể nhìn thấy.

Lưu ý về khả năng hỗ trợ tiếp cận

Một trong các tính năng của content-visibility: auto là nội dung ngoài màn hình vẫn có sẵn trong mô hình đối tượng của tài liệu và cây hỗ trợ tiếp cận (không giống như với visibility: hidden). Tức là người dùng có thể tìm và chuyển đến nội dung trên trang mà không phải chờ nội dung tải hoặc hy sinh hiệu suất kết xuất.

Tuy nhiên, mặt trái của điều này là các phần tử đánh dấu có đặc điểm kiểu như display: none hoặc visibility: hidden cũng sẽ xuất hiện trong cây hỗ trợ tiếp cận khi ở ngoài màn hình, vì trình duyệt sẽ không hiển thị các kiểu này cho đến khi chúng vào khung nhìn. Để những tính năng này không xuất hiện trong cây hỗ trợ tiếp cận vì có thể gây ra tình trạng lộn xộn, hãy nhớ thêm aria-hidden="true".

Ví dụ: blog du lịch

Trong ví dụ này, chúng tôi đặt blog du lịch làm đường cơ sở ở bên phải và áp dụng content-visibility: auto cho các khu vực được chia nhỏ ở bên trái. Kết quả cho thấy thời gian kết xuất thay đổi từ 232 mili giây xuống còn 30 mili giây khi tải trang ban đầu.

Blog du lịch thường chứa một tập hợp các câu chuyện với một vài hình ảnh và một số văn bản mô tả. Dưới đây là những gì sẽ xảy ra trong trình duyệt thông thường khi trình duyệt chuyển đến một blog du lịch:

  1. Một phần của trang sẽ được tải xuống từ mạng, cùng với mọi tài nguyên cần thiết.
  2. Trình duyệt tạo kiểu và bố trí tất cả nội dung của trang mà không xét đến việc nội dung đó có hiển thị cho người dùng hay không.
  3. Trình duyệt sẽ quay lại bước 1 cho đến khi tất cả trang và tài nguyên được tải xuống.

Ở bước 2, trình duyệt xử lý tất cả nội dung đang tìm kiếm những nội dung có thể đã thay đổi. API này cập nhật kiểu và bố cục của mọi phần tử mới, cùng với các phần tử có thể đã thay đổi do các bản cập nhật mới. Đây là thao tác kết xuất hình ảnh. Việc này tốn thời gian.

Ảnh chụp màn hình một blog du lịch.
Ví dụ về một blog du lịch. Xem Bản minh hoạ trên Codepen

Bây giờ, hãy xem xét điều gì sẽ xảy ra nếu bạn đặt content-visibility: auto vào từng câu chuyện riêng lẻ trong blog. Vòng lặp chung cũng giống nhau: trình duyệt tải xuống và hiển thị các phần của trang. Tuy nhiên, sự khác biệt nằm ở khối lượng công việc mà bước này thực hiện ở bước 2.

Nhờ khả năng hiển thị nội dung, Google Play sẽ định kiểu và bố cục cho tất cả nội dung mà người dùng hiện đang nhìn thấy (nội dung đang hiển thị trên màn hình). Tuy nhiên, khi xử lý câu chuyện hoàn toàn ngoài màn hình, trình duyệt sẽ bỏ qua công việc kết xuất và chỉ tạo kiểu cũng như bố cục cho chính hộp phần tử.

Hiệu suất tải trang này sẽ giống như khi trang chứa các tin bài toàn màn hình và ô trống cho mỗi tin bài ngoài màn hình. Giải pháp này hoạt động tốt hơn nhiều, với mức giảm dự kiến 50% trở lên từ chi phí kết xuất khi tải. Trong ví dụ này, chúng ta thấy thời gian kết xuất tăng từ 232 mili giây lên thời gian kết xuất 30 mili giây. Như vậy là hiệu suất tăng 7 lần.

Bạn cần làm gì để nhận được những lợi ích này? Trước tiên, chúng tôi chia nội dung thành các phần:

Ảnh chụp màn hình có chú thích về việc chia nhỏ nội dung thành các phần bằng lớp CSS.
Ví dụ về việc chia nhỏ nội dung thành các phần có áp dụng lớp story để nhận content-visibility: auto. Xem Bản minh hoạ trên Codepen

Sau đó, chúng tôi áp dụng quy tắc kiểu sau cho các mục:

.story {
  content-visibility: auto;
  contain-intrinsic-size: 1000px; /* Explained in the next section. */
}

Chỉ định kích thước tự nhiên của một phần tử bằng contain-intrinsic-size

Để nhận ra những lợi ích tiềm năng của content-visibility, trình duyệt cần áp dụng vùng chứa kích thước để đảm bảo kết quả hiển thị nội dung không ảnh hưởng đến kích thước của phần tử theo bất kỳ cách nào. Điều này có nghĩa là phần tử sẽ được bố trí như thể là phần tử trống. Nếu không chỉ định chiều cao cho phần tử trong bố cục khối thông thường, thì chiều cao của phần tử sẽ bằng 0.

Điều này có thể không lý tưởng vì kích thước của thanh cuộn sẽ thay đổi, phụ thuộc vào từng câu chuyện có chiều cao khác 0.

Rất may là CSS cung cấp một thuộc tính khác là contain-intrinsic-size. Thuộc tính này chỉ định hiệu quả kích thước tự nhiên của phần tử nếu phần tử đó chịu ảnh hưởng của việc chứa kích thước. Trong ví dụ này, chúng ta sẽ đặt giá trị này thành 1000px để ước tính chiều cao và chiều rộng của các phần.

Điều này có nghĩa là thành phần này sẽ bố trí như thể nó có một thành phần con duy nhất của kích thước "kích thước nội tại", nhằm đảm bảo rằng các div không kích thước vẫn chiếm không gian. contain-intrinsic-size đóng vai trò là kích thước phần giữ chỗ thay cho nội dung được hiển thị.

Trong Chromium 98 trở lên, có một từ khoá auto mới cho contain-intrinsic-size. Khi được chỉ định, trình duyệt sẽ ghi nhớ kích thước được hiển thị gần đây nhất (nếu có) và sử dụng kích thước đó thay vì kích thước phần giữ chỗ do nhà phát triển cung cấp. Ví dụ: nếu bạn đã chỉ định contain-intrinsic-size: auto 300px, phần tử sẽ bắt đầu bằng kích thước hàm nội tại 300px trong mỗi chiều, nhưng sau khi nội dung của phần tử được hiển thị, phần tử đó sẽ giữ nguyên kích thước hàm nội tại được hiển thị. Mọi thay đổi về kích thước kết xuất sau đó cũng sẽ được ghi nhớ. Trong thực tế, điều này có nghĩa là nếu bạn cuộn một phần tử đã áp dụng content-visibility: auto, sau đó cuộn phần tử đó ra ngoài màn hình, phần tử đó sẽ tự động giữ lại chiều rộng và chiều cao lý tưởng đồng thời không quay về kích thước của phần giữ chỗ. Tính năng này đặc biệt hữu ích với các trình cuộn vô hạn, giờ đây, bạn có thể tự động cải thiện ước tính kích thước theo thời gian khi người dùng khám phá trang.

Đang ẩn nội dung bằng content-visibility: hidden

Nếu bạn muốn giữ cho nội dung không được hiển thị, bất kể nội dung đó có trên màn hình hay không, trong khi vẫn tận dụng được các lợi ích của trạng thái kết xuất đã lưu vào bộ nhớ đệm? Nhập: content-visibility: hidden.

Thuộc tính content-visibility: hidden cung cấp cho bạn tất cả các lợi ích của nội dung không được hiển thị và trạng thái kết xuất đã lưu vào bộ nhớ đệm giống như content-visibility: auto ngoài màn hình. Tuy nhiên, không giống như auto, API này không tự động bắt đầu kết xuất trên màn hình.

Điều này giúp bạn có nhiều quyền kiểm soát hơn, cho phép bạn ẩn nội dung của một phần tử và sau đó nhanh chóng hiện những phần tử đó.

So sánh với những cách phổ biến khác để ẩn nội dung của phần tử:

  • display: none: ẩn phần tử và huỷ bỏ trạng thái kết xuất của phần tử đó. Điều này có nghĩa là việc hiện phần tử sẽ tốn kém như việc kết xuất một phần tử mới có cùng nội dung.
  • visibility: hidden: ẩn phần tử và giữ nguyên trạng thái kết xuất. Việc này không thực sự xoá phần tử khỏi tài liệu, vì phần tử này (và cây con) vẫn chiếm không gian hình học trên trang và vẫn có thể nhấp vào được. Hàm này cũng cập nhật trạng thái hiển thị bất cứ khi nào cần thiết, ngay cả khi bị ẩn.

Mặt khác, content-visibility: hidden ẩn phần tử trong khi vẫn duy trì trạng thái kết xuất, vì vậy, nếu có bất kỳ thay đổi nào cần xảy ra, thì chúng chỉ xảy ra khi phần tử hiển thị lại (tức là thuộc tính content-visibility: hidden sẽ bị xoá).

Một số trường hợp sử dụng tuyệt vời cho content-visibility: hidden là khi triển khai trình cuộn ảo nâng cao và đo lường bố cục. Các định dạng này cũng rất phù hợp cho các ứng dụng trang đơn (SPA). Những khung hiển thị ứng dụng không hoạt động có thể vẫn còn trong DOM và áp dụng content-visibility: hidden để ngăn việc hiển thị nhưng vẫn duy trì trạng thái lưu vào bộ nhớ đệm. Nhờ vậy, khung hiển thị sẽ kết xuất nhanh khi hoạt động trở lại.

Ảnh hưởng đến lượt tương tác đến nội dung hiển thị tiếp theo (INP)

INP là chỉ số đánh giá khả năng phản hồi đáng tin cậy của một trang đối với hoạt động đầu vào của người dùng. Khả năng phản hồi có thể bị ảnh hưởng bởi bất kỳ khối lượng công việc nào quá mức diễn ra trên luồng chính, bao gồm cả công việc kết xuất.

Bất cứ khi nào bạn có thể giảm công việc kết xuất trên một trang nhất định bất kỳ, bạn đang tạo cho luồng chính cơ hội phản hồi hoạt động đầu vào của người dùng nhanh hơn. Điều này bao gồm cả hoạt động kết xuất và việc sử dụng thuộc tính CSS content-visiblity khi thích hợp có thể làm giảm công việc kết xuất — đặc biệt là trong quá trình khởi động, khi hầu hết công việc kết xuất và bố cục đã hoàn tất.

Việc giảm công việc kết xuất có ảnh hưởng trực tiếp đến INP. Khi người dùng cố gắng tương tác với một trang sử dụng thuộc tính content-visibility đúng cách để trì hoãn bố cục và hiển thị các phần tử ngoài màn hình, bạn đang cho luồng chính cơ hội phản hồi các công việc quan trọng mà người dùng nhìn thấy. Điều này có thể cải thiện INP của trang trong một số trường hợp.

Kết luận

content-visibility và Thông số kỹ thuật về vùng chứa CSS có nghĩa là một số tính năng tăng hiệu suất thú vị đang áp dụng cho tệp CSS của bạn. Để biết thêm thông tin về các thuộc tính này, hãy xem: