2 điểm bởi GN⁺ 2024-04-24 | 1 bình luận | Chia sẻ qua WhatsApp
  • WebKit đang kêu gọi phản hồi từ nhà thiết kế và nhà phát triển trong quá trình chuẩn hóa bố cục masonry/waterfall vốn từ lâu đã khó xử lý trong CSS vào CSS Grid Level 3
  • Mô hình được đề xuất hoạt động trên display: grid với grid-template-rows: masonry, tắt việc tạo hàng và để nội dung lấp đầy khoảng trống như các viên gạch
  • Apple cho rằng tính năng này nên nằm trong Grid để có thể kết hợp với các khả năng Grid hiện có như fr, minmax(), max-content, spanning, định vị tường minh và subgrid
  • Cách tiếp cận display: masonry riêng biệt có thể đơn giản hóa việc tách loại bố cục, nhưng trong thảo luận hiện nay có thể bị giới hạn quanh các cột cùng chiều rộng và khó tận dụng khả năng điều chỉnh kích thước track của Grid
  • Sau bản cập nhật tháng 10/2024, CSS Working Group kết luận rằng track có độ rộng biến thiên, định vị tường minh, spanning và subgrid đều đáng để đưa vào masonry và cũng có thể triển khai với hiệu năng tốt, nhưng tranh luận về cú pháp vẫn tiếp diễn

Vị trí hiện tại của CSS Grid Level 3

  • Sau bản cập nhật tháng 10/2024, bản Working Draft chính thức của W3C cho CSS Grid Layout Module Level 3 đã được tạo, trong đó cách hoạt động của bố cục masonry được ghi lại bằng tài liệu
  • Các thành viên của CSS Working Group đi đến kết luận rằng những tính năng sau đáng để đưa vào bố cục masonry và có thể triển khai với hiệu năng tốt
    • track có độ rộng biến thiên
    • định vị tường minh
    • spanning
    • subgrid
  • Tuy vậy, tranh luận về cú pháp vẫn còn bỏ ngỏ, và WebKit tiếp tục chủ đề này trong bài riêng Help us choose the syntax for Masonry in CSS

Vì sao cần bố cục masonry

  • CSS Grid Level 1 được giới thiệu vào năm 2017, giúp giảm gánh nặng về kích thước và sắp đặt của bố cục dựa trên float, còn Grid Level 2 cung cấp Subgrid
  • Nhưng ngay cả sau khi CSS Grid ra đời, câu hỏi “viết bố cục masonry bằng CSS như thế nào” vẫn không có câu trả lời rõ ràng trong suốt 7 năm
  • Bố cục masonry là kiểu sắp xếp trong đó nội dung được đặt đan khít như gạch hoặc tường đá, còn được gọi là waterfall layout
  • Vì có thể xử lý nội dung với nhiều tỷ lệ khung hình khác nhau, nó giúp giảm nhu cầu phải cắt xén hoặc thu nhỏ mọi mục thành cùng một hình chữ nhật
  • Nội dung được phân tán trên toàn bộ trang nên có thể giữ trật tự đọc tự nhiên khi cuộn, và khi thêm nội dung bằng lazy-load ở cuối trang cũng không cần dịch chuyển nội dung hiện có

Lịch sử đề xuất và tranh luận chuẩn hóa

  • Cơ chế tạo bố cục masonry trong CSS lần đầu được Mozilla đề xuất vào tháng 1/2020 như một mở rộng của CSS Grid, và đã được triển khai thử nghiệm sau cờ tính năng trong Firefox Nightly
  • Apple bắt đầu triển khai đề xuất CSS Grid Level 3 trong Safari Technology Preview từ năm 2022, và hiện được bật mặc định
  • Trong CSS Working Group từng có bất đồng về hướng đi cơ bản
    • một số người cho rằng masonry không nên là một phần của CSS Grid mà phải là một kiểu display riêng
    • một số khác chưa chắc bố cục này có thực sự cần cho web hay các website nổi tiếng có dùng hay không
  • WebKit cho rằng để các trình duyệt phát hành tính năng này thì trước hết cần có đồng thuận của CSS Working Group

Cách dùng cơ bản: Grid chỉ dùng cột và tắt hàng

  • Bố cục masonry/waterfall cổ điển có thể được viết bằng cách áp dụng display: grid cho phần tử main, định nghĩa các cột rồi đặt giá trị masonry cho hướng hàng
main {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1rem;
  grid-template-rows: masonry;
}
  • grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)) lặp lại các cột linh hoạt có chiều rộng tối thiểu 14rem
  • gap: 1rem tạo khoảng cách 1rem giữa các cột và các mục
  • grid-template-rows: masonry bảo trình duyệt đừng tạo hàng mà hãy điền nội dung theo mẫu masonry/waterfall
  • Ví dụ này tạo ra một bố cục linh hoạt thích ứng với nhiều kích thước màn hình chỉ bằng bốn dòng CSS, không cần media query hay container query
  • Hiện tại tên giá trị masonry vẫn có thể thay đổi trước khi các trình duyệt phát hành chính thức

