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 việc 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 mạnh mẽ 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 một phần lớn nội dung của bạn nằm ngoài màn hình, việc tận dụng thuộc tính content-visibility sẽ giúp quá trình tải của người dùng ban đầu 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 đại diện cho 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ỏ sẽ giúp tăng hiệu suất kết xuất gấp 7 lần trong lần tải ban đầu. 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 gốc trong Thông số kỹ thuật của 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à "nguyên mẫu giá trị" cho Firefox), nhưng Thông số kỹ thuật của vùng chứa được hỗ trợ trong hầu hết các trình duyệt hiện đại.

Vùng chứa CSS

Mục tiêu chính và bao quát của việc ngăn chặn CSS là cho phép cải thiện hiệu suất kết xuất của nội dung web bằng cách cung cấp sự tách biệt có thể dự đoán được của 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 tập hợp nội dung, cho phép trình duyệt giải thích về nội dung mà không cần xem xét trạng thái bên ngoài cây con. Khi biết được bit nội dung nào (cây con) chứa nội dung riêng biệt, trình duyệt có thể đưa ra quyết định tối ưu hoá để hiển thị trang.

Có 4 loại chứa CSS, mỗi loại là một giá trị tiềm năng cho thuộc tính CSS contain. Các giá trị này có thể được kết hợp 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 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. Tức 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 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 hơn các thành phần con cháu của nó không 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 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 vẽ đảm bảo rằng các thành phần con 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ó gì 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 phần tử đó cũng sẽ không hiển thị. Điều này cho phép chúng ta có thể bỏ qua việc tô màu con cháu 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

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

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ị cung cấp khả năng cải thiện hiệu suất ngay lập tức. Một phần tử có content-visibility: auto sẽ nhận đượ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ử liên quan có thể là các phần tử có tâm điểm hoặc lựa chọn trong cây con), thì phần tử đó cũng có vùng chứa size (và ngừng hiển thị cũng như kiểm thử lượt truy cập nội dung của phần tử đó).

Đ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 của nó sẽ không được kết xuất. Trình duyệt xác định kích thước của phần tử mà không xem xét bất kỳ nội dung nào và trình duyệt sẽ dừng ở đó. Hầu hết các quy trình kết xuất, chẳng hạn như định kiểu và bố cục cho cây con của phần tử đều bị bỏ qua.

Khi phần tử này tiến đến khung nhìn, trình duyệt sẽ không thêm vùng chứa size nữa và bắt đầu vẽ và kiểm thử lần nhấn nội dung của phần tử. Điều này cho phép người dùng thực hiện công việc kết xuất kịp thời.

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

Một trong những tính năng của content-visibility: auto là nội dung ngoài màn hình vẫn có trong mô hình đối tượng tài liệu, do đó cây hỗ trợ tiếp cận (không giống với visibility: hidden). Tức là người dùng có thể tìm và di chuyển nội dung trên trang mà không cần chờ tải hoặc làm giảm 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ử landmark 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 vào khung nhìn. Để ngăn tình trạng này hiển thị 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ụ: một blog du lịch

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

Blog du lịch thường chứa tập hợp các câu chuyện cùng một vài hình ảnh và một số văn bản mô tả. Sau đây là những gì xảy ra trong một trình duyệt thông thường khi 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. Kiểu trình duyệt và bố trí tất cả nội dung của trang mà không cần xem xét liệu 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 sẽ xử lý tất cả nội dung để tìm những nội dung có thể đã thay đổi. Tính năng 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à kết xuất hình ảnh công việc. Việc này sẽ mất nhiều thời gian.

Ảnh chụp màn hình của 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 điều gì sẽ xảy ra nếu bạn đưa content-visibility: auto vào từng tin bài riêng lẻ trên blog. Vòng lặp chung 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 ở lượng công việc thực hiện ở bước 2.

Với chế độ hiển thị nội dung, chế độ này sẽ tạo kiểu và bố cục cho tất cả nội dung mà người dùng đ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 nằm 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 và 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 này chứa toàn bộ các câu chuyện trên màn hình và các ô trống cho mỗi câu chuyện ngoài màn hình. Điều này hoạt động tốt hơn nhiều, với dự kiến giảm 50% trở lên so với 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. Hiệu suất tăng 7 lần.

Bạn cần làm những 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 nhiều phần:

Ảnh chụp màn hình có chú thích về việc phân đoạn nội dung thành các phần có lớp CSS.
Ví dụ về việc phân đoạn nội dung thành các phần bằ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 phần:

.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 thấy các lợi ích tiềm năng của content-visibility, trình duyệt cần áp dụng giới hạn 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ẽ bố trí như thể phần tử trống. Nếu phần tử không có chiều cao được chỉ định trong bố cục khối thông thường, thì phần tử đó sẽ có chiều cao bằng 0.

Đây có thể không phải là phương án lý tưởng vì kích thước của thanh cuộn sẽ thay đổi do phụ thuộc vào từng tin bài 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 kích thước tự nhiên của phần tử nếu phần tử bị ảnh hưởng bởi việc chứa kích thước. Trong ví dụ này, chúng ta đặt giá trị này thành 1000px làm giá trị ước tính cho chiều cao và chiều rộng của các phần.

Tức là API này sẽ bố trí như thể có một phần tử con của các chiều "kích thước nội tại", đảm bảo rằng các div chưa được định 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 kết xuất.

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 kết xuất 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 với kích thước 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ử này sẽ giữ nguyên kích thước nội tại được kết xuất. Mọi thay đổi về kích thước kết xuất tiếp theo cũng sẽ được ghi nhớ. Trên thực tế, điều này có nghĩa là nếu bạn cuộn một phần tử có áp dụng content-visibility: auto rồi quay lại màn hình, thì phần tử đó sẽ tự động giữ lại chiều rộng và chiều cao lý tưởng và không quay lại kích thước phần giữ chỗ. Tính năng này đặc biệt hữu ích cho các trình cuộn vô hạn, mà hiệ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

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

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

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

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

  • display: none: ẩn phần tử và huỷ trạng thái kết xuất của phần tử đó. Điều này đồng nghĩa với việc hiện phần tử đó cũng 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ử đó (và là 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. Trạng thái kết xuất này cũng cập nhật trạng thái kết xuất bất cứ khi nào cần thiết, ngay cả khi trạng thái kết xuất bị ẩn.

Mặt khác, content-visibility: hidden ẩn phần tử trong khi vẫn giữ nguyên 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ì thay đổi chỉ xảy ra khi phần tử đó xuất hiện lại (tức là thuộc tính content-visibility: hidden đã bị xoá).

Một số trường hợp sử dụng phù hợp cho content-visibility: hidden là khi triển khai trình cuộn ảo nâng cao và đo lường bố cục. Chúng cũng phù hợp với các ứng dụng trang đơn (SPA). Khung hiển thị của ứng dụng không hoạt động có thể được để lại trong DOM khi áp dụng content-visibility: hidden để ngăn hiển thị nhưng duy trì trạng thái được lưu vào bộ nhớ đệm. Điều này giúp khung hiển thị nhanh chóng kết xuất khi hoạt động trở lại.

Ảnh hưởng đến lượt tương tác với 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 hoạt động đầu vào của người dùng của một trang. Khả năng phản hồi có thể bị ảnh hưởng khi có quá nhiều tác vụ chạy trên luồng chính, bao gồm cả tác vụ kết xuất hình ảnh.

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ạ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ông việc kết xuất hình ảnh 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 sẽ cho luồng chính cơ hội phản hồi công việc quan trọng mà người dùng thấy được. Đ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ị sẽ có mặt 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: