Nhóm Chrome rất mong muốn thấy được cách triển khai bố cục kiểu xếp kề trên web. Tuy nhiên, chúng tôi cho rằng việc triển khai thuộc tính này như một phần của quy cách CSS Grid như đề xuất trong bài đăng gần đây của WebKit sẽ là một sai lầm. Chúng tôi cũng cảm thấy rằng bài đăng trên WebKit đã phản đối một phiên bản thiết kế xếp kề mà không ai đề xuất.
Do đó, bài đăng này nhằm giải thích lý do tại sao chúng tôi tại Chrome lo ngại về việc triển khai kiểu xếp kề trong quy cách Bố cục lưới CSS, đồng thời làm rõ chính xác những gì đề xuất thay thế cho phép. Tóm lại:
- Nhóm Chrome rất muốn bỏ chặn tính năng xếp kề, chúng tôi biết rằng đây là điều mà các nhà phát triển muốn.
- Việc thêm kiểu xếp kề vào thông số kỹ thuật của lưới sẽ gây ra vấn đề vì nhiều lý do khác ngoài việc bạn có cho rằng kiểu xếp kề là lưới hay không.
- Việc xác định kiểu xếp kề bên ngoài thông số kỹ thuật của lưới không ngăn việc sử dụng nhiều kích thước kênh cho kiểu xếp kề 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 sử dụng trong bố cục lưới.
Có nên sử dụng bố cục xếp kề trong lưới không?
Nhóm Chrome cho rằng kiểu xếp kề phải là một phương thức bố cục riêng biệt, được xác định bằng display: masonry
(hoặc một từ khoá khác nếu bạn quyết định tên khác phù hợp hơn). Ở phần sau của bài đăng này, bạn có thể xem một số ví dụ về giao diện của mã.
Có hai lý do liên quan khiến chúng tôi cảm thấy rằng bố cục xếp kề được xác định tốt hơn bên ngoài bố cục lưới – khả năng xảy ra vấn đề về hiệu suất bố cục và thực tế là cả bố cục xếp kề và lưới đều có các tính năng phù hợp với một phương thức bố cục nhưng không phù hợp với phương thức bố cục còn lại.
Hiệu suất
Lưới và kiểu xếp kề đối lập nhau về cách trình duyệt xử lý kích thước và vị trí. Khi bố trí lưới, tất cả các mục sẽ được đặt trước bố cục và trình duyệt sẽ biết chính xác nội dung trong mỗi kênh. Điều này cho phép định cỡ nội tại phức tạp rất hữu ích trong lưới. Với kiểu xếp kề, các mục được đặt theo cách bố trí và trình duyệt không biết có bao nhiêu mục trong mỗi kênh. Đây không phải là vấn đề với tất cả các kênh có kích thước nội tại hoặc tất cả các kênh có kích thước cố định, nhưng là vấn đề nếu bạn kết hợp các kênh 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 bước bố cục trước khi bố trí mọi mục theo mọi cách có thể để đo lường, với lưới lớn, điều này sẽ góp phần gây ra các vấn đề về hiệu suất bố cục.
Do đó, nếu có bố cục xếp kề với định nghĩa theo dõi là grid-template-columns: 200px auto 200px
(một việc rất phổ biến trong lưới), bạn sẽ bắt đầu gặp vấn đề. Các vấn đề này sẽ tăng theo cấp số nhân sau khi bạn thêm lưới con.
Có một quan điểm cho 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 ta đã biết rằng mọi người có lưới rất lớn. Chúng tôi không muốn phân phối một tính năng có giới hạn về cách sử dụng khi có một phương pháp thay thế.
Chúng ta sẽ làm gì với những điều không hợp lý trong từng phương thức bố cục?
Khi flexbox và lưới trở thành một phần của CSS, các nhà phát triển thường cảm thấy rằng chúng hoạt động không nhất quán. Sự không nhất quán mà họ đang gặp phải là do các giả định lâu nay 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 bối cảnh định dạng lưới hoặc flex, một số thứ sẽ hoạt động theo cách khác. Ví dụ: bạn biết rằng khi ở trong flexbox, 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 đóng gói kiểu xếp kề vào lưới sẽ phá vỡ mối liên kết rõ ràng này giữa ngữ cảnh định dạng và khả năng sử dụng các thuộc tính căn chỉnh được xác định trong quy cách Căn chỉnh hộp theo từng ngữ cảnh định dạng.
Nếu chúng ta quyết định giải quyết vấn đề về hiệu suất được nêu trước đó bằng cách làm cho các định nghĩa về kênh nội tại và cố định kết hợp trở nên bất hợp pháp trong bố cục xếp kề, thì 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 bố cục xếp kề.
Ngoài ra, còn có các mẫu sẽ phù hợp với kiểu xếp kề, ví dụ như grid-template-columns: repeat(auto-fill, max-content)
, vì bạn không có các quy tắc ràng buộc chéo nhưng cần phải giữ nguyên giá trị không hợp lệ trong lưới. Dưới đây là danh sách các thuộc tính mà chúng tôi dự kiến sẽ hoạt động khác hoặc có các giá trị hợp lệ khác nhau.
grid-template-areas
: Trong kiểu xếp kề, bạn chỉ có thể chỉ định hàng ban đầu theo hướng không phải kiểu xếp kề.grid-template
: Chữ viết tắt cần tính đến tất cả sự khác biệt.- Theo dõi các giá trị định cỡ cho
grid-template-columns
vàgrid-template-rows
do sự khác biệt về giá trị hợp pháp. grid-auto-flow
không áp dụng cho kiểu xếp kề vàmasonry-auto-flow
không áp dụng cho kiểu lưới. Việc hợp nhất các lớp này sẽ tạo ra các 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.v.), còn kiểu xếp kề chỉ có 2 thuộc tính. - Lưới có thể sử dụng cả 6 thuộc tính
justify-*
vàalign-*
, nhưng Masonry chỉ sử dụng một tập hợp con như flexbox.
Ngoài ra, bạn cũng sẽ phải chỉ định những 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ó kiểu xếp kề hoặc lưới không có kiểu xếp kề. Ví dụ: bạn có thể 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 lúc. Điều gì sẽ 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 thông tin chi tiết này để tất cả trình duyệt đều làm như vậy.
Tất cả những điều này trở nên phức tạp từ quan điểm về thông số kỹ thuật, hiện tại và trong tương lai. Chúng ta cần đảm bảo rằng mọi thứ đều tính đến bố cục xếp kề và bố cục này có hoạt động trong bố cục xếp kề hay không. Điều này cũng gây nhầm lẫn từ quan điểm của nhà phát triển. Tại sao bạn cần lưu ý rằng mặc dù sử dụng display: grid
, nhưng một số tính năng không hoạt động do sử dụng kiểu xếp kề?
Đề xuất thay thế
Như đã đề cập, nhóm Chrome muốn xác định kiểu xếp kề bên ngoài quy cách lưới. Điều này không có nghĩa là bạn chỉ có thể sử dụng một phương thức bố cục rất đơn giản với kích thước cột giống hệt nhau. Bạn vẫn có thể thực hiện tất cả các bản minh hoạ trong bài đăng về WebKit.
Bố cục xếp kề cổ điển
Khi nhắc đến bố cục kiểu xếp kề, 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 thuộc tính này bằng CSS sau đây. Thuộc tính này cần ít dòng mã hơn so với phiên bản lưới đi kèm tương đương.
.masonry {
display: masonry;
masonry-template-tracks: repeat(auto-fill, minmax(14rem, 1fr));
gap: 1rem;
}
Sử dụng tính năng định cỡ kênh dạng lưới cho nhiều chiều rộng cột
Ngoài vấn đề đã đề cập trước đó về việc kết hợp kích thước nội tại và cố định của kênh, bạn có thể sử dụng tất cả kích thước kênh mà bạn yêu thích từ lưới. Chẳng hạn như ví dụ trong bài đăng trên blog WebKit, một mẫu lặp lại các cột 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;
}
Kích thước kênh bổ sung cho bố cục xếp kề
Có một số tuỳ chọn định cỡ kênh bổ sung mà chúng tôi không cho phép trong lưới vì lưới là một phương thức bố cục hai chiều. Những thuộc tính này sẽ hữu ích trong bố cục xếp kề, nhưng sẽ gây nhầm lẫn nếu không hoạt động trong bố cục lưới.
Tự động điền các kênh 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 kênh có kích thước auto
. Thao tác này sẽ tạo các kênh có cùng kích thước, tự động điều chỉnh kích thước để phù hợp với kênh lớn nhất.
.masonry {
display: masonry;
masonry-template-tracks: repeat(auto-fill, auto);
gap: 1rem;
}
Cho phép nội dung trải dài các cột và đặt các mục trên bố cục kiểu xếp kề
Không có lý do gì để không có nội dung trải dài các cột trong một thông số kỹ thuật riêng biệt về kiểu xếp kề. Thao tác này có thể sử dụng thuộc tính masonry-track
, là viết tắt của masonry-track-start
và masonry-track-end
vì bạn chỉ có một phương diện để mở rộng các thành phần khi ở bố cục kiểu xếp kề.
.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 */
}
Lưới phụ hoặc lưới con sử dụng các kênh lưới
Bạn có thể hỗ trợ việc này bằng một quy cách riêng biệt về kiểu xếp kề, với điều kiện là không được phép kết hợp các kênh có kích thước cố định và nội tại. Bạn cần xác định chính xác giao diện của ứng dụng. Chúng tôi không thấy lý do nào khiến cách này không hoạt động.
Kết luận
Chúng tôi muốn đạt đến một điểm mà thông số kỹ thuật có thể được vận chuyển một cách tương tác. Tuy nhiên, chúng tôi muốn làm điều đó theo cách hoạt động hiệu quả ngay bây giờ và trong tương lai, đồng thời 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 được nêu là làm cho vấn đề thứ hai (vấn đề về việc có một số phần của lưới bất hợp pháp trong bố cục xếp kề) trở nên tệ hơn. Chúng tôi không nghĩ đó là giải pháp tốt, đặc biệt là khi bạn có thể có tất cả các tính năng của lưới mà bạn muốn, đồng thời tách biệt rõ ràng những thứ khác biệt.
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 và các cuộc thảo luận liên quan.