Vì sao muốn giữ khả năng định nghĩa cột của Grid

  • Để chứng minh masonry nên là một phần của CSS Grid, WebKit đã tạo bốn demo và có thể thử trực tiếp tại webkit.org/demos/grid3
  • Các demo có thể xem trên trình duyệt hỗ trợ Grid Level 3
  • CSS Grid cung cấp nhiều lựa chọn khi định nghĩa cột
    • kích thước cố định với nhiều đơn vị như px, em, rem, cqi, lh, ch, ic, cap, vw, svh
    • max-content, min-content
    • đơn vị fr
    • minmax()
    • kích thước %
    • auto
  • Ví dụ, có thể để cột đầu và cột cuối có chiều rộng cố định 14ch, còn các cột giữa là cột linh hoạt với tối thiểu 28ch
main {
  display: grid;
  grid-template-columns: 14ch repeat(auto-fill, minmax(28ch, 1fr)) 14ch;
  grid-template-rows: masonry;
  gap: 1rem;
}
  • Kết hợp đơn vị fr với minmax() cho phép tạo độ linh hoạt hai giai đoạn, nơi các cột nở ra và co lại ở những ngưỡng khác nhau
  • max-contentmin-content giúp kích thước cột khớp với kích thước nội dung, mở ra kiểu bố trí khác với cách ép nội dung theo cột
  • Cũng có thể tạo các cột có độ rộng khác nhau bằng dãy Fibonacci như grid-template-columns: 1fr 1fr 2fr 3fr 5fr 8fr;
  • Ví dụ mega menu dùng grid-template-columns: repeat(auto-fill, minmax(max-content, 30ch)); để mỗi cột đủ rộng chứa văn bản liên kết mà không bị xuống dòng
  • WebKit cho rằng thảo luận về display: masonry riêng biệt hiện đang nghiêng về hướng chỉ cho phép các cột cùng kích thước như multicolumn layout ngày nay

Spanning, View Transitions, columnar grid

  • CSS Grid cho phép các mục trải qua nhiều cột, nhờ đó bố cục masonry cũng có thể tạo ra nhiều cấu hình thị giác đa dạng
  • Trong ví dụ, có thể cho mọi ảnh thứ 5 trải qua hai cột, còn các ảnh khác chỉ chiếm một cột
  • Cũng có thể gán lớp wider cho ảnh có tỷ lệ khung hình rộng hơn để chúng chiếm nhiều cột, hoặc biến thể bằng cách đổi góc thành vuông hay giảm khoảng cách về 0
  • Demo Photos kết hợp với View Transitions để khi người dùng nhấp hoặc chạm vào ảnh, ảnh đó sẽ phóng to qua nhiều cột và trình duyệt tự động animate chuyển tiếp
    • Demo này yêu cầu Safari Technology Preview 192 trở lên
  • WebKit xem cốt lõi của Grid Level 3 không phải là mẫu cụ thể mang tên “masonry” mà là cơ chế tắt hàng
  • Cách tiếp cận này tạo ra một columnar grid chỉ gồm cột, đối lập với modular grid của CSS Grid Level 1 vốn căn chỉnh cả hàng lẫn cột

Khác biệt giữa modular grid và columnar grid

  • modular grid là kiểu Grid trong đó nội dung khớp theo cả cột và hàng, và CSS Grid Level 1 rất phù hợp cho loại bố trí này
  • Bố cục dựa trên float cũng khuyến khích việc dùng modular grid trên web vì muốn float được dọn dẹp đúng thì chiều cao nội dung phải khớp nhau
  • Trên các website thực tế, người ta thường làm cho ảnh có cùng tỷ lệ khung hình, làm độ dài văn bản tương đồng, hoặc ép nội dung vào các hộp giống nhau bằng chính sách CMS hay CSS cắt xén và ellipsis
  • columnar grid cho phép giữ nguyên kích thước mong muốn của nội dung và để bố cục vận hành theo nội dung
  • WebKit cho rằng ngay cả nội dung thiên về văn bản cũng có thể được sắp đặt sinh động hơn, chẳng hạn bài mới nhất chiếm bốn cột, một số bài gần đây chiếm hai cột, còn nội dung cũ hơn chỉ chiếm một cột

