Đề xuất thay thế cho khối xây CSS

Nhóm Chrome muốn xem cách triển khai các bố cục kiểu khối trên web. Tuy nhiên, chúng tôi cảm thấy rằng việc triển khai cấu hình này trong quy cách Lưới CSS như được đề xuất trong bài đăng WebKit gần đây sẽ là một sai lầm. Chúng tôi cũng cảm thấy rằng bài đăng WebKit đã lập luận chống lại một phiên bản khối xây mà không có ai đề xuất.

Do đó, bài đăng này nhằm giải thích lý do Chrome lo ngại về việc triển khai khối xây như một phần của quy cách Bố cục lưới CSS và làm rõ chính xác những gì đề xuất thay thế cho phép. Tóm tắt:

  • Nhóm Chrome rất muốn bỏ chặn khối xây, chúng tôi biết đó là điều mà các nhà phát triển mong muốn.
  • Việc thêm khối xây vào thông số kỹ thuật của lưới sẽ gặp vấn đề vì nhiều lý do khác ngoài việc bạn nghĩ khối xây có phải là một lưới hay không.
  • Việc xác định khối xây bên ngoài thông số kỹ thuật của lưới sẽ không cản trở nhiều kích thước đường đi cho khối xây hoặc sử dụng các thuộc tính như căn chỉnh hoặc khoảng trống, hoặc bất kỳ tính năng nào khác được dùng trong bố cục lưới.

Khối xây có nên là một phần của lưới không?

Nhóm Chrome tin rằng khối xây phải là một phương thức bố cục riêng biệt, được xác định bằng cách sử dụng display: masonry (hoặc một từ khoá khác nên chọn tên phù hợp hơn). Trong phần sau của bài đăng này, bạn có thể xem một số ví dụ về cách hiển thị trong mã.

Có hai lý do liên quan khiến chúng ta cảm thấy khối xây được xác định rõ hơn bên ngoài bố cục lưới – tiềm ẩn của các vấn đề về hiệu suất bố cục và trên thực tế, cả khối xây và lưới đều có các tính năng có ý nghĩa trong một phương thức bố cục nhưng không có ý nghĩa trong phương thức khác.

Hiệu suất

Lưới và khối xây trái ngược nhau về cách trình duyệt xử lý kích thước và vị trí. Khi bố trí một lưới, tất cả các mục sẽ được đặt trước bố cục và trình duyệt biết chính xác nội dung trong mỗi kênh. Điều này cho phép kích thước hàm nội tại phức tạp rất hữu ích trong lưới. Với khối xây, các mục được đặt khi chúng được bố trí và trình duyệt không biết có bao nhiêu mục trong mỗi đường đi. Đây không phải là vấn đề với tất cả các bản nhạc có kích thước nội tại hay tất cả các bản nhạc có kích thước cố định, mà là nếu bạn kết hợp các bản nhạc cố định và nội tại. Để giải quyết vấn đề này, trình duyệt cần thực hiện một bước bố cục trước để sắp xếp mọi mục theo mọi cách có thể để có được kết quả đo lường. Với một lưới lớn, việc này sẽ góp phần gây ra vấn đề về hiệu suất bố cục.

Do đó, nếu bạn có một bố cục khối xây dựng có định nghĩa theo dõi là grid-template-columns: 200px auto 200px (một việc rất phổ biến thường xảy ra trong lưới), thì bạn sẽ bắt đầu gặp vấn đề. Các bài toán này sẽ trở thành cấp số nhân sau khi bạn thêm lưới con.

Có một lập luận rằng hầu hết mọi người sẽ không gặp phải vấn đề này, tuy nhiên, chúng tôi biết rằng mọi người thường có những lưới rất lớn. Chúng tôi không muốn truyền một nội dung có các giới hạn về cách sử dụng khi có một phương pháp thay thế.

Chúng ta làm gì với những điều không có ý nghĩa trong mỗi phương thức bố cục?

