w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.42k stars 649 forks source link

[css-grid-3] Designer/developer feedback on masonry layout #10233

Open jensimmons opened 4 months ago

jensimmons commented 4 months ago

We just published an article about Grid Level 3 / Masonry layout on webkit.org, https://webkit.org/blog/15269/help-us-invent-masonry-layouts-for-css-grid-level-3/, and at the end of the article, we asked web designers and developers to weigh in with their thoughts.

We opened this issue to provide a place for people to leave their input after reading the article, to especially answer these questions:

What do you think? Try it out. Write about it on your own blog. Describe what you do and don’t like about current implementations. Create some demos of your own to explore what else is possible.

  • Should “masonry”/“waterfall” be part of CSS Grid or a separate display type??
  • Do you want the capabilities to define a single-axis grid with CSS Grid — to use subgrid, spanning, explicit placement, and combining different track sizes? Or do you only want the ability to define a classic masonry layout with equal-sized columns?
  • Will you use this at all? What might you do with it?
  • Do you have links to demos you’ve made? We want to see your ideas and use cases.
  • Are there things you want to do that you can’t do with this model?

If you are finding this issue through the typical CSSWG channels, please read the article before commenting. It provides 4,000 words of context.

TALlama commented 4 months ago

I used the Masonry jQuery plugin back in the day for a few things, and I've missed it in a number of places since then. I've even built similar systems with JavaScript and CSS Grid, by defining absurd numbers of rows and dynamically calculating a row span for each item, which allowed me to do some of the neat column-spanning and column-picking seen in Jen's examples.

Extending CSS Grid with "masonry rows" seems like a great idea to me, and the right place for it. That would allow us web devs to grow our existing knowledge as the possibilities grow, and to leverage our existing code and understanding as we do so. We've already seen how flexbox and grid are (wrongly) viewed as competitors; adding yet another fundamental layout would just confuse things more. Empowering the layouts we have is the better option.

hermosawave commented 4 months ago

I agree that masonry is a type of grid and should be implemented as such. I also used the Jquery plugin back in the day, it would be nice to have this functionality in CSS. I've had to implement a sub-optimal version of this as a result.

chrisarmstrong commented 4 months ago

I think masonry (or whatever it ends up being called) should be a part of CSS Grid, for a few reasons:

~

Side note: One thing we've discovered over the past 10 years has been the importance of being able to intuitively predict how a masonry grid will re-flow when content is added to or rearranged within it. Let’s say you have a Pinterest-style image grid, and you load in an additional 50 items... if all the existing items suddenly jump around and switch columns etc that gets really disorienting for users. Same goes for making an element span multiple columns... you don’t expect that to suddenly rearrange the entire grid, simply the content below that element (like upside-down Tetris). I’m hopeful CSS grid’s ability to specify a column position will help with this, which is another reason to build on the existing Grid spec.

DanielHeath commented 4 months ago

Key thoughts on this proposal:

1) Should this be part of CSS grid? I agree it should, if (and only if) it can be implemented orthogonally to other grid features. By that, I mean it should do something sensible when combined with every other grid option. If that's not likely to happen (consistently, in each browser), I don't think it should. This really needs to have a suite of conformance test pages fairly early on.

1) It's unclear whether grid-template-columns would be equally supported - IMO not doing so would be a serious mistake, because everything else in grid works equally on either axis

2) I've seen various requirements RE the slot fill order for masonry layout. grid-auto-flow doesn't appear to work with masonry layout in safari tech preview.

2) Other grid features: Spanning and track sizing are very common requirements. I struggle to think of a sensible way to use explicit placement with masonry, although I'm sure someone will. Subgrid might be useful with spanning, although it feels very complex and I'd expect implementations to vary sufficiently that I probably couldn't rely on it for authoring.