Kết hợp với Subgrid và định vị tường minh

  • subgrid của CSS Grid Level 2 hiện đã được hỗ trợ trên hầu hết trình duyệt
  • Ví dụ trang bảo tàng cho thấy thay vì liệt kê metadata của thẻ tranh trong một cột căn trái duy nhất, có thể dùng subgrid để đặt năm và số catalog ở bên phải từng thẻ và căn hàng với cùng dữ liệu của các thẻ khác
  • Nếu masonry đi vào CSS Grid Level 3 thì các công cụ dành cho nhà phát triển hiện có cũng tiếp tục dùng được nguyên trạng
    • có thể thử grid-template-rows: masonry bằng Grid Inspector trong Safari Technology Preview
  • Nếu trở thành một kiểu display riêng thì sẽ không tận dụng được lợi ích của subgrid
  • Cũng có thể dùng cùng với định vị tường minh của CSS Grid Level 1; trong ví dụ, grid-column: -3 / -1 được dùng để đặt header ở góc trên bên phải trang, chiếm hai cột cuối
  • WebKit cho rằng chỉ với vài dòng mã bố cục có thể kết hợp các tính năng của Grid Level 1, 2 và 3 để tạo bố cục thay đổi số cột theo không gian sẵn có mà không cần media query hay container query

Điểm tranh cãi với display: masonry

  • WebKit và Apple xem Masonry là một tính năng mở rộng CSS Grid để không chỉ tạo modular grid mà còn tạo được columnar grid
  • Theo hướng này, có thể dùng cùng các tính năng của Grid như định nghĩa cột, track spanning, định vị tường minh và subgrid
  • Bên ủng hộ kiểu display riêng cho rằng như vậy sẽ tách bạch loại bố cục rõ ràng hơn
display: block;
display: inline;
display: flexbox;
display: grid;
display: masonry;
  • CSS Working Group vẫn chưa bàn xong cú pháp cho kiểu Masonry display riêng, nhưng WebKit đưa ra ví dụ về cú pháp giống Multicolumn layout hoặc cú pháp giống Grid nhưng bị giới hạn
main {
  display: masonry;
  columns: 28ch;
}
main {
  display: masonry;
  masonry-columns: repeat(5, minmax(28ch, 1fr));
                   /* where only one repeating width is allowed */
}
  • Một loại bố cục riêng có thể tránh phần công việc cần thiết để tiếp tục làm cho Grid và Masonry hoạt động cùng nhau
    • mô hình bố cục đơn giản hơn
    • trình duyệt dễ triển khai hơn
    • ít khả năng rơi vào bẫy hiệu năng hơn
    • tập tính năng của Grid và Masonry có thể khác nhau
  • Ngược lại, WebKit cho rằng nếu hai kiểu bố cục Grid này được gắn kết với nhau, CSS Working Group sẽ phải định nghĩa các tính năng tương lai cho cả modular grid lẫn columnar grid
  • Ví dụ, nếu CSS Grid Level 4 bổ sung các tính năng như styling cho grid area và grid line, màu nền track, hay rule line của gap, thì tốt hơn là chúng hoạt động trên cả hai loại Grid ngay từ đầu

Nên hiểu “Grid” như thế nào

  • Bên ủng hộ display: masonry riêng cho rằng CSS Grid về bản chất là căn chỉnh hai chiều, còn masonry chỉ căn theo một hướng nên không phải Grid
  • WebKit cho rằng trong lịch sử thiết kế đồ họa, grid là công cụ sắp xếp văn bản, hình ảnh và nội dung theo các mẫu có quy luật để hỗ trợ khả năng đọc và sử dụng
  • Ngay cả trước khi các nhà hiện đại chủ nghĩa ở châu Âu và Mỹ thế kỷ 20 nhấn mạnh việc căn chỉnh cả cột và hàng như một graphic design grid “đúng chuẩn”, vẫn đã có nhiều loại grid khác nhau được sử dụng
  • Mark Boulton cho rằng symmetric columnar grid quá hình thức và nhàm chán, đồng thời khuyến khích dùng asymmetrical compound grid trong web design
  • CSS Grid Level 1 đã giúp tạo asymmetrical grid và compound grid dễ dàng, nhưng hiện điều đó chỉ đúng khi Grid đó là modular grid
  • WebKit cho rằng cả modular grid lẫn columnar grid đều là grid, và CSS Grid cũng nên có khả năng tạo columnar grid

Lời kêu gọi phản hồi dành cho nhà phát triển và nhà thiết kế

  • WebKit kêu gọi nhà phát triển và nhà thiết kế tự làm demo, viết ý kiến trên blog hoặc mạng xã hội, và để lại nhận xét trong các issue của CSS Working Group
  • Những câu hỏi mà WebKit muốn nhận phản hồi gồm
    • “masonry”/“waterfall” có nên là một phần của CSS Grid hay không
    • có cần các khả năng columnar grid gồm subgrid, spanning, định vị tường minh và nhiều kiểu track sizing khác nhau hay không
    • chỉ cần bố cục masonry cổ điển với các cột cùng kích thước có đủ hay không
    • có thực sự sẽ dùng tính năng này hay không, và có thể làm ra những gì
    • có liên kết tới demo đã làm hay không
    • có điều gì mô hình này không làm được hay không
  • Nhóm WebKit đã làm việc về Masonry trong một năm rưỡi, và tính năng này được bật mặc định từ Safari Technology Preview 163 vào tháng 2/2023
  • Họ muốn sớm phát hành tính năng, nhưng trước đó các chi tiết bao gồm cả tên gọi và những câu hỏi mang tính nền tảng cần được giải quyết