Khi flexbox và lưới trở thành một phần của CSS, nhà phát triển thường cảm thấy rằng họ đã hoạt động không nhất quán. Sự không nhất quán mà họ gặp phải là do các giả định được áp dụng từ lâu về cách bố cục hoạt động, dựa trên bố cục khối. Theo thời gian, các nhà phát triển đã bắt đầu hiểu được ngữ cảnh định dạng. Khi chúng ta chuyển sang ngữ cảnh dạng lưới hoặc định dạng linh hoạt, một số thứ sẽ hoạt động theo cách khác. Ví dụ: bạn biết rằng khi đang ở trong Linh hoạt, không phải tất cả các phương thức căn chỉnh đều có sẵn, vì flexbox là một chiều.

Việc nhóm khối xây vào lưới sẽ phá vỡ mối liên kết rõ ràng giữa ngữ cảnh định dạng và khả năng sử dụng của những thứ như thuộc tính căn chỉnh, được xác định trong thông số kỹ thuật Căn chỉnh hộp cho mỗi ngữ cảnh định dạng.

Nếu chúng tôi quyết định xử lý vấn đề về hiệu suất đã nêu trước đó bằng cách làm cho các khai báo theo dõi cố định và hàm nội tại hỗn hợp trở thành bất hợp pháp trong khối xây, bạn sẽ phải nhớ rằng một mẫu rất phổ biến cho bố cục lưới không hoạt động đối với khối xây.

Ngoài ra, còn có các mẫu có ý nghĩa trong khối xây, chẳng hạn như grid-template-columns: repeat(auto-fill, max-content), vì bạn không có hạn chế chéo, nhưng cần phải duy trì không hợp lệ trong lưới. Sau đây là danh sách các thuộc tính mà chúng tôi dự kiến sẽ hoạt động theo cách khác hoặc có các giá trị hợp lệ khác nhau.

  • grid-template-areas: Trong khối xây, bạn chỉ có thể chỉ định hàng đầu tiên theo hướng không phải khối xây.
  • grid-template: Cách viết tắt cần tính đến mọi điểm khác biệt.
  • Theo dõi các giá trị kích thước cho grid-template-columnsgrid-template-rows do sự khác biệt về giá trị pháp lý.
  • grid-auto-flow không áp dụng cho khối xây và masonry-auto-flow không áp dụng cho lưới. Việc hợp nhất các thành phần này sẽ gây ra vấn đề về những thứ không hợp lệ do phương thức bố cục mà bạn đang sử dụng.
  • Lưới có 4 thuộc tính vị trí (grid-column-start và các thuộc tính khác), khối xây chỉ có 2 thuộc tính.
  • Grid có thể sử dụng cả 6 thuộc tính justify-*align-*, nhưng Masonry chỉ sử dụng một tập hợp con như flexbox.

Ngoài ra, bạn cũng phải chỉ định rõ điều gì sẽ xảy ra trong tất cả các trường hợp lỗi mới do nhà phát triển sử dụng một giá trị không hợp lệ trong lưới có khối xây hoặc lưới không có khối xây. Ví dụ: bạn nên sử dụng grid-template-columns: masonry hoặc grid-template-rows: masonry, nhưng không thể sử dụng cả hai cùng một lúc. Điều gì xảy ra nếu bạn sử dụng cả hai cùng một lúc? Bạn phải chỉ định những chi tiết này để tất cả các trình duyệt đều thực hiện giống nhau.

Tất cả việc này đều trở nên phức tạp từ góc nhìn về quy cách, cả ở hiện tại và trong tương lai. Chúng tôi sẽ cần đảm bảo rằng mọi thứ đều được tính đến khối xây, và cho dù đó có hoạt động trong khối xây hay không. Theo quan điểm của các nhà phát triển, điều này cũng khó hiểu. Tại sao bạn cần phải lưu ý rằng mặc dù sử dụng display: grid, một số thứ sẽ không hoạt động do sử dụng khối xây?

Đề xuất thay thế

Như đã đề cập, nhóm Chrome muốn xác định khối xây ngoài thông số kỹ thuật của lưới. Điều này không có nghĩa là nó sẽ bị giới hạn ở một phương thức bố cục rất đơn giản có kích thước cột giống hệt nhau. Tất cả bản minh hoạ trong bài đăng WebKit sẽ vẫn có thể thực hiện.

