w3c / csswg-drafts

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

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

Closed jensimmons closed 6 days ago

jensimmons commented 6 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.

harunaamadu commented 4 months ago

There's no harm in trying. I think display masonry and waterfall will best fit in the grid because they come much in common. But separating them too is not bad as it will reduce the code lines making things simpler.

In any way they appear creative people will use it to achieve great and eye-catching designs.

Or better still they can be versatile that is, they can be used independently or as in display grid.

rileymcmaster commented 4 months ago

Thanks Jen Simmons and Rachel Andrews for writing such in-depth articles about the future of CSS!

After reading both the Jen's Webkit and Rachel's Chrome articles, I would say I'm leaning towards masonry being its own display type. The masonry layout is more concerned about one axis like flexbox, rather than grid's concern over both axes.

If masonry was added to the grid spec, I think the amount of properties that do not cross-over from one layout to the other would make troubleshooting issues a big pain. Some values seem logical with masonry while should throw errors in grid : repeat(auto-fill, auto).

I use grid constantly and am well versed in the syntax and I think masonry should share a lot of the terminology and functionality but they should still be separate display types.

One is issue I have with the Webkit article is their case for subgrid. I've tried shoe-horning subgrid into projects several times and it never really makes sense to me. In their example (I understand it's an example and maybe not the best real-world scenario), I think it would make more sense to define the layout of the card so that the cards are all uniform. Their use of subgrid seems arbitrary since every card is taking up two columns, one of those columns on the parent is just to align child's content. That seems like classic case of over-parenting.

sgarciagallego commented 3 months ago

Great to see the discussion at WebKit and Google alike, both with differing opinions on whether masonry should be an extension to grid or it's own display type. I personally believe, from a visual standpoint, that masonry is a type of grid, and as such should be able to be implemented through the grid-template-rows: masonry; declaration.

As well as this, I was looking into how Google were looking into an implementation of the masonry/waterfall layout, and was confused by what seemed like a top-to-bottom then left-to-right approach to ordering items, even if not explicitly mentioned. I believe this should be able to be implemented left-to-right then top-to-bottom, following the current natural reading patterns.

Aps-x commented 3 months ago

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

Recently, I was working on a timetable website that displayed information about class times. The user could have any combination of different classes, so the layout would have to respond dynamically to different content (per column). Just like this example (that uses JavaScript):

Demo

I think this is a perfect use case for horizontal masonry.

I tried to achieve this layout with just CSS and no JavaScript, but I found that I was unable to. CSS Grid with auto columns comes close, but I couldn't get the cards to fill in available space. If the content was static, it would be no problem, but the content is dynamic and I can't provide an explicit column span ahead of time.

I wanted a layout option that was in-between Flexbox and Grid; in other words, I wanted a single-axis grid. In this case, I needed rigid rows without columns so the cards could be explicitly placed on rows but have flexible widths.

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

Not exactly the model, more a specific implementation, but I messed around with the current masonry implementation in Firefox and it came close to what I needed. For the use case I was talking about, it would be great if I could set a card to have a width of 1fr and have it fill in available space. Also, grid-auto-flow: dense; only seems to pack in one item rather than as many that can fit.

ddamato commented 3 months ago

I tried to achieve this layout with just CSS and no JavaScript, but I found that I was unable to. CSS Grid with auto columns comes close, but I couldn't get the cards to fill in available space. If the content was static, it would be no problem, but the content is dynamic and I can't provide an explicit column span ahead of time.

IMO, I think your example is better suited for CSS Grid than masonry. In fact, this would be great with named lines:

#calendar {
  display: grid;
  grid-template-columns: [monday] 1fr [tuesday] 1fr ...;
  grid-template-rows: [t0900] 1lh [t0915] 1lh ...; /* Probably needs to be generated, needs a lot of lines. */
}

#COMP3704_S2_1 {
  grid-column: monday;
  grid-row: t1000 / t1130; /* Must start with alpha, omitting special chars */
}

For conflicting events (like the first events on Tuesday in your example), I'd probably consider subgrid to continue aligning with the times but try repeat(auto-fill) for the column. Definitely an interesting problem regardless! Might even give it a shot myself in my free time. Thanks for sharing.

Aps-x commented 3 months ago

@ddamato Thank you for your reply! I am admittedly not super experienced with CSS, so there might be something obvious I am missing.

Here is a demo of the layout I think would be good with horizontal masonry (I messed up the code embed): index.txt

I think seeing the problem visually might do it more justice than my attempt at explaining it in writing. Grid doesn't have an equivalent to flex-grow where cards can grow to fill in a fraction of the space. They have to span discrete columns and you have to explicitly provide this ahead of time. To be clear, the issue is having cards fill in all available space when the cards are placed dynamically.

Sorry if I am wrong, I don't mean to derail the conversation, but is this not a problem that could be solved with grid-template-columns: masonry; ? Is it already possible to do this with just CSS?

nt1m commented 1 month ago

I found this layout: https://x.com/dwinawan_/status/1833369698282476018

Link2Twenty commented 1 month ago

I found this layout: https://x.com/dwinawan_/status/1833369698282476018

The bento grid is quite easy to replicate in the existing grid. I don't think masonry layout would be used to create it.

ShaunaGordon commented 1 month ago

I feel like I'm in the minority with @tryoxiss, who has pointed out that it's possible to have masonry layouts that have neither fixed rows nor fixed columns. I've read through all of the comments and if there are any others noting this, they're few and far between, despite it being what I'd consider to be a "true" masonry layout. In fact, I like the distinction they make between masonry and waterfall, because those are two fundamentally different layouts that just happen to achieve a somewhat similar result if you don't look too closely. I get the sense that the responses so far have been kind of stuck by the current limitations of masonry implementations, stymieing the potential of this feature to break free of those limitations.

If "masonry" is only ever defined as "defined rows, undefined columns" or "defined columns, undefined rows," then sure, put it into grid, but if there's ever the possibility of allowing the "fit them together like a jigsaw" style that tryoxiss illustrates, then shoehorning it into grid is shortsighted, in my opinion, because you end up throwing out most of grid's features, instead of just some of them to make this layout, and you inhibit your ability to add features that would pertain to waterfall or masonry, but not to grid, without having to make concessions that those additional features are just invalid with certain other combinations. In light of that, it seems better all around to separate them -- it's clearer for the front end developer what display paradigm an element is working under and more predictable for what does and doesn't work, and it doesn't take as much overhead for implementers to figure out all the combinations that do and don't work for directives that are otherwise valid for that display paradigm.

Now, if it is part of grid, it does create a rather obvious solution to the question raised earlier of "what happens when grid-template-rows and grid-template-columns are both set to off?" At that point, it would/could be the "true" masonry, whereas when only one or the other is off, it creates a waterfall layout. ...But at that point, if we turned off both rows and columns, are we even talking about a grid anymore? Isn't the whole purpose of a grid...rows and columns? Not having one is stretching it, in my opinion. Discarding both breaks it entirely.

To me, having grid, waterfall, and masonry as separate options for display makes the most sense. display concerns itself with content flow, both of the element in relation to its siblings (block, inline-block, inline) and in relation to its contents (grid, flex, table), while the individual settings determine the details of how the elements flow, without significantly changing the overall flow model set by display -- spanning a row or column doesn't mean the element is no longer working within the context of a grid or table, for example. Waterfall and masonry are different flow models from grid and flexbox, for the aforementioned reasons, and thus warrant their own options on display.

(tl;dr - +1 for display: masonry)

essenmitsosse commented 3 weeks ago

This feedback might not align exactly with the original intent of this issue, but since the discussion is happening here, I’ll share it anyway:

TL;DR: Masonry is a good grid to have, but the proposed implementation is too specific and opinionated. Instead of adding more and more "predefined" layouts, CSS should offer more general tools for developers to define their own layout logic.

I believe that while flex and grid introduced useful features, they represent a step in the wrong direction overall, and implementing Masonry via CSS Grid Level 3 would likely make things worse. My main issue with these technologies is that they implement highly opinionated constraint-solving algorithms, which can be opaque in terms of both the layouts they enable and how to achieve them. Both flexbox and grid allow for a wide range of layouts, but there are also many that feel like they should be possible, yet aren’t. I expect the same will be true for Masonry — there will inevitably be certain layouts it won’t support, forcing developers to fall back on JavaScript for manual implementation. Worse still, it’s likely to be unclear where those limitations lie.

