-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking: extend layout options in Gutenberg #39336
Comments
Fleshing out my comment from #38719, I feel like leaning on CSS custom properties could drastically simplify things compared to the other PRs I read through exploring this, so I spent a couple hours pulling together an example. Again, apologies if I’ve missed something that makes this impractical or if this is the wrong place for this kind of feedback! The default CSS custom property values for widths would appear in the global styles block ( <div class="wp-layout-container has-default-widths wp-block-group">
<!-- inner content width is --wp--layout--content-size -->
<div class="wp-layout-container wp-block-group">
<!-- container width is --wp--layout--content-size -->
<!-- inner content width is --wp--layout--content-size -->
</div>
<div class="wp-layout-container wp-block-group alignwide">
<!-- container width is --wp--layout--wide-size -->
<!-- inner content width is --wp--layout--wide-size -->
</div>
<div class="wp-layout-container has-default-widths wp-block-group alignwide">
<!-- container width is --wp-wide-size -->
<!-- inner content width is --wp--layout--content-size -->
</div>
</div>
<div
class="wp-layout-container has-custom-widths wp-block-group"
style="--wp--layout--content-size--custom: 825px; --wp--layout--wide-size--custom: 1350px;"
>
<!-- inner content width is --wp--layout--content-size--custom -->
<div class="wp-layout-container wp-block-group">
<!-- container width is --wp--layout--content-size--custom -->
<!-- inner content width is --wp--layout--content-size--custom -->
</div>
<div class="wp-layout-container has-default-widths wp-block-group">
<!-- container width is --wp--layout--content-size--custom -->
<!-- inner content width is --wp--layout--content-size -->
</div>
<div class="wp-layout-container wp-block-group alignwide">
<!-- container width is --wp--layout--wide-size--custom -->
<!-- inner content width is --wp--layout--wide-size--custom -->
</div>
<div class="wp-layout-container has-default-widths wp-block-group alignwide">
<!-- container width is --wp-wide-size--custom -->
<!-- inner content width is --wp--layout--content-size -->
</div>
</div> :root {
/* These would appear with all the other theme.json-generated custom properties: */
--wp--layout--content-size: 650px;
--wp--layout--wide-size: 1000px;
/* These custom width values would be output as inline styles on a container element */
/* --wp--layout--content-size--custom: 850px; */
/* --wp--layout--wide-size--custom: 1400px; */
}
.wp-layout-container > * {
width: var(--wp--layout--content-size--custom, var(--wp--layout--content-size));
max-width: 100%;
margin-left: auto;
margin-right: auto;
}
.wp-layout-container.has-default-widths > * {
width: var(--wp--layout--content-size);
}
.wp-layout-container.alignwide,
.wp-layout-container.alignwide:not(.wp-layout-container.has-default-widths) > * {
width: var(--wp--layout--wide-size--custom, var(--wp--layout--wide-size));
}
.wp-layout-container.alignfull,
.wp-layout-container.alignfull:not(.wp-layout-container.has-default-widths) > * {
width: 100%;
} I have a full working example in Codepen based on output from Blockbase: https://codepen.io/cbirdsong/pen/dyJbyXO Changes to the default markup:
As an aside, this could all be drastically simpler if the very confusing "inherit default layout" option was removed or reworked, as discussed in #36082. The |
Thanks a lot for the comment, and for taking the time to illustrate things via code @cbirdsong 🙇 In my mind, the combination of global and local CSS variables/properties might have the potential to strike a balance between semantic classnames and bespoke, container-specific styles. There are competing but, I believe, reconcilable demands in relation to how we define layout styles at various levels:
I know you've seen it before, but just to document for others who might be reading: #38998 (comment) and #38998 (comment) contain more discussion on points 1 and 2. The over-arching hooks, such as I suspect the area that needs careful consideration is how to represent auto-generated output – styles, classes and other "states" – based on declarations in block/theme.json. Where (and in which format) to output them, while adhering to the hierarchical contract of Theme > Global Styles > Block, and also having a maintainable system to do so is the current challenge of both the layout and the style engine work. A marriage of inline styles and CSS vars as you've demonstrated is one way to do it I'm sure. Kind of related, is an idea to hook into theme.json presets to output styles. |
I feel like the idea that the editor can satisfactorily handle layout for every use case on 40%+ of the internet is fundamentally flawed – is this issue the right place to discuss that, or is there somewhere else I should take that discussion? |
The editor isn't able to satisfactorily meet every conceivable layout challenge on the internet, but I'm not convinced anyone is making the claim that it can or ever will. Plus this will be a slow moving train I suspect, the result of which – at least initially – will be a small and opinionated set of layouts followed by maturation and expansion.
Good question. The motivation behind this issue is that Gutenberg should widen the availability of default layout options in the editor, so perhaps it'd be helpful to open the topic on a new discussion thread. I for one am interested in joining in, so thanks! |
Update 2022/03/25: We've been digging in and exploring a few potential longer-term options for how we might render out common layout styles to consolidate how things work (e.g. #39374 and #39708) — these are some experiments to think about how we might solve for issues like Global Styles: Make the default layout work as a preset. However, with the timeline for WordPress 6.0 fast approaching, we'll likely pause some of these more open-ended explorations, and focus more on the Prerequisites issues over the next couple of weeks:
Broadly the above issues cover the areas of better exposing some of the existing layout options that already exist, and improving the behaviour / stability of those features. CC: @scruffian (or anyone else looking closely at this), please comment if there are other shorter-term issues that you feel are high priority for us to 👀 at! |
@andrewserong @ramonjd What's the latest update on this one? |
Update 2022/05/20:
Some of the current work underway:
Some of the current thinking about the above issues are that:
While in the shorter-term, I'm very keen for us to resolve the issue of generating Next steps:
|
Update 2022/05/31: One of the main areas I've been looking into is how we can render out blockGap values at the block level in The current goals / explorations of that PR are:
The result is that we should be able to have gap output like the following: /* Root level blockGap in theme.json */
body .is-layout-flex {
gap: 1.5rem;
}
/* Block level in theme.json */
.wp-block-buttons.is-layout-flex {
gap: 5px 20px;
} This exploration seeks to both solve the issue of supporting blockGap at the block level in theme JSON, as well as dipping our toes into adding in semantic classnames for the layout support. My hope is that by declaratively describing the layout in the JSON file, it'll be easier to both consolidate and extend the layout support, and have logical classnames. That's a bit of a bigger question though, so the idea with the PR is to see if there's a minimally viable approach to adding it in. If it does appear to be viable, then it could unlock follow-up PRs to address the other features of layout support and make them declarative in their output, too. There's still more work to be done on the PR before it's ready for review (a couple of edge cases to deal with, tests are failing, etc), but I'm very happy for feedback if anyone's keen to take a look. |
Expanding on what I said in #40159: I think it would be best if the layouts used throughout the editor/front-end CSS were conceptualized/divided more cleanly. Ideally, every
Viewed this way, Going over the blocks with significant layout components, here's how I'd divide them:
Listing these out makes it clear that customized spacing values shouldn't be applied directly to a Here is a stab at some CSS that would cover flow, row, stack and grid, accounting for spacing customization across all of them: First, set up the basic layouts and spacing: .is-layout-flow > * + * {
margin-top: var(--wp--default--spacing);
}
.is-layout-stack,
.is-layout-row {
display: flex;
gap: var(--wp--default--spacing);
}
.is-layout-stack {
flex-direction: column;
}
.is-layout-row {
flex-direction: row;
}
.is-layout-grid {
display: grid;
gap: var(--wp--default--spacing);
}
.wp-block-group {
--wp--default--spacing: 20px;
}
.wp-block-buttons {
--wp--default--spacing: 10px;
}
.wp-block-row {
--wp--default--spacing: 30px;
}
.wp-block-gallery {
--wp--default--spacing: 1px;
} When custom spacing values are set by a user in the editor, a .is-layout-flow.has-custom-spacing > * + * {
margin-top: var(--wp--custom--spacing, var(--wp--default--spacing));
}
.is-layout-stack.has-custom-spacing,
.is-layout-row.has-custom-spacing {
gap: var(--wp--custom--spacing, var(--wp--default--spacing));
}
.is-layout-grid.has-custom-spacing {
gap: var(--wp--custom--spacing, var(--wp--default--spacing));
} The
.has-spacing-10 {
--wp--custom--spacing: var(--wp--preset--spacing--10);
}
.has-spacing-20 {
--wp--custom--spacing: var(--wp--preset--spacing--20);
}
.has-spacing-30 {
--wp--custom--spacing: var(--wp--preset--spacing--30);
}
/* etc, etc */ Other benefits of this approach:
Footnotes
|
Thanks for sharing the ideas @cbirdsong! Unfortunately there were a number of subtle issues at play when the blockGap behaviour relied more directly on CSS variables. The main issue tracking styling conflicts was #36521 and it partially resolved in #37360, which attempted to remove most used of CSS variables for block gap styles. The problem comes when we have a flow-based block with a custom gap value like I think a safer approach for the layout support is to rewrite it to support directly computed values at the block level in theme.json / global styles (to restore that behaviour). We can use root-level CSS variables as spacing values, but I think we should avoid resetting / re-declaring the CSS variables from within individual block's inline styles since it can introduce subtle and difficult to debug styling issues. For a bit more context, I'm currently exploring this (computing / outputting gap values directly) in #40875 (there's a bit more work to do before it's ready for review), which is exploring the idea that @youknowriad raised in #36521 (comment) last year.
That's an interesting point. My understanding was that in the case of As a first step, for simplicity of implementation, I'd be inclined to keep
A limitation here of trying to represent the layout in a single class is that there are many different parameters for each particular layout type. One way to think of it is that the base class contains just those common styles as a starting point for achieving the layout, but we then defer to utility classes for the things that can be variable (e.g. orientation, justification, etc). There's an open PR from @glendaviesnz (#41487) to add back in utility classnames for backwards compatibility with Buttons block, etc. Just thought I'd mention it in case you wanted to add any feedback on that PR 🙂 |
Hmm, I can see you're right about this in the case of inline styles and flow layout. I had solved that problem by applying the custom property to the child, but that can't work with an inline style: View Code.is-layout-flow > * + * {
margin-top: var(--flow-gap, 1.25rem);
}
.is-layout-flow.has-gap-1 > * {
--flow-gap: 0.25rem;
}
/* etc, etc */ However, it does work for custom values in general. In my non-theme.json themes, I've successfully used the
I think the issue here is that "one-dimensional" isn't enough to hang it on conceptually. You see the issues start as soon as you write the justification utility classes. For vertical layout, you need to modify .wp-block-buttons {
&.is-vertical {
flex-direction: column;
> .wp-block-button {
&:last-child {
margin-bottom: 0;
}
}
}
// Increased specificity to override blocks default margin.
> .wp-block-button {
display: inline-block;
margin: 0;
}
&.is-content-justification-left {
justify-content: flex-start;
&.is-vertical {
align-items: flex-start;
}
}
&.is-content-justification-center {
justify-content: center;
&.is-vertical {
align-items: center;
}
}
&.is-content-justification-right {
justify-content: flex-end;
&.is-vertical {
align-items: flex-end;
}
}
&.is-content-justification-space-between {
justify-content: space-between;
}
} Changing layout behavior based on the presence of .is-layout-stack {
flex-direction: column;
&.is-content-justification-left {
align-items: flex-start;
}
&.is-content-justification-center {
align-items: center;
}
&.is-content-justification-right {
align-items: flex-end;
}
}
.is-layout-row {
flex-direction: row;
&.is-content-justification-left {
justify-content: flex-start;
}
&.is-content-justification-center {
justify-content: center;
}
&.is-content-justification-right {
justify-content: flex-end;
}
&.is-content-justification-space-between {
justify-content: space-between;
}
} |
That's a great point, thanks for the example CSS, that very much highlights the improvement of moving to separate classes between I'm hopeful that if and when #40875 is ready for review / looks viable, in a follow-up we can tackle the utility classes, and I think you've made a strong case for exploring seeing if we can separate out the |
Update 2022/06/21: The PR to explore refactoring the Layout support to centralise base styles output and add back in support for rendering blockGap values at the block level in
It's a pretty large PR that proposes rethinking how the Layout support works — unfortunately, it's a difficult PR to reduce in size, as the changes rely on a refactor happening all at once. The hope is that the PR can progress a few different ideas, incrementally get us toward reducing duplication of container / style tags, and a step forward in outputting semantic classnames, and improving the logic of how the support works. I'm sure there are edge cases that I've missed while working on the PR, so I'm very happy for feedback / testing to help with the next stage of the PR, and to see whether or not folks think it'll be a viable path forwards. |
I recognize this is already a huge PR, but to me it would make sense to go ahead and get the |
Thanks for the feedback @cbirdsong!
The PR has been a tricky one to rein in, in terms of scope, and in my explorations so far, switching to these classnames means addressing more aspects of introducing the remaining semantic classnames of the layout attributes (to help close out #38719). In the Buttons block, for example, the I think this is tricky to do in a backwards compatible way without running into edge cases, so while the step of introducing
Definitely my intention would be for us to immediately explore a follow-up that looks at how we go about implementing the remaining semantic classnames and safely move the Buttons block over to a new classname structure — my hope is that the follow-up PR would be a bit easier to read so that we could get more contributors to offer their feedback / ideas in how to shape things, and we could tease apart the implications of splitting the |
Update 2022/07/12: The Layout refactor PR (#40875) has now been merged in. This PR implemented a centralised place for layout definitions to be stored, and to be output in the global styles stylesheet using semantic classnames based on the layout type, block-level support for blockGap in theme.json, and some de-duping of redundant
Also, now that #40875 has landed, the PR (#42085) to add support for root padding CSS variables and factoring in padding when outputting |
Update 2022/07/20:
In Progress PRs: The focus currently is on adding in a few new features, and optimising output, across the following PRs:
|
Update 2022/08/03: Recently merged PRs:
In Progress PRs / tasks:
|
@andrewserong What's the latest here? I think progress is done in terms of what can make it for 6.1? |
Thanks for the ping @apeatling, yes I think progress is nearly done for what can make it for 6.1. The main work to consolidate and improve the output for base layout styles and re-enable block spacing at the block level in global styles is complete. There are a couple of tidying up tasks that still need to be completed. Here's an update: Update: 2022/08/17: Recently merged PRs:
In Progress / hoping to make it in time for 6.1:
All in all, I think we'll be ready for the 6.1 feature freeze next month. Beyond 6.1, we should be in a good place for exploring adding additional layout types and controls, along with collaborating on the style engine project to encapsulate rules into stable utility classes, as flagged by @ramonjd in the latest style engine update. |
Update: 2022/10/06: With all layout changes that were slated for 6.1 now backported and in the 6.1 beta, now is a good time to close out this particular tracking issue. For bug fixes and smaller tasks, there is a new For tracking work slated for WordPress 6.2, there is now a fresh issue for tracking those particular higher level tasks over in: #44720. I'll close out this issue, and I'm happy to help out with status updates on #44720 as work kicks off following the stabilising of features that landed in 6.1. |
This issue will track experimentation, discussion and other output in relation to the extension of Gutenberg's layout capabilities.
Prerequisites
There are some outstanding issues with the current layout implementation we should address as a priority:
theme.json
for classic themes)The direction
Blocks may opt into Gutenberg’s experimental layout API through their individual block.json files, for example:
There are presently two layouts: flex and flow. The aim of this tracking issue is to explore approaches that will open up the ability to add and control advanced layouts with blocks that go beyond the block gap, or margin/padding controls.
In #33687 a"layout" is defined as:
The corresponding UI objective is to allow users to choose between a set of layouts and related options in the editor.
Current layout related PRs, issues and other background context
Earlier layout related drafts, experiments and WIPs
Future layout possibilities:
Future layout WIPs and experiments:
Why?
Gutenberg should widen the availability of default (and robust) layout options so that users can structure their sites in various ways.
Rather than provide a panacea for every layout problem, we could offer common patterns that appear, and have proved successful, in modern websites.
It would be preferable to provide an extensible system through which we could add future layouts as well.
Current work
There has been some preliminary discussion around how to refactor existing, and integrate new, layouts into Gutenberg in #38974. That discussion has since evolved into a proposal for a refactor of how the Layout support works in: #40875
So far, the work has been to target the current layout implementation and focussing on the means to register and output styles, while trying to take into account contemporary ideas and explorations surrounding the Style Engine.
The plates are still up in the air and spinning, but some concepts that folks are trying (or will have to try) to reconcile include:
What’s next (short term)
Continuation of the experimentation and research phase
With the following goals:
A further line of inquiry is to research how to provide layout options at the root and inner block level, that is, applying "layout" to a blocks container element (and therefore immediate first-level descendants) and targeting specific inner block "containers".
The relevance of the Style Engine
Integral to the refactor and addition of layout styles to Gutenberg is the Style Engine, which has thus far a few stated goals and many more hopes pinned upon it.
A distilled statement of these goals and hopes might be “to offer a consistent API for generating classnames and rendering CSS for blocks”.
In the context of layouts (and beyond), a centralized way to generate lean, consistent CSS and classnames is important to:
One potential path forward is to explore centralising base layout styles output in global styles, and use a centralised set of definitions for the various layout types. This is being explored in #40875.
TODO
This is a short-list attempting to capture some incremental steps toward a centralised approach for outputting layout styles, instead of layout styles being applied one-at-a-time when each individual block is rendered.
style
tags. (Merged in #40875).space-between
should not be available in vertical orientation?)disable-layout-styles
support flag, to explore whether or not we should prevent UI controls from being displayed that have no reachable output when the styles are disabled (e.g. custom content sizes). This was raised in this comment.The text was updated successfully, but these errors were encountered: