WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.52k stars 4.2k forks source link

Designing a Core CSS Grid Block for Intrinsic Design #49084

Open robglidden opened 1 year ago

robglidden commented 1 year ago

What problem does this address?

In recent releases, WordPress has increasingly embraced intrisic design as a fundamental modern styling methodology.

And since the term was coined, CSS Grid has been a central tool of intrinsic design.

The CSS Grid Layout Module offers a grid-based layout system with rows and columns, enabling an endless variety of layouts beyond its simpler cousin, Flexbox.

Nearly all modern CMSs have adopted CSS grid in some form.

Numerous Gutenberg issues have explored the topic of grids from several angles:

But a recurring challenge has been to design a user interface that copes with the versatility and complexity of the CSS grid properties.

A CSS grid block design needs to:

A start-simple approach postpones the UI design issues down the road and constrains the real power of CSS grid, which is in the interplay of its 10 basic properties:

A fully-functional CSS grid block needs to consider 3 potentially conflicting use flows:

A core design question is whether it is necessary, or feasible, to design an "ultimate CSS grid user interface" that is both easy for users without CSS knowledge and flexible enough for designers to access all of CSS grid's power.

Or perhaps multiple user interfaces on top of the css grid properties might be more tailorable to particular uses.

What is your proposed solution?

Here is a proof-of-concept CSS grid block that fully implements CSS grid and addresses the use flows of using, designing, and sharing/locking.

For users, it is easy to use, like a row block with more layout options:

css-grid-block

There is a design panel for designers to make and save grid layouts for users to use:

css-grid-design-panel

Sharing/locking:

Note that the css grid block works with the Query Loop block -- just put a Query Loop inside it and set the flag.

The block supports per-instance custom CSS, to enable advanced uses like different template areas at breakpoints. The placeholder ".wp-grid-name-class" is auto-replaced with the actual name of the grid block instance.

Possible refinements:

Hopefully, a proof of concept of a fully functional css grid block will inspire more consideration of how to extend WordPress's intrinsic design capabilities.

annezazu commented 1 year ago

Thanks so much for opening this issue and putting so much effort into sharing a possible idea. As you noted, there are a few related issues. In particular, I want to cross connect to this issue: https://github.com/WordPress/gutenberg/issues/42385 It would be really awesome to consolidate these if possible but I'll leave that to @WordPress/gutenberg-design to know what's best!

jasmussen commented 1 year ago

Indeed, there's a PR working on this in #49018, I shared some thoughts relevant to this issue in this comment.

Edit: I see you've already discovered that PR. My comments on that PR are still relevant. I also want to note that #47809 is another avenue on this issue, which links two further. I wonder if we should consolidate issues, so the conversation doesn't get spread across 4 issues?

robglidden commented 1 year ago

@annezazu and @jasmussen thanks for referencing these related issues. As I understand it, these are potentially complementary but different approaches.

47809 and #49018, if I understand correctly, are exploring a start-simple approach to grid, asking in essence:

What's the simplest yet useful first version UI of a grid that could be later extended?

They only consider grid-template-columns and not areas and other grid properties, and purposely postpone the UI design issues of a full CSS grid implementation and constrain the full power of CSS grid.

This issue takes a different enable-the-power-of-grid approach:

Assuming the full power of CSS grid as the starting point rather than an eventual destination (that is, all the basic CSS grid properties), what UI(s) on top would best enable user, designer, and sharing/locking use flows?

There are several reasons to fully examine the UI implications of a full-powered CSS grid at the onset rather than down the road:

In essence, the modern Web has given us the powerful design tool of CSS grid. Let's use it!

42385 and the follow on #48070 as I understand it are about bringing consistency to layout, like the dimensions panel, which applies to grid too and is included in the proof of concept block.

annezazu commented 1 year ago

Tagging in @tellthemachines who has thought a lot about this from a developer perspective as more food for thought!

jasmussen commented 1 year ago

Sorry I meant to link https://github.com/WordPress/gutenberg/issues/47809#issuecomment-1422202779, which summarizes my reasoning for why it's best to start simple. That's mainly my opinion, of course, and is mainly a thought on how we approach it, not something that precludes additional properties and UIs.

robglidden commented 1 year ago

@jasmussen, I found that #47809 (comment) extremely insightful. I returned to it several times in building the poc block.

The key to me is "start with the smallest feasible step that can be useful on its own". "step", not "UI".

I framed this: what is the minimum viable solid foundation which would support all future grid layouts and UIs? Even if there were no UI at all?

In implementation terms, what block attributes implement the Grid Module spec and would always reliably underly any grid layout or UI?

Removing short-hand properties, the full Grid Module spec is 10 basic properties:

grid-template-columns/rows/areas grid-auto-columns/rows/flow row/column-gap grid-column/row

These 10 properties work together, not separately, and have defaults. How to express as block attributes?

That leaves grid-column/row, technically properties on children of the grid, like flexbox also has child properties.

The poc adopts the single alphabetical letter naming convention. It is versatile, adequate, and maps intuitively to the WordPress inner block architecture. A possible refinement would be a list of free-form names or values, which some grid layout designs may favor.

By aligning to the Grid Module, we have a solid foundation on which grid work can reliably move forward, while being forwardly compatible with upcoming enhancements like masonry and subgrid.