Moreover, Masonry is a very specific design that solves a narrow set of problems while creating a distinctive, but somewhat dated, visual style. It’s less of a general UX pattern and more of a late-2000s aesthetic. I’m not sure CSS properties should encourage such specific design choices; rather, they should function as general-purpose tools. Adding a feature like Masonry will only encourage more uniformity across websites. And if we add Masonry, why stop there? Should we also add other grid layouts tailored to different styles? While flex and grid are justifiable as general-purpose tools, Masonry feels like it crosses into being overly opinionated.

At this point, CSS is becoming more like a full programming language, but instead of moving toward making it more general-purpose, we’re adding new predefined functions (display: grid, display: masonry) with increasingly convoluted arguments (grid-template, align-self, etc.). I think we should acknowledge this trend and consider making CSS more flexible and general instead of more specific. Rather than adding more predefined layouts, we should provide developers with tools to define their own constraint-solving algorithms. Features like calc() and variables have already brought CSS closer to this ideal, and custom layout algorithms seem like the logical next step. Introducing Masonry feels like add() and mult() would have been added, instead of the general purpose calc() we luckily got.

In summary, while the ability to create a Masonry layout in CSS would be valuable, I don’t believe an overly specific specification is the right solution. Developers should rather get the tools to implement their own Masonry.

ShaunaGordon commented 3 weeks ago

@essenmitsosse What kinds tools do you suggest that would be sufficiently generic enough and easily provide the ability to create masonry style layouts?

Loirooriol commented 3 weeks ago

@ShaunaGordon Not sure if it's what essenmitsosse was referring to, but there is https://drafts.css-houdini.org/css-layout-api/

essenmitsosse commented 3 weeks ago

@Loirooriol ah thank you! Wasn't aware of that proposal. Your link doesn't seem to be working (currently), but here is a good explanation.

And: Yes! The Houdini proposal is definitely something I would prefer over "hardcoding" another algorithm, as per the arguments I mentioned in my initial comment.

oscarotero commented 3 weeks ago

IMO, Houdini proposal is a way to insert JavaScript in CSS, which means if JavaScript fails for some reason (and probably fail), the CSS will fail too.

CSS is a powerful programming language that should be enough by itself, we don't need to "complete" it with JavaScript.

@essenmitsosse I understand your point of view, but keep in mind that CSS is a declarative programming language to build interfaces, is not imperative like JavaScript. Declarative languages are always opinionated and domain specific (the oposite of a general-purpose language). I don't think a complex language that force you to create a two-columns layout from scratch at low level (having to implement the algorithm by yourself) is a better option. Surely it will be more powerful but also more complex (in the same way C is more powerful than PHP but nobody will want to create a website in C).

essenmitsosse commented 3 weeks ago

I just want to point out: My initial comment left out JavaScript on purpose as a solution. It most certainly would be an obvious one, but the discussion shouldn't rely on it being solved with JavaScript.

@oscarotero I absolutely see your point and I agree that it is the best counter-argument to the point I made. But I think this is exactly the kind of discussion that needs to happen.


The counter argument that could be brought up is: Why not complete it with JavaScript, if we already have it? I think the concept of a website, that runs without JavaScript is basically dead by now. This wouldn't be about removing all of CSS and replacing it with JavaScript. It would only means to add an option to add more custom algorithms via a new general purpose tooling that would solve dozends, hundreds or even thousands of layout problems at once, instead of adding one very specific trendy layout algorithm every 5 years or so. And then waiting each time until all browsers have implemented it (correctly).

Houdini (or something like it) wouldn't take away anything from CSS. But Masonry won't be the last layout algorithm people will want and would set the precedence of having these things added via hardcoded logic, with a convoluted API surface. Even experienced front-end developers already complain about the complexity and convolutedness of flex and grid. Masonry most certainly wouldn't end up being a simpler implementation.

So for me it's about if we prefer to be able to run custom scripts (which could be much more focused on the specific use case) or if we prefer making CSS harder and harder to learn with each year.