Tranh luận về tên gọi: masonry, waterfall, off

  • WebKit cho rằng masonry có lẽ không phải là tên tốt nhất cho giá trị mới này
  • Tên trong CSS thường là những từ đơn giản mô tả trực tiếp kết quả như center, contain, clip, wrap, smooth
  • masonry là một phép ẩn dụ cần giải thích nền tảng nên có thể khó nhớ với các nhà phát triển không dùng tiếng Anh
  • Ở một số khu vực, bố cục này được gọi là waterfall nhiều hơn, nên grid-template-rows: waterfall cũng có thể là một ứng viên
  • WebKit xem tính năng này gần với cơ chế “hãy tạo Grid nhưng đừng tạo hàng” hơn là bản thân kiểu bố cục giống Pinterest
  • grid-template-rows: none; có thể hợp nghĩa, nhưng none đã là giá trị mặc định của grid-template-* với ý nghĩa “không có hàng tường minh, chỉ dùng hàng ngầm định”, nên không thể dùng
  • Một phương án khác được đưa ra là grid-template-rows: off;
main {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  grid-template-rows: off;
}
  • CSSWG đang thảo luận tên gọi tại issue này
  • Hiện tại Safari Technology Preview và các demo đang dùng giá trị masonry theo Editor’s Draft, nhưng tên đó có thể thay đổi trong tương lai