2) Spanning columns is of virtually no use (I'll still end up having to use JS or something anyways) without a way to control how the extra whitespace this creates is positioned (eg I set justify-content: space-between; align-content: space-between, but the extra whitespace all ends up below the image - see image).

Minor nits on the demo at https://webkit.org/demos/grid3//photos/ :

charlesmunson commented 4 months ago

I've worked with CSS for what, twenty years, and been a web dev since 1995. Yes, we want this. Masonry layout would solve so many problems for my art and photography websites. Even today I had to fire up Gimp to resize photos for different aspect ratios.

LorenAmelang commented 4 months ago

I see Jen's promotion of this in my Fedi feed, and I just tried some of her demos, especially the photos demo. I guess my concern is not particularly with 'Masonry' but with the 'modern' trend toward web pages designed for huge screens. I have two main routes (limited by lousy vision). The smallest iPhone, where after a confusing delay the photos demo reverted to a vertical scroll of single images (that didn't seem connected to the grid images I'd been able to see). And a 1920x1080 Linux view where what's left of the browser window after headers and toolbars took about a minute to fill up with one-third of the full example - many images a half-inch across. Scrolling to the other 2/3 happened painfully slowly, with the image grid filling in random order.

Maybe I missed it, but is there any 'Responsive' technology being discussed to make these new web features work for people who don't have the huge screen area to take advantage of them? Or for people dependent on Alt text? WAVE shows no Alt text at all in the demo. And if there was, a grid of 51 images would be a bit much to navigate...

In that vein, WAVE finds no headings! "Headings ... provide important document structure, outlines, and navigation functionality to assistive technology users." There really needs to be some rational structure within the page for those of us who can't just glance at the whole wall of images at once!

If someone knows a better place to post this issue, please suggest!

LorenAmelang commented 4 months ago

@DanielHeath Just noticed this: There's heaps of CLS on a slow connection because the img tags lack an aspect-ratio

Is that why my view loaded so slowly? Granted I'm at the far end of 30 miles of WISP radio, but my 10 Mb usually loads web pages in milliseconds, not minutes.

SaraSoueidan commented 4 months ago

Anyone who's been a part of the dev community long enough and who has been talking and listening to designers and developers in the community knows that we do want masonry layout. We may not all be working on "big websites", but we are the ones building the Web.

I cast an additional vote to including masonry as part of the CSS Grid layout system, not a separate display value, for all the reasons @jensimmons mentioned in the article. All of them.

I have been waiting for this layout for to become possible in CSS for years. And it only makes sense that we get enough control over it like we would with other layouts. I believe one of the reasons CSS Columns are not as widely used as one would hope is because they are limited and not flexible. We do want control over column widths. And it only makes sense that Grid Level 3 be able to leverage all the capabilities of Grid Level 1 and Level 2.

Thank you Jen and the Webkit team for pushing to make this feature actually usable.


UPDATE: I've read Rachel Andrew's post which explains the alternative proposal for Masonry. I think this post was a much-needed clarification.

Seeing that both proposals would give us the flexibility to design and implement the layouts in Jen's post, I no longer have a strong preference as to which property or spec Masonry goes into. As a developer, I want the flexibility to build creatively. Whichever way we get to do that will be welcome. I appreciate everyone involved in this discussion and who is working to push this feature forward.

tomchiverton commented 4 months ago

Masonry, however implemented, should exist. Photo albums would be a use case I would put this too. Non-symetric would be nice to have because of a mix of aspect ratio.

michaeltugby0 commented 4 months ago

We recently implemented a masonry grid as part of our website's dashboard, which held a list of infinite-scrolling cards, and we opted to use CSS Grid for it because we wanted control over the columns (using grid-template-columns: repeat(auto-fill, ...)) like you mentioned. For the rows, for now, we used a bit of JS to give them all a grid-row: span ... based on each childs height. It's definitely something I'd love to have to be able to progressively enhance this behaviour and remove the need for JS.

In general, it would also be much easier to progressively enhance too in grid. Just add a grid-template-rows: masonry, if it's not supported, no problem, we get the default grid row generation with cards stretching to fit, which is what I would want as the fallback. Whereas with display: masonry, that would most likely require an @supports and/or duping layout rules.

chriskirknielsen commented 4 months ago

While I already agree with everything mentioned, just adding my own thoughts below:

I've recently shipped a project that could have made great use of masonry layout for a "mega menu". We ended up using standard multicol to get a similar behaviour, but each group has to be manually placed to optimise how much space they take (some have 2 sub-items, other have 8), so it ends up being tedious to place all the pieces. Masonry would make that very easy and solve common layout problems on many projects.

As far as the display debate, I'd be in favour of keeping everything as grid. This allows me to remember a single set of properties that work consistently, simply expanding what I know instead of learning new rules, and to easily switch between the behaviours should I need to revert — or more likely, progressively enhance an existing grid.

Regarding the naming, the obvious alternative is columnar but holy heck would that be confusing: grid-template-rows: columnar (and if you read further ahead in my comment, would grid-template-columns also be columnar…?). I like the off idea, short and sweet, though I could also see something like:

Finally to piggyback on @DanielHeath's comments:

It's unclear whether grid-template-columns would be equally supported - IMO not doing so would be a serious mistake, because everything else in grid works equally on either axis

I am wondering about this too. While I wouldn't need it as much, I'd definitely like that flexibility.

And a nitpick of my own:

There's heaps of CLS on a slow connection because the img tags lack an aspect-ratio

Not only the lack of width/height (which, ironically, I now consistently do because of Jen's push on that some years ago 😄) but also the 1MB+ PNGs in the article can easily be optimised.

TL;DR: Overall, feeling very positive about all of this!

keller-mark commented 4 months ago

Should “masonry”/“waterfall” be part of CSS Grid?

As part of CSS yes, but I am more agnostic about whether it should be part of grid vs. a different display mode.

It seems to me the main pro for being part of grid would be that the fallback behavior would be more reasonable.

Are there things you want to do that you can’t do with this model?

The article only discusses (and shows demos of) a column-based / vertical orientation. However, the feature should also support row-based / horizontal orientation for a use case like the Flickr gallery layout:

Even if not supported initially, the syntax should be designed with this future possibility in mind, so

display: masonry-columns (or display: masonry; masonry-direction: columns) as opposed to simply display: masonry. The grid-template-rows: off would also be sufficient.

EDIT

It was pointed out by @rileybathurst in a comment below that the demo includes two Horizontal options: Horizontal Masonry and Horizontal Flexbox.

Screen Shot 2024-04-27 at 11 07 23 AM

However there are nuances to the Flickr version that differ from both of these:

The big difference with the Flickr masonry is that the heights of the rows are dynamic based on the aspect ratios of the bricks in each row. The CSS masonry should also support this option to have dynamic row height (in the case of Flickr) or dynamic column width (in the case of the column-based support described in the blog post) based on the aspect ratios of the contents, so that the ends of the rows/columns are flush with the right/bottom sides of the container, respectively, and the clipping of brick contents is avoided.

brandonmcconnell commented 4 months ago

I think keeping everything part of grid would be simplest in terms of use with other properties.

chartgerink commented 4 months ago

Hi 👋 Thanks for the opportunity to share some thoughts - I really liked the article and it comes at a fantastic time as we are doing redesigns of our website. This has been inspirational!

Should “masonry”/“waterfall” be part of CSS Grid?

Yes.

Do you want the capabilities to define a columnar grid with CSS Grid — to use subgrid, spanning, explicit placement, and all the many options for track sizing? Or do you only want the ability to define a classic masonry layout with equal-sized columns?

Variable column sizes would be preferable. These allow for wider range of design options, and I would expect it to not be an uncommon design pattern. The use of subgrid would also be a fantastic capability that I would prefer to see included.

Will you use this? What might you create with it?

We offer users a way to curate (research) works and are looking to provide them with a visually appealing, dynamic, and scalable way to present the curated content. We want to provide them with an option to present their curated works in magazine/print quality layouts, without having to put in much work to do so. The columnar grid would be perfect for this.

Are there things you want to do that you can’t do with this model?

I also wondered about horizontal options, similar to a previous comment raised. I can imagine this also to be an interesting design element if at all possible.


I have not previously contributed to a W3C discussion, so if I missed anything in how to contribute, I am happy to expand further upon request 😊

kitgrose commented 4 months ago

I prefer this being part of CSS Grid too.

If all the columns are intended to be the same width, it makes this feature feel very similar to the columns behaviour—one container separated into multiple columns—albeit with children flowing across the columns rather than down them. In fact, it feels somewhat related to the column-fill: balance property, since it's similarly attempting to pack each column evenly.

If this was to be implemented as a new display style where all the columns were the same width, it should also support the use of the order property, which provides a lot more flexibility in responsive layouts to get elements balanced nicely.

In any case, if it doesn't end up being implemented as part of Grid, you can expect that authors will often embed grids inside each element to align captions, etc., which seems inherently more work for the UA to handle than a single shared base grid accessed through subgrid.

Some usage scenarios that would benefit me:

desandro commented 4 months ago

Hi! Author of the Masonry JS library here 👋 . I am stoked to see Jen and the WebKit team prioritize making Masonry a first-class citizen in the browser. My heart-felt gratitude ❤️

Custom track sizing vs uniform column width

In my experience, the vast majority of users want uniform column width. CSS grids provide so much power over layout with track sizing. I think that amount of customization over the tracks is an unwanted feature when working with masonry layouts. Typically with a masonry layout, you want the item to have the same size regardless of its position in the grid. So, if you want to be practical, go with display: masonry, this will satisfy 95% of masonry layout usage.

"display: masonry" vs "grid-template-rows: masonry"

Having said that, grid-template-rows: masonry maps to my mental model of how Masonry works, now that CSS grid is an established convention. Personally, I'd like to see "masonry" used as the value name, as it's the convention with 14 years of history. I could also go with grid-template-rows: collapse, as it describes the behavior better.

Follow-up issues

Here are some issues that I know will come up. I don't think they need to be solved in this spec/implementation. But they are worth thinking about during this concepting phase.

Loading images

Day 2 issue for implementing a Masonry layout is dealing with shifting layout caused by loading images. With a masonry layout, the problem is exacerbated as taller cell element causes subsequent cells elements to move to a different column. The issue is best address by setting aspect-ratio or better yet width and height attributes on the <img>. I'd say it's outside the scope of this proposal to solve for unloaded images in the spec. But, the issue should be addressed in documentation.

Expanding cells and maintaining position

@chrisarmstrong mentions above:

One thing we've discovered over the past 10 years has been the importance of being able to intuitively predict how a masonry grid will re-flow when content is added to or rearranged within it.

The classic Masonry layout will shift a newly expanded cell element to the next possible position

https://github.com/w3c/csswg-drafts/assets/85566/ce4a8746-d2a1-4fc9-8e96-f069e50870c2

But users just want the item to open up where they clicked it. I actually had to build a separate layout library, Packery, with a bin packing algorithm to solve for it

https://github.com/w3c/csswg-drafts/assets/85566/4bea6f9f-abff-480d-ad50-195c0bfcb09f

Maybe something like grid-row: maintain could address this

Keeping horizontal order with a masonry layout

A good amount of people requested that Masonry have more leeway in its layout algorithm so that horizontal order could be maintained. I eventually added a horizontalOrder option to Masonry.

WQVtdGp


Thrilled to see this work. I'll be following this thread merrily.

jeff-wolff commented 4 months ago

Yes. Seems like the logical progression of CSS grid. Something that shouldn't be done with JavaScript anymore.

scriptype commented 4 months ago

Hi all, while reading the article, I thought about the possibility of having the masonry as a new display value that can sufficiently interoperate with grid properties, like the flex currently does (e.g. gap, justify-* / align-*).

This would perhaps ease the mental model for developers and designers, and perhaps simplify the browser implementations, since it will not automatically (and possibly incorrectly) force every grid feature to work with the proposed masonry mode. Instead, the masonry could grow its own vocabulary free of other grid features.

But on the other side, the new display type would just work™ with the most relevant parts of the grid layout (e.g. fine control over columns, gap).

I personally have no strong preference/opinions on either way. Masonry in any form would be a leap forward.

Also, I think the spec should warn us of possible accessibility pitfalls, like:

Maybe I missed it, but is there any 'Responsive' technology being discussed to make these new web features work for people who don't have the huge screen area to take advantage of them? Or for people dependent on Alt text? WAVE shows no Alt text at all in the demo. And if there was, a grid of 51 images would be a bit much to navigate...

In that vein, WAVE finds no headings! "Headings ... provide important document structure, outlines, and navigation functionality to assistive technology users." There really needs to be some rational structure within the page for those of us who can't just glance at the whole wall of images at once!


Thanks! 💛

p.s. Just found a much better explanation to the idea of "segregation with some interoperability" here (from @rachelandrew): https://github.com/w3c/csswg-drafts/issues/9733#issuecomment-2070382976

dougalg-js-tw commented 4 months ago

I recently came across a use-case at work where we want a 2-column layout on desktop, and a single column on mobile. But we want the top item of the right column to be "in the middle" of the single column, and the bottom item of the right column to be at the bottom of the single column like so:

image

Currently as far as I know there is no way to achieve this in CSS, but with masonry grid it is quite simple to achieve, as shown in this codepen:

https://codepen.io/dougalg/pen/GRLPZea

The benefits of grid here are ability to pull items naturally into different columns following the standard grid syntax, and doing so allows to maintain tab order easily to achieve the desired flow both on mobile and desktop.

seyedi commented 4 months ago

Lots of devs seem to find CSS Grid difficult to understand and use. They'd love a super easy way to do Masonry, like this:

main { 
  display: masonry;
  columns: 28ch;
}

But this other way, with all the brackets and stuff, is almost as scary as CSS Grid syntax itself, so I wouldn't go for it:

main {
  display: masonry;
  masonry-columns: repeat(5, minmax(28ch, 1fr)); 
                   /* where only one repeating width is allowed */
}

However we will eventually need those extra syntax for more controls, so...

For the reasons Jen mentioned, I'm all for adding masonry to CSS Grid layout.

DanielHeath commented 4 months ago

@desandro That's a great point RE horizontal order - eg item 11 in the mega-menu demo being positioned to the right of item 12 is correct, but looks totally wrong (see screenshot).

image
oscarotero commented 4 months ago

I think masonry should have its own display value instead of being integrated in the grid spec. Reasons:

kbrilla commented 4 months ago

Please, mayby create an questionnaire like with nesting, to gather more votes on the matter.

txdm commented 4 months ago

Lots of devs seem to find CSS Grid difficult to understand and use. They'd love a super easy way to do Masonry, like this:

main { 
  display: masonry;
  columns: 28ch;
}

But this other way, with all the brackets and stuff, is almost as scary as CSS Grid syntax itself, so I wouldn't go for it:

main {
  display: masonry;
  masonry-columns: repeat(5, minmax(28ch, 1fr)); 
                   /* where only one repeating width is allowed */
}

However we will eventually need those extra syntax for more controls, so...

For the reasons Jen mentioned, I'm all for adding masonry to CSS Grid layout.

I believe both could be made to work, eg: masonry-columns: 28ch for a simplified/shorthand version, or masonry-columns: repeat(5, minmax(28ch, 1fr)); if someone wants to be more specific.

I think it should be masonry-columns instead of just columns to disambiguate it from the existing columns

saivan commented 4 months ago

I know there was no mention of column masonry layouts, I'm just wondering "why not". I'm all for display: grid being extended, it's also quite logical in my view. I think the proposed syntax is a logical syntax, you're effectively independently defining a masonry layout in either direction. One difficulty for me would be, how should the following behave?

display: grid;
grid-template-rows: masonry;
grid-template-columns: masonry;

This could be a messy layout as follows:

image

Or should this be an error condition? If this shouldn't be allowed, it would be a slight problem for me, because it seems to break the line independence of css. Now by adding line 3, you've effectively broken the way line 2 should work. So this case would need to lead to a reasonable layout.

But then my question would be, is this still a grid?

Also, how do I specify the layout direction, because this would also be a valid way to lay out the exact same boxes:

image

Then we have problems of "how we should align them" or how they should be reflowed to fill the available space. But these are all initial issues that I'm running into when imagining this.

legostud commented 4 months ago

Please make masonry part of grid. It's already implemented on Firefox, but disabled. Once enabled, it was so easy to build a fluid grid.

The one dependency I would tack on to this is to have browsers respect the Grid/Flex order as the reading order for screen readers and keyboards. If we start rearranging things visually using masonry grids, we want to make sure keyboard uses can still understand how to navigate it.

Kerrick commented 4 months ago

Items that can span columns and the use of subgrid are incredibly compelling reasons to make the masonry layout (or columnar grids, my preferred name) part of CSS Grid. I recently created a layout for a local newspaper's homepage, but found myself making compromises that I wouldn't've needed to make were masonry a part of the CSS Grid spec (and widely available). Those compromises would have to remain in place forever if CSS masonry doesn't support column spanning or non-symmetrical column sizes.

jensimmons commented 4 months ago

This is on the front page of Hacker News today, with over 200 comments and counting: https://news.ycombinator.com/item?id=40130148

astronautintheocean commented 4 months ago
  1. Should “masonry”/“waterfall” be part of CSS Grid? Yes, it should. It's quite a common layout used for various image galleries.

  2. Do you want the capabilities to define a columnar grid with CSS Grid — to use subgrid, spanning and all the many options for track sizing? Or do you only want the ability to define a classic masonry layout with equal-sized columns? Would love to see a mosaic-like layout implementation similar to Flickr, Google Images, Shutterstock, Adobe Stock, iStock, etc.

mosaic-layout-example
astrit commented 4 months ago

First and foremost, I must say it is incredible the work being done here, and I am happy to know this conversation is happening.

I am very passionate about CSS in general and I must say that Grid is not being used as much as I would like to see it being used especially when building layouts.

For context, my name is Astrit, and I work as a front-end developer at SEB. We are creating a design system called Green and I want to share an example of how we leverage CSS Grid for enhanced layouts and discuss the benefits of implementing a masonry layout.

Within our development process, we use Lit to construct our web components. One of the key layout components is Grid, which uses attributes like columns, gaps, padding, and many more that I will not go through here. This Grid layout operates seamlessly and offers exceptional functionality across all our platforms.

Here is an example how we use it:

<gds-grid
  columns="l:8 m:4 s:2"
  gap="l:xl m:l s:xs"
  row-gap="l:xl m:l s:xs"
  padding="l:2xl m:l s:xs"
>
...
</gds-grid>

Might not be the best way to use attributes but still working on it!

Thus far, the results have met our expectations, providing us with highly responsive layouts utilising 'grid-template-columns' with 'repeat' and 'min-max' functions.

Here is an example how that looks like


  @layer grid {
   /* When using columns prop */
    :host {
      --_c: var(--gds-sys-grid-columns-12);
      --_grid-col: repeat(var(--_c), 1fr);
      --_grid-col-start: 1;
      --_grid-col-end: -1;
      --_gap-column: 0;
      --_gap-row: 0;
      display: grid;
      width: 100%;
      grid-template-columns: var(--_grid-col);
      grid-column-gap: var(--_gap-column);
      grid-row-gap: var(--_gap-row);
      padding: var(--_grid-padding);
      text-wrap: balance;
    }

    /* 

     Auto columns enables us to have columns that respond to content when we want automated columns based on a predefined min width
     Eliminate the need for breakpoints, or when necessary to combine having some control while giving priority to content

    */

    :host([auto-columns]) {
      --_col-count: var(--_c, 0);
      --_gap-count: calc(var(--_col-count) - 1);
      --_total-gap-width: calc(var(--_gap-count) * var(--_gap-column, 0px));
      --_col-width-max: calc(
        (100% - var(--_total-gap-width)) / var(--_col-count)
      );
      grid-template-columns: repeat(
        auto-fill,
        minmax(max(var(--_col-width), var(--_col-width-max)), 1fr)
      );
    }
  }

The auto-columns attribute, used with CSS grid layout, calculates the maximum column width by subtracting the total gap width from the total available width and dividing by the number of columns. This is represented by the formula MaxColumnWidth = (W - ((C - 1) * G)) / C, where W is the total available width, C is the number of columns, and G is the width of a single gap. This calculated width is then used to set each column's width, with a minimum width of the auto-columns value.

Or you can just straight forward use the auto-columns="200" attribute that will adapt the columns to have min width of 200px across the board or any value for that matter!

And this way we have managed to cover all the use cases we had except one, which is having a masonry layout, we already span in between columns and rows how ever if we had something like grid-template-rows: off; or grid-template-rows: masonry; it would be super helpful to cover these types of layouts and with that pretty much is limitless and very efficient at the same time.

I am not sure how the logic would follow if you have different language direction and if this logic should be similar for columns and rows but as of now any progress on this direction would be more than welcomed.

And for the end I must say these types of things are a big factor of having a much more efficient, maintainable and smaller codebase. And on top of that less libraries and dependencies to do just those calculations.

✌️

fantasai commented 4 months ago

Please, mayby create an questionnaire like with nesting, to gather more votes on the matter.

In this case we wanted more qualitative feedback. If we get to a point where it's just preferences on syntax, we could do a poll; but here we want developers to tell us about use cases and explain or show how they would use the feature. One of the core points of contention is whether or not various aspects of the proposal are necessary complications. Therefore comments like https://github.com/w3c/csswg-drafts/issues/10233#issuecomment-2071279204 and https://github.com/w3c/csswg-drafts/issues/10233#issuecomment-2067472993 are particularly helpful.

sahandnayebaziz commented 4 months ago

I think this is necessary and should absolutely be added to CSS Grid where it feels intuitive to me and is okay if some properties have no effect.

A few times a year, I need to create a masonry grid, check to see if it's possible yet without JavaScript, and eventually give up on it or fake it in a hacky way. Everything described in the blog post, including the ability to do multiple-column designs and mixed-size columns thanks to grid, sound phenomenal.

Thank you for this work and hope to see it in major browsers very soon. I definitely see masonry layouts all over the place and would love to implement more of my own if it were easier like this.

xypnox commented 4 months ago

A new display type with shared properties seems the faster and cleaner compromise.

All listed capabilities are gladly wanted. (And hungrily awaited for.)

Yes I (we?) will use it in a lot of layouts with different sized content.

I cooked up a masonry layout component recently and have implemented a few ideas so far:

Like anyone implementing masonry layouts, I encountered the problems of resizing and image loading. However as I have added customizable theming, I have encountered the need to repaint the layout on a new font load. If masonry becomes a part of CSS these issues would be managed by the browser.

kylehotchkiss commented 4 months ago
brandonmcconnell commented 4 months ago

@kylehotchkiss Do you have an example of a 3D masonry layout? I'm not sure how that would work or look in practice, but I imagine such improvements could be made to grid at the same time. 🙂

As I see it, that's the beauty of masonry being part of grid. Grid and masonry can grow together, so when grid gets new capabilities, so does masonry, and vice versa.

This would also seem to imply easier maintenance and likely fewer new supporting properties needed in the future.

sebfriedrich commented 4 months ago

Should it be part of CSS grid?

Use subgrid, spanning, explicit placement, and combining different track sizes?

yes, super exciting!

What might you do with it?

I imagine dashboard layouts in respect to the level of detail of the chart figures

Are there things you want to do that you can’t do with this model?

Keep stacked elements order closer to markup source

I wonder how the proximity between elements could maybe improved now or later in regard to the original order of nodes (e.g images) in the markup.

Thinking further, grid-template-rows: masonry(0) could make it a CSS function, which uses the closest (zero) gap, while grid-template-rows: masonry(1) would always stack the next row next to former without any interference. Fractions between would work like a threshold of how big a relative gap has to be to make the next image populate the slot. In this example picture a threshold of ~0.2 would make image 6 and 7 change places (and sort of maintain a slightly better order in the sense of the given left to right flow). A threshold of ~0.5 would swap image 6 and 8 and keep 7 in place. Obviously this is just a draft here, experiments would need to validate how well this really works out. I share an idea here, which is still sketchy.

masonry-threshold

I image such kind of control would also help further advance the newspaper examples.

Slicing the grid

A potential UX problem with masonry is, when content blocks don't stack up well or scrolling content becomes very long. The content block fitting keeps working technically speaking, but the relation to the actual order the html nodes had in markup gets more and more shuffled. This can make the user need to scroll back when looking through all the content in detail to not miss out on one.

I wonder how grids in general could offer a way to split content into chunks, which could be like pages or just sections in an infinite page, but making sure the layout fitting algorithm starts fresh at a certain index. The threshold function mentioned above, could apply a threshold of 1 on a certain nth-child. E.g.

main {
    grid-template-rows:masonry(0)
}

main:nth-child(100n) {
    grid-template-rows:masonry(1)
}
kizu commented 4 months ago

I would love to write a longer post about this in the future, but I’ll need more time to experiment with the existing masonry prototype implementations, and think about it more.

Based on my preliminary explorations and experiments:

  1. I think masonry-like something should be a part of CSS Grids.
  2. However, I think right now it is too “magical” and tries to combine many things in one:
    • Removal of the grid lines from one of the axes. This can be useful in regular grids, without the “masonry” behavior. Occasionally it can be worked around by extra wrappers and, optionally, subgrid, but there are many cases where this can be helpful for a “flat” tree.
    • The “masonry” item-placement algorithm, where when we have the above feature on, we can place items in the shortest available spot in one of the “collapsed” columns or rows. Note how I said, “one of”: I would love to be able to make only a subset of rows or columns in a grid to behave like “masonry” (probably a use case for combining them with subgrids).
    • Track alignment: I am not sure why we can’t use the existing content alignment/justification for this and had to introduce masonry alternatives. It feels like something in-between of masonry being a part of a grid, and not.
  3. There are cases for one-dimensional grid that could benefit from something similar to masonry, but not exactly: when we want an element in one column to start (or attempt to start) in a different column from the same row. The main example of this: sidenotes. This is a bit similar to masonry in a sense that in this case there are no defined row lines, and one element’s position depends on the others’ elements. There were some explorations of how to solve this with anchor positioning, but it still felt like a hack. Having this a built-in feature would be awesome, and there might be multiple other cases for these kinds of layouts (placing elements in different rows/columns based on other elements’ positions in different ones) in typography.
  4. The best way forward, in my opinion, could be if we could decouple all the features that make masonry what it is, and see how they could be implemented as a part of CSS grids one by one. It is better to create smaller building blocks with well-defined interactions with other elements, than trying to fit a bigger concept into a pre-existing one.

That’s all from me for now — I have many other thoughts, but will need to read all the comments here, and experiment more before I could properly articulate them (and show examples).

pmitros commented 4 months ago

Disclaimer: I read the webkit blog post. I'm coming in with a clean set of eyes, but limited expertise in this specific proposal. My background is developing full stack applications (some major, like Open edX, and many little ones), as well as a lot of teaching experience, again, full stack, spanning elementary schools through corporate PD through MIT EECS students. Take this as a 1000-foot-view.

Feedback: I like the concept, but I don't like the proposal as presented here or where the discussion is headed (keeping in mind there are other proposals as well, and a blog post is an imperfect presentation).

I think the key issues are:

  1. CSS and HTML have been growing in complexity -- almost exponentially -- since the HTML 2.0 days when it could be taught to elementary school students to where it's inordinately complex.
  2. There has been a battle of semantics versus directing pixel-perfection for many years. Pixel-perfection keeps winning.
  3. Related to that, there has been a battle of semantic elements versus everything-is-a-div
  4. All of that also makes things like one-off browsers, bots, scrapers, test cases, etc. increasingly complex. This was a major use-case in the nineties.
  5. Even today, with most of the creative client-side stuff dead, and where even Microsoft can't afford to maintain its own browser engine, there are critical audiences hurt by the growth in complexity and decline in semantics (e.g. a11y)

This discussion feels like it is far too far on the complexity / pixel-perfection / everything-is-a-div side. As with many of these discussions, it's dominated by front-end developers who are comfortable with language like main:nth-child(100n) { grid-template-rows:masonry(1)}, let alone --_total-gap-width: calc(var(--_gap-count) * var(--_gap-column, 0px));. That's a very small portion of people who would be using this.

It's also -- to be frank -- not very important. Big web sites will look a little bit prettier, which will make web devs happy, but I don't think the world improved when it went from Hacker News or Craigslist-style layouts. People are famously okay with simple layouts. Having a nicer one gives a competitive edge, but if everyone has a nicer one, the competitive edge goes away, and we're just treading water. Making ugly layouts easy and nice layouts hard -- which is what happens when HTML / CSS become more complex -- just gives an edge to big corporations who can afford big front-end teams. Keeping things simple has a major effort on democratizing the open web.

What I'd love to see here is HTML and CSS which is simple enough that I mere mortals can read and write layouts without digging through reams of documentation.

I think the trick would be to do user studies with e.g. high school students. Can this proposal (like HTML 2.0) be taught and interesting in a short session? If so, bring it in. Until it's that simple, please leave it out.

I suspect where a proposal might land might be:

  1. Define and document clear use-cases.
  2. Extend CSS, and HTML, to handle those which works out-of-the-box to good results. Something as simple as <gallery><img><img><img></gallery>.
  3. Provide a few easy-to-understand high-level options (e.g. should order be kept, or can the browser rearrange the order per some optimization? should a particular box be made big?).
  4. Since we can't get away from it, provide a set of further properties which allow pixel-perfection for the front end developers, and perhaps some validation (remember ACID, back in the day?).

Publish those, and ask for feedback. See how understandable they are to ordinary individuals -- ideally at the level of high-school students, but at the very least, non-front-end developers. You can even walk into the grumpy sysadmin's office at your own company and see what they think.

FWIW, major use cases I've seen are (1) an image gallery (2) a newspaper-style navigation page, of boxes with text. Those sorts of things might want semantic HTML elements. Using those elements, CSS should be strictly optional.

theAdhocracy commented 4 months ago

Another vote for keeping it as part of CSS Grid. Alongside the ability to use subgrid, column spans, and other existing features, as others have noted, making masonry a new feature for Grid allows for easier progressive enhancement and adoption. You could build a regular grid, then enhance to be masonry for those browsers that support it, in a lot of scenarios where this functionality would be used.

I'm also someone who has been hoping for native masonry layouts for some time; many of the reasons given above overlap with my own experience. However, I think it is worth flagging the accessibility concerns that such a fluid layout algorithm can have.

What considerations are being included in the spec for dealing with the disconnect between visual layout order and DOM order? Or for handling focus order correctly? As the nature of masonry is very hands-off from a developer's perspective – we're letting the browser decide placement, after all – it won't be easy (or even impossible) to retroactively patch this behaviour for assistive technologies.

I'm aware that there are discussions elsewhere within the CSS community (and Working Group) around making better, more robust accessibility APIs for functionality like Grid, but masonry seems to come with these concerns baked in and unavoidable, so it would be good to see a concerted effort to ensure that they are covered before masonry sees wide usage or implementation.

chrisarmstrong commented 4 months ago

@pmitros

the HTML 2.0 days when it could be taught to elementary school students

The great thing about HTML & CSS is that you can still code like it’s 2001 and it’ll all still work... but in reality all the “added complexity” has made it easier to accomplish the things we commonly need to do.

You can still build a house with a hammer, but professionals use more complicated nailguns.

pmitros commented 4 months ago

@chrisarmstrong In theory, yes. In practice, no, at least if you want even basic readability.

HTML 2.0 browsers all had their own native styling built-in for things like headers and paragraphs which were different, and designed to look okay on the devices of the day. HTML2 was entirely semantic, and a browser was free to render headers or paragraphs as most appropriate for the context, be that a text-only terminal (remember Lynx?), a graphic browser, Windows 3.1 on a VGA screen, an SGI workstation with a 1600x1200 monitor running Irix, or a screenreader.

Although tables were part of HTML2, they really moved into their "prime" around the time of HTML 3 and 4, where they were widely used to define layout (rather than tabular data). Around the time, there was an expectation that browsers have pixel-perfect layout (which was the era of things like ACID tests). Those were the bad days, but from that point on, a browser could no longer render headings and text as it saw fit and appropriate for the device it was on. The rendering algorithm was specified, and as specified, was designed to look fine on a 640x480 VGA monitor (and even an SVGA monitor).

Consequently, default styling is now locked down to what worked on ancient operating system at low resolutions. Today, modern browsers don't render HTML 2.0 okay. On a 4k monitor, you will have lines in of text in p tags which run end-to-end on the screen, without reasonable margins. It's unreadable and unusable (at least until you click the little "toggle reader view" icon on Firefox, when it's rendered the way HTML 2.0 was meant to be rendered). Some minimal CSS is needed for even a very baseline level of usability.

(That's not to mention many other issues, such as the move from SGML to XML; modern browsers don't always seem to handle SGML properly)

I'm, of course, not suggesting a return to the HTML2 days. HTML5 was a major clean-up and takes an entirely different philosophy from HTML2. However, I'd like to see newer standards continue with that clean-up and general simplification to where newer standards continue to make things increasingly usable for normal users on a democratic, open web, like we used to have.

32teeth commented 4 months ago

Considering there is low browser support currently, we can still use /span to demark layout strategies

Has some Codepen that on a 12x12 grid you can set row span and col span to get some awesome layout

rileybathurst commented 4 months ago

It seems a some people may have missed the demo in https://webkit.org/demos/grid3/photos/ Photos switch the layout to Horizontal Masonary so make sure to look at all the options this might be what you are thinkink about @keller-mark @chartgerink

Another vote for in grid, the fall back dor a display grid seems like a good place to start

dgattey commented 4 months ago

Should “masonry”/“waterfall” be part of CSS Grid?

Absolutely - it's a grid and I want to use all the capabilities of one with the waterfall layout

Do you want the capabilities to define a columnar grid with CSS Grid — to use subgrid, spanning, explicit placement, and all the many options for track sizing? Or do you only want the ability to define a classic masonry layout with equal-sized columns?

PLEASE! I'd love to use the capability and the flexibility that comes with it. Explicit placement is less interesting to me than the other mentioned features

Will you use this? What might you create with it?

Yes, most immediately on a personal profile with a boring static sized grid right now

Ngranger commented 4 months ago

I think that the masonry/waterfall idea should be part of CSS Grid, but it should also be available in CSS rows not just the column direction.

wolfhechel commented 4 months ago

I attempted to create a masonry like layout for a gallery just the other week. In the end, the solution I ended up with was to use columns: but at the cost of not being able to align the images horizontally.

I'd support adding masonry to the grid specification rather than as an additional display property, the benefits of building on top a well established (and already complicated but feature full) standard makes most sense.

ryanleichty commented 4 months ago

Should “masonry” be part of CSS Grid?

Yes!

Do you want the capabilities to define a single-axis grid with CSS Grid — to use subgrid, spanning, explicit placement, and combining different track sizes?

Yes! I also want the ability to use gap.

Will you use this at all? What might you do with it?

I've had to implement a masonry-like grid twice in the last year, both times having to research the available options, reading through extensive articles and/or documentation for JavaScript based solutions, but ultimately never landing on a perfect option. The proposed solution solves all of our problems and needs.

Adding it as a display property would be too limiting.

It’s likely masonry is not the best name for this new value.

I think masonry makes the most sense given it's usage both in blog posts as well as in the names of JavaScript libraries. It has historical context and weight. Waterfall doesn't convey the same kind of visual imagery as bricks stacked on top of each other.

KieranP commented 4 months ago

Yes, I feel "masonry" should be part of grid, but I also agree having it as a display value rather than a template-rows setting makes more sense. IIRC, display takes multiple values. So how about something like this?

display: grid balance;
SaraSoueidan commented 4 months ago

@desandro Hi Dave! It's good to see you here. I've been a fan of your work for years.

In my experience, the vast majority of users want uniform column width. CSS grids provide so much power over layout with track sizing. I think that amount of customization over the tracks is an unwanted feature when working with masonry layouts. Typically with a masonry layout, you want the item to have the same size regardless of its position in the grid. So, if you want to be practical, go with display: masonry, this will satisfy 95% of masonry layout usage.

By "users" do you mean us devs using the feature? The reason I ask is because the main reason I (as a dev) didn't use the JS plugin back in the days on many websites was because it forced me to set a uniform column size when I wanted more flexibility and freedom to get creative.

I believe that even though the masonry layout is traditionally known for uniform-width columns, non-uniform columns are very appealing. And sticking with uniform widths means that the layout will not be as adaptable to different use cases anymore.

FremyCompany commented 4 months ago

With my CSS Tables editor hat on, I would strongly advise against entirely merging this feature with CSS Grid.

I'll give you two reasons:

  1. When layout systems start to introduce modes, it makes it very diffcult to describe what their properties do in a clear way. You keep having to add conditionals, additional explanations, and every new feature that doesn't get thought about equally well in both modes introduce subtle interop bugs between browsers, which over time result in quirks that have to be documented, making the text even less readable.
  2. The performance characteristics of CSS Grid and Masonry are completely different. With CSS Grid, the cell where items are located is decided once and for all before doing layout, but this is not the case for Masonry, where every resize can potentially shuffle every element. Layout systems with very different performance characteristics (and recommendations) should probably not be joined together under one name, making it difficult to introduce appropriate guidance, but also causing signifiant slow downs for the fast paths (CSS Grid regressions) or invalidation bugs as new optimizations are introduced using assumuptions that do not hold for the slow paths (Masonry).

As a user, there's a third reason, which is that:

  1. The way you can specify column placement in CSS Grid does not appear intuitive to me in the world of Masonry. When you have a Masonry with different column sizes, you might want to restrict some items to be placed only in one or the other of the column types, but you cannot achieve this with CSS Grid, at least without significantly changing the semantics of column placement.

I understand the appeal of "just adding one more feature to Grid" but I don't think this is the right path forward. The difference in performance, ordering of layout steps, and (frankly) desired results make a franken-grid system look unappealing from me. This doesn't mean that masonry has to be limited to a few options only, it can certainly draw inspiration from grid, but I'd prefer this to happen as an inspired copy rather than an intricated inplace edit.

My two cents ;)