The good thing about a Turing-complete language is, that you only need a finite set of things to express anything. The nature of CSS is, that every time you want to do something new you need to increase its surface. I can't think of many systems that have improved by continuously adding more specialized features while neglecting versatile, general-purpose tools.

oscarotero commented 3 weeks ago

@essenmitsosse

I think the concept of a website, that runs without JavaScript is basically dead by now.

I think it's the opposite. Most of the stuff that needed JavaScript in the past (like animations, scroll snap, anchor position, etc) can now be achieved with pure CSS (unless you want to translate all these features to JavaScript again, which is what I understand in your latest comment 😛).

experienced front-end developers already complain about the complexity and convolutedness of flex and grid.

I don't think flex and grid are harder than creating a responsive layout with all elements with position absolute and placing them using JavaScript.

I can't think of many systems that have improved by continuously adding more specialized features while neglecting versatile, general-purpose tools.

CSS is an advanced language, with a lot of features. Selectors can be very powerful. Properties like color manipulation, 2D/3D transformation, animations, open type features, variables, math functions, etc make CSS the most advanced language ever created to build interfaces. All these features are general-purpose. You can combine them and create infinite designs.

Grids and flex are properties that distribute elements over a surface. They were designed to be the most flexible as possible. Grid, for example, allows the build layouts in a declarative way (using named areas, grid-lines, configuring auto-flow, etc), imperatively (using line numbers to place every element over a surface of fixed columns and rows), or a mix of both (probably the best in most cases).

Masonry, (that probably should change the name for something more generic to avoid this kind of misinterpretation) is just another way to distribute elements in a surface, similar to grid and flex, but with a different algorithm to open new possibilities that grid and flex don't allow. It's not only to build "Pinterest-like" interfaces (although you can) but there are many other use cases like magazine-like interfaces, etc.

Ultinio commented 3 weeks ago

Alright, I didn't have an opinion about one or the other (part of grid or its own display type), but let's admit plenty of developers are confused when they have to choose between grid or flex. So it's already not really clear.

As @essenmitsosse wrote, it might be a step in the wrong direction. Instead of making things even more confusing for developers, why not giving them the possibility to define ways to fill a container in a more general way ?

Not mentioning Javascript or the solutions adding some JS-or-similar-system into CSS because it shouldn't be like that and this whole conversation is actually to avoid JS in the first place.

But if there is no possibility to change the whole system in the short term, here it feels like grid-auto-flow is the property designed to tell the browser where and how to add new elements. Isn't it why this property is there ?

So it could be added to grid-auto-flow, as masonry or waterfall (whatever). Columns are defined as usual with grid-template-rows, and the algorithm knows what to do with new elements.

Or maybe I am wrong and please feel free to show me some examples where this cannot work.

alcinnz commented 3 weeks ago

I think the concept of a website, that runs without JavaScript is basically dead by now.

I think it's the opposite. Most of the stuff that needed JavaScript in the past (like animations, scroll snap, anchor position, etc) can now be achieved with pure CSS (unless you want to translate all these features to JavaScript again, which is what I understand in your latest comment 😛).

Indeed, exciting times for CSS! I will add that amongst the indie web circles I like to surf... JavaScript-reliant sites are the exception, not the norm.

The old web never disappeared, it just got built up around. Same city, new skyline.

experienced front-end developers already complain about the complexity and convolutedness of flex and grid.

I don't think flex and grid are harder than creating a responsive layout with all elements with position absolute and placing them using JavaScript.

I find flex & grid easier to use! And understand!

fearthelettuce commented 2 weeks ago

IMO, display: masonry is much cleaner. Shoehorning it into grid makes both more confusing.

jensimmons commented 6 days ago

Thank you to everyone who commented here in response to our original article, Help us invent CSS Grid Level 3, aka “Masonry” layout, published April 2024.

A lot has happened since we wrote that article. This week we published a new article explaining what the CSSWG has decided and what still needs to be decided. We'd love for you to read it: https://webkit.org/blog/16026/css-masonry-syntax/

Meanwhile, I'm going to close this issue. We created a new issue to have a new space where we'd love for you to comment on the current questions at hand. (It's linked to from the article.)