-
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
Global styles: force root min-height of 100% for backgrounds #59809
Conversation
// Abstract into something like static::update_separator_declarations. | ||
// @TODO - how can this be overwritten by theme.json, if at all? styles.dimensions.minHeight? | ||
// @TODO - implement the same logic in the editor https://github.com/WordPress/gutenberg/blob/f079bd2f7fe8e4c5694fc3feb276567777f9997b/packages/block-editor/src/components/iframe/index.js#L252-L252 | ||
if ( static::ROOT_BLOCK_SELECTOR === $selector ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@andrewserong @tellthemachines
Before I go too deep on this PR, I wanted to garner a few opinions on how we might achieve the objectives.
The PR's description outlines the why of this PR, but the technical criteria is that, when there's a gradient background or background size of cover at the root level, we want to force the window (HTML
or :root
) to have a min-height: 100%
so the background stretches the full height without scrolling.
This is a naive attempt to add the requisite CSS.
The first, hopeful, attempt was to switch the static::ROOT_BLOCK_SELECTOR
from 'body'
to :root/html
, and then set the value of styles.dimensions.minHeight
. This would have been my preferred approach, however, it came with a bunch of unknowns, one of the weirdest being that it doesn't allow themes to overwrite a browser's default margins.
Then I mused whether html
could be a top level "element", and therefore be "styleable", but I abandoned that idea. It might have legs, I don't know, but it'd be a bunch of work.
Then I landed here, at the MVP.
It works, but I would be glad of alternative points of view 😄
Some considerations:
- How, if at all, could a theme developer overwrite the min-height value? Should they at all? Maybe not since it's tightly coupled to the background option. Or am I thinking to hard about it? 😄
- I plan to abstract the logic - if you can see avenues for optimization, that'd be great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some quick thoughts off the top of my head:
- I think it's fine if the output is
:root
but that theROOT_BLOCK_SELECTOR
is stillbody
as the rules here can be different to the selector since it's a slightly non-standard use case. The important thing IMO is that we're outputting root rules of some kind just a single time. Out of curiosity, why do we need the rule to be attached to:root
instead ofbody
? Is it because of potential margins onbody
? - Should there be a way for folks to explicitly switch this setting off? I do like that it's guarded behind only being output when
background
orbackgroundImage
is set at the root level 👍. - Since you asked the question of whether a theme developer could overwrite the min-height value, I think I can imagine someone wanting to do just that! I don't think it'd necessarily need to be implemented in this PR, but if a theme were to set the root
styles.dimensions.minHeight
value in theirtheme.json
file, perhaps that could overwrite the value used here? In that case, though, I imagine the theme developers would expect the value to always be output, not just whenbackground
is set 🤔 - In terms of abstraction, what did you have in mind? If it's only being used in one place, I like the idea of it essentially being private code so that it could be easier to change in follow-ups, potentially.
Thanks for digging in here!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How, if at all, could a theme developer overwrite the min-height value? Should they at all?
Is there a need for overriding this value? It's an essential part of making sure gradients and background images work correctly on the site background.
A possible alternative would be setting min-height to a custom property via the background block support (so we'd only output it if there were a background gradient/image), and then we'd only have to set the custom property's value in this function when static::ROOT_BLOCK_SELECTOR === $selector
. However, that would mean outputting min-height: var(--something)
whenever there were a background set. Would we ever want to set min-height together with background in other circumstances?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the topic of abstraction, I'm not entirely sure about the reasoning behind static::update_separator_declarations
but it looks like something that should be solved in the block itself by skipping serialization and adding custom logic to deal with it 🤔 It would be great to reduce the amount of functions in the theme.json class if at all possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the helpful feedback! I feel like I have some paths forward, now 🙇🏻
Out of curiosity, why do we need the rule to be attached to :root instead of body? Is it because of potential margins on body?
Good question! Two reasons:
min-height: 100%
on the body tag doesn't have any effect on when using background gradients.min-height: 100vh
, however, does. See: https://codepen.io/BoganJustice/pen/jORMKKE- I couldn't quite get the scrolling to behave with adding it to the body tag because of various margins of nested elements. The video below is testing
100vh
but it's also the same for100%
2024-03-15.10.06.13.mp4
I haven't reached the end of experimentation, yet though. If it's just the logged-in admin view, then it might be something we can deal with.
Also, I suspect min-height: 100vh;
on the body takes care of most situations, in which case it would fit nicely with theme.json styles.dimensions.minHeight
.
Should there be a way for folks to explicitly switch this setting off? I do like that it's guarded behind only being output when background or backgroundImage is set at the root level
If I can get it to play with styles.dimensions.minHeight
then maybe it'll be already taken care of.
Is there a need for overriding this value? It's an essential part of making sure gradients and background images work correctly on the site background.
You're right. It must be 100%
for it to have the intended effect on the background. I like the idea of creating a CSS custom property to be more flexible - that could potentially be overridable.
But yeah, it might be good enough to start with the CSS rule and then decide before creating a global CSS property that folks might rely on.
If it's only being used in one place, I like the idea of it essentially being private code so that it could be easier to change in follow-ups, potentially
It would be great to reduce the amount of functions in the theme.json class if at all possible.
Good points. I'll leave the code in place for now. I'm not excited about another for loop there, but I can't see a tidy alternative.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of creating a CSS custom property to be more flexible
The custom property wasn't for flexibility, it was a way to avoid the for loop here 😅 .
The idea is you'd set min-height: var(--something)
in the background block support, whenever you're setting gradients or background images. But the property itself isn't set unless the declarations are being applied to the root level. You'd probably need something like `html { --something: 100%; } body { --something: unset } so that value doesn't accidentally apply to all background supports. It's messy though, unless there's a use for min-height in non-root cases.
*/ | ||
if ( $should_set_root_min_height ) { | ||
$block_rules .= static::to_ruleset( | ||
'html', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why on the HTML and not BODY?
- setting it on the body revealed potential issues, e.g., the background gradient did not always stretch (unless we used 100vh)
- Also unpredictable margins causing scrolling , e.g., an unstyled H1 at the root of the document in empty theme
- Settings "styles.dimensions.minHeight" in theme.json would overwrite the value - I suppose this would be fine for theme devs who know what they're doing, but for folks using themes that have "styles.dimensions.minHeight" hardcoded it would mean that backgrounds don't behave as they should, that is, with the background gradient/image filling the window.
- 'HTML' is also the selector that's being used in the editor to achieve the same effect.
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
c59a3a4
to
9a1b6f4
Compare
@@ -2633,6 +2641,29 @@ static function ( $pseudo_selector ) use ( $selector ) { | |||
} | |||
unset( $declarations[ $index ] ); | |||
} | |||
|
|||
if ( $is_root_selector && ( | |||
'background-size' === $declaration['name'] && 'cover' === $declaration['value'] || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering, would we also want the min-height rule to be output if we use contain
as the background size? I.e. should we always output the min height if any background image is set, a little like how we're outputting if any background
shorthand property is in use? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering, would we also want the min-height rule to be output if we use contain as the background size?
Good question. I don't know, but I'll test it out.
I.e. should we always output the min height if any background image is set, a little like how we're outputting if any background shorthand property is in use?
We could I suppose, so long as it behaves as expected with other possible background property values. I'll also play around with it.
Nicely captured, thanks for confirming!
Sounds reasonable to me 👍 |
Removed value test as it's already checked in compute_properties function
Well, la-di-dah
a6353e8
to
adb016a
Compare
…ound-size of "cover"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is testing very nicely for me, and feels safely guarded in that it'll only be output if folks are using a site-wide gradient or background image, so the chances for any negative impact (i.e. sites out in the wild with a site-wide gradient) seem very minimal to me, and most likely it'll feel more like a bug fix 👍
Also, as you mention, we can always explore allowing the value to be customised in follow-ups if need be.
Looking good with site-wide background images in local testing:
Before | After |
---|---|
LGTM! ✨
Thanks for all the help testing these @andrewserong 🙇🏻 |
…ss#59809) Set html min-height to 100% for background and background-image Hijack the existing duotone for loop to do the dirty work. Update unit tests Co-authored-by: ramonjd <[email protected]> Co-authored-by: andrewserong <[email protected]> Co-authored-by: tellthemachines <[email protected]>
What?
Initial commit - set html min-height to 100% for backgrounds (
background
orbackground-image
properties)See: #59354 (comment)
Why?
The objective is to ensure that the
:html
selector has a minimum height of100%
when:styles.color.background
)styles.background.backgroundImage
)The reason is so the background gradient or image takes up the entire screen.
The block editor already does this by giving the HTML tag a min-height of 100% all the time, so the corollary objective is to have the frontend match this.
How?
Not sure yet 😄
So far, just detecting the background and hardcoding
html { min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px)); }
Testing Instructions
In the site editor or in theme.json, add a gradient background to your site:
Also try with a background image:
Screenshots or screencast