1 bình luận

 
GN⁺ 2024-04-24
Ý kiến trên Hacker News
  • Bối cảnh là những người phụ trách quan hệ nhà phát triển của CSSWG từ các hãng trình duyệt đã thảo luận về cách chính thức đưa bố cục Masonry vào CSS. Cuộc thảo luận này đã kéo dài ít nhất từ năm 2020, khi Firefox lần đầu đề xuất
    Điểm đáng chú ý lần này là phía WebKit đã đưa cuộc thảo luận này ra công khai và kêu gọi nhà thiết kế cũng như nhà phát triển hành động theo kiểu “đăng lên mạng xã hội, viết bài blog”
    Nhìn bề ngoài, việc này có thể trông như một thủ tục mang tính hình thức, nhưng nó có thể trở thành một tiền lệ quan trọng. Vấn đề cốt lõi là nên xử lý mọi tùy chọn bố cục như một phần của CSS Grid, hay tiếp tục bổ sung các thuộc tính CSS Display mới mỗi khi cần
    Cách thứ nhất sẽ làm đặc tả CSS Grid vốn đã phức tạp trở nên phức tạp hơn, còn cách thứ hai có thể làm đặc tả CSS phình to với các thuộc tính và thuộc tính con mới. Dù chọn bên nào thì cũng không dễ như vẻ ngoài

    • Lý do nảy sinh căng thẳng khi đặt Masonry lên trên Grid là vì hai thứ này hoạt động khác nhau về căn bản
      Grid trước hết đặt tất cả mục vào lưới, chẳng hạn như đặt ở col:2,row:3, rồi sau đó mới xác định kích thước lưới. Masonry, lý tưởng mà nói, muốn xác định kích thước track trước rồi mới đặt các mục vào các track đó
      Bản triển khai đầu tiên của Firefox và đặc tả khi đó về cơ bản nói rằng, ngoại trừ hàng đầu tiên và một vài quy tắc phức tạp, các mục Masonry không được tính đến khi tính kích thước track, nên rất dễ xảy ra việc mục làm tràn track
      Đặc tả hiện tại yêu cầu thử đặt mọi mục vào mọi track có thể. Trong trường hợp xấu nhất, mà cũng khá phổ biến, sẽ có hiệu năng bậc hai O(N_tracks * N_items), và hiệu năng bậc hai là tệ[1]; hầu như không có thuật toán bố cục nào khác như vậy
      Nếu thêm cả lồng nhau, hiệu năng sẽ xấu đi theo kiểu gần hàm mũ, và CPU nhanh cũng không tốt. Có thể nói những trường hợp như vậy không phổ biến, nhưng trong các chế độ bố cục CSS, mọi người luôn thử các ranh giới, nên mặc định nó phải nhanh
      Trong Grid, một mục có thể tự xác định kích thước khác nhau tùy theo nó được đặt vào track nào, nên cần thử đặt nó ở mọi vị trí có thể. Để giảm nhẹ vấn đề này, Masonry có thể cần một thuật toán khác cho việc tính kích thước track, nhưng bài blog không bàn đủ về điểm này. Có thể từng tồn tại một phiên bản tính kích thước Grid không phụ thuộc vào vị trí mục, nhưng con thuyền đó đã rời bến rồi
      [1] https://randomascii.wordpress.com/2019/12/08/on2-again-now-i...
    • Grid “không có hàng” hiện khá khớp với đặc tả CSS Grid. Đó là vì có thể tái sử dụng các thuộc tính định nghĩa cột mạnh mẽ và subgrid, và các ví dụ cũng cho thấy khá thuyết phục rằng những tính năng này trực giao với nhau đến mức nào
      Nhìn chung, chỉ cần dùng grid-row-template: masonry là phần còn lại vẫn hoạt động tốt. Đây là điểm hay, và tôi không nghĩ nó khiến bố cục Grid khó dùng hơn hiện nay
      Nhược điểm chủ yếu nằm ở phía những người viết engine trình duyệt. Lý do là tiêu chuẩn để được xem là “hỗ trợ CSS Grid đầy đủ” sẽ cao hơn. Ngoài ra, họ nói rằng cũng có thể tránh được các bẫy hiệu năng khiến một triển khai phải hỗ trợ mọi tính năng của Grid trở nên chậm hơn trong một số bố cục Grid so với khi đặc tả còn đơn giản hơn
      Nếu có một chế độ display riêng, sẽ phải lặp lại đặc tả grid-column cho bố cục Masonry, và như vậy thì đáng tiếc
    • Đây không phải lần đầu một việc như vậy được đưa ra lấy phản hồi cộng đồng. Với bộ chọn CSS lồng nhau họ cũng đã làm theo cách tương tự, và xét về mặt phản hồi thì nó hoạt động khá tốt: https://webkit.org/blog/13607/help-choose-from-options-for-c...
    • Khi khám phá các điểm thỏa hiệp, bạn có thể phải suy nghĩ lại về lựa chọn ban đầu của mình
      Không liên quan trực tiếp đến CSS Masonry, nhưng gần đây tôi đã tạo nguyên mẫu vòng lặp thứ hai của một giao diện có sự căng thẳng tương tự. Vấn đề là nên tăng thêm các kiểu tương tự nhưng khác nhau trong mô hình dữ liệu, hay tăng thêm các sắc thái chi tiết trong kiểu hiện có để hỗ trợ tinh chỉnh
      Lúc bắt đầu, tôi rất nghiêng về phương án sau, nhưng khi thực sự khám phá các lựa chọn, hóa ra việc tiêu thụ một giao diện “phình to” rồi suy luận mã ứng dụng từ kết quả đó lại đơn giản hơn nhiều
      Tôi không có lập trường mạnh về CSS Masonry, nhưng có thể cũng sẽ có một bất ngờ tương tự giữa sự căng thẳng mà mọi người nghĩ theo trực giác và cảm giác khi sử dụng thực tế. Riêng với CSS, chắc chắn khó biện minh cho việc “phình to”, tức là tăng thêm ngữ nghĩa theo từng trường hợp sử dụng, nhưng người dùng cũng có thể có xu hướng thấy các API đậm đặc như Grid khó hơn
    • Việc tiến hành công khai như thế này là tốt. Từ năm ngoái tôi đã liên tục thúc ép tất cả những người liên quan. Phía Chrome là bên tụt lại xa nhất và vẫn chưa hỗ trợ. Firefox có hỗ trợ sau flag
      Tôi đã thử nghiệm trên Firefox và Safari từ năm ngoái và không có phàn nàn gì về triển khai. Có người càu nhàu về vị trí và tên thuộc tính, nhưng cần thừa nhận rằng có lẽ không có lời giải hoàn hảo và nên triển khai theo hướng thực dụng
      Tôi từ chối dùng JavaScript làm triển khai thay thế. Vì vậy phương án thay thế có rất nhiều CSS xấu xí không sắp thứ tự đúng được, nhưng với dự án tôi đang làm thì không phải vấn đề lớn. Hiện tại phần lớn sẽ thay thế bằng JavaScript, nhưng nếu lời giải cho bố cục lại là JavaScript thì ngay từ đầu đã ở thế thua rồi
  • Tôi thật sự không thích bản demo mega menu <https://webkit.org/demos/grid3/megamenu/>, và việc dùng Masonry ở đó trông hoàn toàn không phù hợp. Nó làm rối hướng luồng và phá vỡ kỳ vọng một cách nghiêm trọng
    Thứ tự đọc được mong đợi: https://temp.chrismorgan.info/2024-04-23-masonry-megamenu-2....
    Thứ tự mà demo thực tế đưa ra: https://temp.chrismorgan.info/2024-04-23-masonry-megamenu-1..... Điều này ảnh hưởng đến thứ tự đọc đúng và tab index. Người dùng thị giác trên thực tế hầu như luôn đọc theo thứ tự “sai”
    Rốt cuộc, nó cho thấy đây chỉ là một túi liên kết phi cấu trúc, không có cấu trúc gì cả. Nhưng nếu đi theo thứ tự số thì trông như thể đã có một thứ tự khá logic, rồi bị phá hỏng hoàn toàn vì bị áp Masonry không phù hợp
    Trong ảnh chụp màn hình tôi đã bật “hiển thị số thứ tự mục”. Bình thường nó trông như các cột thông thường không có nền
    Cách triển khai lẽ ra nên dùng cột và thêm break-inside: avoid cho từng section. Demo đã bỏ sót điều này
    Demo báo chí cũng hơi đáng ngờ vì lý do tương tự, nhưng vấn đề nhỏ hơn nhiều
    Với những khối độc lập hơn như phương tiện hình ảnh, nơi thứ tự đọc không ăn sâu đến vậy, bố cục Masonry phù hợp hơn. Dù vẫn có vài điểm hơi mơ hồ quanh tab index, nó không còn rõ ràng là sai nữa

    • Nếu điều đó có nghĩa là cây accessibility và thứ tự tab bỏ qua thứ tự nội dung thực tế rồi duyệt từng cột một, thì tôi xem đó là bug
      Kỳ vọng của người dùng thị giác trong bố cục Masonry là sự tiếp nối theo các hàng trực quan, chứ không phải có tính liên tục giữa các cột. Thứ tự mà bạn nêu là “ngoài dự kiến” cũng đang đi theo điều đó
      Vấn đề có vẻ nằm ở chỗ thứ tự tab bỏ qua thứ tự nội dung gốc và cố bắt chước phần thị giác, và gần như chắc chắn đó là dấu vết còn sót lại từ cách triển khai hiện tại
    • Nếu chỉ xét người dùng thị giác, thứ tự hiện tại có vẻ hợp lý. Cách bạn đề xuất sẽ thường xuyên phải cuộn lên xuống để xem các mục theo thứ tự, và khi thêm mục mới có thể gây ra dịch chuyển bố cục lớn
    • Nếu muốn hiệu ứng Masonry/thác nước thì chẳng phải dùng CSS multi-column layout vốn được hỗ trợ rộng rãi là được sao?
    • Nó chỉ là một demo tùy ý, và có vẻ không liên quan nhiều đến chính khái niệm thu thập phản hồi
  • Điểm hay của tính năng này là khi xem demo trên các trình duyệt không hỗ trợ, tức là tất cả trình duyệt stable hiện nay nếu không bật flag đặc biệt, nó vẫn hiển thị dưới dạng hàng cố định khá hợp lý vì được xây trực tiếp trên Grid layout: https://webkit.org/demos/grid3/
    Trong từng trường hợp, nếu là bố cục Masonry đúng nghĩa thì nhìn sẽ đẹp hơn nhiều, nhưng ngay cả khi không phải vậy thì vẫn đủ dùng. Nếu không thích, cũng có thể dùng feature detection để cung cấp phương án hiển thị thay thế tốt hơn

  • Tôi rất thích tổng thể hình dáng và cảm giác của bố cục Masonry/dạng thác nước. Có lẽ vì tôi lớn lên cùng báo giấy và đến giờ vẫn đọc, nên bố cục dựa trên cột tạo cảm giác như một cách trực quan để chia trang
    Tuy nhiên tôi muốn có lựa chọn thay thế cho cách căn Masonry mặc định. Theo tôi biết, quy tắc cơ bản là “đặt mục tiếp theo vào cột mà nó có thể nằm cao nhất”, và vì vậy từ hàng thứ hai trở đi, thứ tự trái phải bị xáo trộn đáng kể
    Cách tốt hơn mà tôi hình dung là một bố cục bảo toàn nhiều hơn luồng đọc trái→phải, hoặc nếu hướng ưu tiên là phải→trái thì theo hướng đó. Ví dụ như “mục tiếp theo đặt vào cột bên phải của mục trước; nếu đã ở ngoài cùng bên phải thì đưa về ngoài cùng bên trái; và nếu đáy mới không thấp hơn quá nhiều so với ranh dưới của cột bên trái thì có thể đặt mục thứ hai vào cùng cột”
    Nó linh hoạt hơn so với trái→phải nghiêm ngặt nên cũng ít làm hỏng căn chỉnh hơn, đồng thời vẫn giữ được phần nào ý nghĩa của hướng đọc trái→phải
    Masonry không thể bao quát mọi công thức mà người ta có thể ưu tiên, nhưng với nội dung mà thứ tự có dù chỉ một chút quan trọng, chẳng hạn như tạp chí dù có thể không phải Pinterest, tôi cho rằng cách này là mặc định hợp lý hơn so với quy tắc Masonry cổ điển

    • Tôi chỉ dùng bố cục Masonry cho những thứ vốn dĩ không có thứ tự rõ ràng. Có lẽ tôi sẽ không dùng cho ảnh được sắp theo thời gian
    • Vấn đề chính là bản thân việc căn trái→phải. Tôi nghĩ gần như không có cách nào căn trái→phải trong bố cục này mà không phải nhảy qua nhảy lại
      Nếu là bố cục kiểu tạp chí, chẳng phải ta đọc cột từ trên→dưới trước rồi sau đó mới từ trái→phải sao? Trong CSS, điều này đã có thể làm bằng columns hoặc Flexbox hướng dọc
      Một vấn đề khác của bố cục Masonry này là phần đáy lởm chởm. Nếu là tạp chí thì có lẽ người ta sẽ căn đều, và điều này cũng có thể làm bằng cột hoặc Flexbox
      Trên web dường như có một giả định ngầm rằng nội dung cuộn vô tận nên hình dạng ở cuối trang không quan trọng. Nếu vậy thì đó không hẳn là một giả định đáng khuyến khích
    • Nếu làm như thế này thì sao:
      { /* khi cập nhật, chỉ di chuyển phần tử sang trái hoặc phải tối đa 2 cột */ grid-template-max-horizontal-shift: 2 col; }
  • Nếu giả sử có thể tạo ra một hệ thống không tương thích ngược để thay thế CSS thì nên làm thế nào?
    Có cuốn sách hay bài nghiên cứu nào về cách tạo ra một hệ thống layout nhất quán không?
    Các phương án thay thế như Qt, Tk, SwiftUI thì sao? Ngoài CSS ra thì tôi chưa từng dùng cái nào. Nếu trong các hệ thống đã được triển khai rộng rãi thực sự có cái tốt hơn, thì điều gì khiến nó tốt hơn?
    Tôi muốn một hệ thống mang lại giao diện tốt hơn cho lập trình viên, nhưng không biết nên làm thế nào. Nếu có thể bắt đầu lại từ đầu, các nguyên tắc thiết kế nên là gì?

    • Không hẳn là chống CSS, nhưng có thể đáng quan tâm đến các khái niệm như nhóm kích thước, chu kỳ yêu cầu-cấp phát kích thước có thể dự đoán, chiều rộng phụ thuộc vào chiều cao, layout dựa trên ràng buộc và căn chỉnh. Và nhìn chung cần dọn dẹp sự rối rắm của các khái niệm bị đan xen không trực giao trong CSS
      Thuộc tính nên tường minh và tách bạch hơn. Loại bỏ những trò vô lý như margin âm, và mọi khoảng cách nên được tạo thành nhiều cấp. Ví dụ như padding = max(el.paddings[])
      Hộp biên nên được làm tường minh, còn đường viền nên trở thành một phần tử đúng nghĩa. Bản thân box model không tệ; CSS mới là thứ triển khai nó một cách khủng khiếp. Nó đầy những bùa chú mong manh mà cứ đụng vào là 99% sẽ vỡ, cùng các giới hạn phi lý, và chính những giới hạn đó lại sinh ra thêm nhiều vấn đề và “giải pháp”
    • Layout dựa trên ràng buộc dùng thuật toán Cassowary từng có vẻ là một phương án thay thế phổ biến trong một thời gian: https://github.com/slightlyoff/cassowary.js/?tab=readme-ov-f...
      Cách này được thiết kế để giải quyết sự thay đổi về kích thước và hình dạng màn hình. Apple đã chuyển sang SwiftUI và có thể đã rời khỏi cách tiếp cận này
    • Sẽ rất thú vị nếu có một bài viết so sánh nhiều hệ thống styling/layout. Tuy vậy, có lẽ không nhiều người đã trải nghiệm nhiều ngôn ngữ styling, nên cũng không có nhiều người có thể viết được bài như vậy
      Flutter và XAML cũng có vẻ đáng để xem xét
    • Một điểm cần lưu ý khi chọn tiền lệ để tham khảo là CSS đặt tiêu chuẩn khá cao về điều khiển khai báo. Tôi không thể nói chi tiết về những thứ đã được nhắc đến, nhưng các tiền lệ có thể so sánh tốt hơn có lẽ nên được tìm trong các use case về in ấn
    • Có vẻ cuốn sách kinh điển về chủ đề này là "Rastersysteme für die visuelle Gestaltung - Grid systems in Graphic Design". Tôi chưa đọc
  • Đăng lại thành bình luận cấp cao nhất để dễ thấy hơn
    Tôi có một website ảnh và không dùng JavaScript cho layout. Khi xây dựng, tôi đã xem xét các thư viện JavaScript Masonry nhưng kết quả không làm tôi hài lòng
    Một layout Masonry đúng nghĩa, thực sự lấp đầy mọi không gian khả dụng, sẽ cắt bớt một số ảnh. Nếu muốn giữ tỷ lệ khung hình mà không cắt, phải để lại khoảng trống quanh ảnh. Cách duy nhất để không làm vậy là cuộn vô hạn, và có lẽ đó là điều các cỗ máy gây nghiện kiểu doanh nghiệp muốn, nhưng không phải điều tôi muốn trên website của mình
    Tôi đã làm như thế này:
    https://yakubin.com/photography/albumless/
    https://yakubin.com/photography/album/kenya-2023/
    Để đạt được kết quả này, tôi dùng display:inline-block, về cơ bản coi ảnh như văn bản cần được reflow sang dòng mới. Tôi rất hài lòng với kết quả và thích cách này hơn cách mà các thư viện Masonry làm

    • Layout này có lẽ có thể được triển khai chỉ bằng vài dòng CSS với Flexbox hướng hàng có xuống dòng và căn giữa. Đó cũng là cách chuẩn hơn
    • Tôi không dùng JavaScript cho layout Masonry. Tôi đặt fallback bằng một giải pháp CSS được hỗ trợ trong các giải pháp Masonry CSS hiện tại
      Vấn đề là thứ tự. Nếu thứ tự không quan trọng thì các giải pháp chỉ dùng CSS hiện nay cũng hoạt động tốt. Tuy nhiên, nếu nhớ không nhầm thì phần dưới các cột có thể để lại hình dạng kỳ lạ
    • Những layout như thế này chính là mục đích mà Flexbox được thiết kế, nên nó cũng có thể là một lựa chọn ở đây
  • Liên quan đến chủ đề này, tôi đã làm một demo tương tác về các nguyên lý Grid:
    https://cssprinciples.com/3/grid/

  • Đã có float truyền thống, lại có cả các layout hiện đại như Flexbox và Grid, nên cũng thắc mắc liệu có đúng khi cứ tiếp tục thêm các tùy chọn “layout” vào CSS hay không
    Nếu vẫn còn những trường hợp chưa được bao quát, có thể một giải pháp tốt hơn là có một hệ thống dựa trên ràng buộc cuối cùng, dù phức tạp hơn, bao quát mọi trường hợp layout. Khi đó các framework CSS và thư viện tiện ích có thể xây dựng Masonry Grid thế hệ tiếp theo, v.v. trên nền tảng đó

    • Tôi hoài nghi liệu một hệ thống ràng buộc có thực sự được xem xét hay không. Từ trước đến nay CSS luôn nhắm mạnh tới khả năng dự đoán chi phí layout
      Dù vậy, đề xuất Houdini layout là thứ gần nhất với ý tưởng này. Đó là cách chuyển layout sang một ngữ cảnh JavaScript được cô lập: https://github.com/w3c/css-houdini-drafts/blob/main/css-layo...
      Nhưng nói thật, vì Flexbox, Grid và những thứ như containment đã giải quyết rất nhiều vấn đề, nên nhu cầu cải tiến đã giảm đi nhiều so với thời trước Flexbox
    • Cốt lõi của động thái này là ngừng dùng các mẹo float cũ kỹ hoặc các mẹo CSS Grid/Flexbox rồi cũng sẽ sớm lỗi thời. Masonry layout của Firefox thực ra được thêm bằng một thuộc tính mới để gập các hàng Grid, nên về bản chất nó được triển khai theo hướng bao quát mọi trường hợp layout
    • Đây là Grid level 3. Có thể làm như thế này:
      display: grid;
      grid-template-rows: masonry;
      Tuy nhiên nó bị giới hạn ở WebKit. Tôi từng triển khai trong chế độ gallery của news feed cá nhân, rồi đã bỏ từ tháng 10/2023
    • JavaScript là hệ thống layout tối hậu. Không ngôn ngữ khai báo nào có thể xử lý mọi ca sử dụng. May là từ khi có Grid, hiếm khi phải phụ thuộc vào JavaScript
      Một hệ thống dựa trên ràng buộc có vẻ sẽ nằm lưng chừng một cách gượng gạo giữa Grid và JavaScript, nên tôi không rõ nó có giúp được nhiều không
    • Nếu có yêu cầu mà CSS layout không hỗ trợ trực tiếp, lúc nào cũng có thể tạo layout bằng JavaScript
  • Tôi đã dùng cái này rồi. Trên Firefox thì bật trong tùy chọn và dùng cho bookmark. Trên mobile thì không thành vấn đề vì đơn giản là chúng xếp chồng từ trên xuống dưới. Trên mobile không có about:config
    Ảnh cuối là trạng thái đã tắt
    https://imgur.com/a/o7OyZEW

    • Theo tôi hiểu, vì quy tắc Masonry layout ưu tiên lấp chỗ trống cao nhất theo từng hàng, nên sẽ tạo ra căn chỉnh không đều. Nhưng về mặt thị giác thì trông như được căn theo cột
      Vì vậy khi thay đổi kích thước cửa sổ, thứ tự bookmark sẽ thay đổi
    • Hãy thử Firefox Beta trên mobile xem :)
  • Có thể xem thêm nhiều bối cảnh hơn và lập luận phía đối lập, tức vì sao display: masonry tốt hơn display:grid + grid-template-rows: masonry, tại đây: https://github.com/w3c/csswg-drafts/issues/9041