Bố cục khối xây cổ điển

Khi nhắc đến khối xây, hầu hết mọi người đều nghĩ đến một bố cục có nhiều cột có kích thước bằng nhau. Bạn có thể xác định vấn đề này bằng cách sử dụng CSS sau đây. CSS cần mã ít dòng hơn so với phiên bản đi kèm lưới tương đương.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1rem;
}

Các bản nhạc có kích thước bằng nhau.

Sử dụng kích thước theo dõi loại lưới cho các chiều rộng cột khác nhau

Ngoài vấn đề đã đề cập trước đó với việc định kích thước bản nhạc cố định và hàm nội tại hỗn hợp, bạn có thể sử dụng tất cả kích thước bản nhạc mà bạn yêu thích trong lưới. Chẳng hạn như ví dụ từ bài đăng trên blog WebKit, mẫu các cột lặp lại hẹp và rộng hơn.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, minmax(8rem, 1fr) minmax(16rem, 2fr)) minmax(8rem, 1fr);
  gap: 1rem;
}

Một mẫu đường có kích thước rộng và hẹp.

Kích thước đường ray bổ sung cho khối xây

Ngoài ra còn có các lựa chọn định kích thước kênh khác mà chúng tôi không cho phép trong lưới do thực tế lưới là phương thức bố cục hai chiều. Các hàm này hữu ích trong khối xây, nhưng sẽ gây nhầm lẫn nếu sau đó các hàm này không hoạt động trong lưới.

Tự động điền bản nhạc có kích thước max-content.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, max-content);
  gap: 1rem;
}

Tự động điền các bản nhạc có kích thước auto để tạo các bản nhạc có cùng kích thước và tự động được định kích thước để chứa bản nhạc lớn nhất.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, auto);
  gap: 1rem;
}

Khối xây với thanh theo kích thước tự động.

Cho phép nội dung trải rộng các cột và đặt các mục trên bố cục khối xây

Không có lý do gì để không có nội dung bao gồm các cột trong một quy cách khối xây riêng biệt. Phương thức này có thể sử dụng thuộc tính masonry-track, là cách viết tắt của masonry-track-startmasonry-track-end vì bạn chỉ có một chiều để mở rộng mọi thứ khi ở trong bố cục khối xây dựng.

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, auto);
}

.span-2 {
  masonry-track: span 2; /* spans two columns */
}

.placed {
  masonry-track: 2 / 5; /* covers tracks 2, 3, and 4 */
}

Khối xây có các mục được đặt và đặt.

Khối xây hoặc lưới con thi công đường tường

Điều này có thể được hỗ trợ với một thông số kỹ thuật riêng của khối xây, một lần nữa với điều kiện là không được phép sử dụng các vệt gỗ có kích thước nội tại và có kích thước cố định hỗn hợp. Chúng ta cần xác định chính xác nội dung đó. Chúng tôi không tìm thấy lý do nào mà tính năng này không hoạt động.

Kết luận

Chúng tôi rất mong muốn đi đến phần cụ thể về thông số kỹ thuật có thể được gửi tương tác. Tuy nhiên, chúng tôi muốn thực hiện điều đó theo cách hiệu quả cả hiện tại và trong tương lai, cũng như các nhà phát triển có thể tin tưởng. Cách duy nhất để giải quyết các vấn đề về hiệu suất đã nêu là làm cho vấn đề thứ hai trở nên tệ hơn – đó là việc có các phần của lưới trong khối xây dựng không hợp lệ. Chúng tôi không nghĩ đó là giải pháp hiệu quả, đặc biệt là khi có thể có tất cả các tính năng lưới mà bạn muốn trong khi vẫn tách biệt những tính năng khác nhau một cách rõ ràng.

Nếu bạn có ý kiến phản hồi, hãy tham gia thảo luận trong Vấn đề 9041.

Cảm ơn Bramus, Tab Atkins-Bittner, Una Kravets, Ian Kilpatrick và Chris Harrelson đã xem xét bài đăng này cũng như các cuộc thảo luận giúp đưa ra thông tin.