The "minimumColumnWidth" attribute used in PR #49018 is not a Grid Module spec, and not a foundation for further grid work, although it may be a useful configuration value for a very particular grid variant (in that case grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));).

I note that Chris Coyer of CSS Tricks in 2019 discussed this same "most famous line of code to have come out of CSS grid so far" and recommended the refinement grid-template-columns: repeat(auto-fill, minmax(min(10rem, 100%), 1fr));

The next step on a solid foundation is to consider the use flows of use, design, and sharing/locking, which the poc block then explores.

jasmussen commented 1 year ago

Thanks for all that context. I've had some busy days and have been unable to go very deep on this lately. And this particular effort definitely needs going deep, as it's clear you know.

The poc adopts the single alphabetical letter naming convention. It is versatile, adequate, and maps intuitively to the WordPress inner block architecture. A possible refinement would be a list of free-form names or values, which some grid layout designs may favor.

That all sounds good to me, honestly. On top of the challenge it is to fully understand the inner workings of CSS grid, the two that concern me the most are:

Some technical debt is likely impossible to avoid as we figure things out, but ultimately it boils down to finding a way to grow, while starting with the properties we have the highest confidence in.

The "minimumColumnWidth" attribute used in PR https://github.com/WordPress/gutenberg/pull/49018 is not a Grid Module spec, and not a foundation for further grid work, although it may be a useful configuration value for a very particular grid variant (in that case grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));).

That sounds like it'd be good feedback on the PR.

robglidden commented 1 year ago

Great questions.

How can we strike a balance between surfacing grid-spec options for power-users, while ensuring it's intuitive enough that anyone could pick it up by just tinkering with properties in the inspector?

A few ways the poc block takes:

How can we roll that out in a way that can slowly prove itself, while not painting ourselves into a corner by either going too deep on the spec, or too far from the spec?

A couple of ways the poc block takes:

Some technical debt is likely impossible to avoid as we figure things out, but ultimately it boils down to finding a way to grow, while starting with the properties we have the highest confidence in.

So keep preset layouts, preferred variants, first-pass and UI settings out of the block attributes, and only write the generated css properties to the block attributes. Then new presets, new UIs, and new slotfills can be introduced and old ones removed without the block attribute level technical debt.

tellthemachines commented 1 year ago

Thanks for all your work on this @robglidden !

The approach that makes the most sense given the existing layout architecture in Core is to add "grid" as another layout type. Apart from API consistency, there's the emerging need for a grid layout type that can be used to solve layout problems in existing blocks, such as Post Template (see #44557) and possibly Columns, if it can be leveraged to improve the block's current responsive behaviour.

As a consequence, my work in #49018 attempts to lay the groundwork for this approach, adding "grid" as a new layout type and defining a minimal API that can be gradually built upon with further features. The API deliberately doesn't reflect the CSS grid spec; it is an abstraction that exposes functionality in a hopefully intuitive way. Its implementation shouldn't matter to consumers; it should hypothetically be possible to switch grid out with a completely different system that produces the same result, if it becomes necessary to do so at some point in the future.

robglidden commented 1 year ago

Thanks @tellthemachines for distilling the complementary nature of these topics. Hope to early-adopt is-layout-grid or whatever makes sense.

To help folks get up to speed and not lose the thread though already touched from multiple angles here and in #47809:

The approach that makes the most sense given the existing layout architecture in Core is to add "grid" as another layout type.

Yes, a well-designed grid layout type would be welcome for many existing and future blocks. Columns, Post Template, grid-ish variants of the Row, Stack or Group blocks to name a few, as well as a grid block.

It may help folks following this to explicitly state, a "grid layout type" and a "grid block" are two different things. Think a new .is-layout-grid CSS class, which many block types in addition to a grid block would hopefully use. A particular block's block attributes are also different, which is why multiple blocks can use the simpler .is-layout-flex class, even though it is "a limited subset of what is possible with Flexbox".

In the meantime, you may have noticed the poc grid block uses a workaround -- obviously a grid layout type isn't yet available -- but also:

Any specific thoughts on early adoption of an .is-layout-grid to a full-featured grid block given these constraints would be quite helpful.

Apart from API consistency, there's the emerging need for a grid layout type that can be used to solve layout problems in existing blocks, such as Post Template (see #44557) and possibly Columns, if it can be leveraged to improve the block's current responsive behaviour.

Yes. And CSS grid works great with media queries as mentioned before. Intrinsic and responsive design paradigms are complements not competitors.

As a consequence, my work in #49018 attempts to lay the groundwork for this approach, adding "grid" as a new layout type and defining a minimal API that can be gradually built upon with further features.

The minimal API and its relation to a full-featured block is noted in this comment to #49018.

BTW Chris Coyer's "most famous line of code to have come out of CSS grid so far" was also implemented in the poc grid block as one of the click-the-icon switchable grid layouts, to avoid block attribute technical debt. Could also inform a slotfill in the UI.

The API deliberately doesn't reflect the CSS grid spec; it is an abstraction that exposes functionality in a hopefully intuitive way.

Yes, I hope it is clear the different use flows of a full-featured grid block.

Its implementation shouldn't matter to consumers; it should hypothetically be possible to switch grid out with a completely different system that produces the same result, if it becomes necessary to do so at some point in the future.

Yes, as applicable to multiple block types.