Skip to content
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: Add CSS vars for root level settings #29714

Closed
wants to merge 3 commits into from

Conversation

scruffian
Copy link
Contributor

@scruffian scruffian commented Mar 10, 2021

Description

We need a way for blocks to implement the default colors set in root. Often this happens via CSS inheritance but sometimes we want to use the theme colors in a block in a different way, which won't work with inheritance.

This PRs adds CSS variables for root level settings from theme.json:

--wp--style--color--background: #0000ff;
 --wp--style--color--text: #ff0000;
 --wp--style--typography--font-size: var(--wp--preset--font-size--normal);
 --wp--style--typography--line-height: var(--wp--custom--line-height--body);
 --wp--style--typography--font-family: var(--wp--preset--font-family--base);

This gives blocks a standard way of accessing the default colors for a site which is independent of the theme.

This PR was co-created with @MaggieCabrera

How has this been tested?

  • Switch to a block theme
  • Set colors for the text color and background

Types of changes

New feature (non-breaking change which adds functionality)

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • I've tested my changes with keyboard and screen readers.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR.

@scruffian scruffian added [Block] Calendar Affects the Calendar Block Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json labels Mar 10, 2021
@scruffian scruffian self-assigned this Mar 10, 2021
@github-actions
Copy link

github-actions bot commented Mar 10, 2021

Size Change: 0 B

Total Size: 1.31 MB

ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.12 kB 0 B
build/annotations/index.js 2.93 kB 0 B
build/api-fetch/index.js 2.42 kB 0 B
build/autop/index.js 2.28 kB 0 B
build/blob/index.js 673 B 0 B
build/block-directory/index.js 6.6 kB 0 B
build/block-directory/style-rtl.css 993 B 0 B
build/block-directory/style.css 995 B 0 B
build/block-editor/index.js 116 kB 0 B
build/block-editor/style-rtl.css 13 kB 0 B
build/block-editor/style.css 13 kB 0 B
build/block-library/blocks/archives/editor-rtl.css 61 B 0 B
build/block-library/blocks/archives/editor.css 60 B 0 B
build/block-library/blocks/audio/editor-rtl.css 58 B 0 B
build/block-library/blocks/audio/editor.css 58 B 0 B
build/block-library/blocks/audio/style-rtl.css 112 B 0 B
build/block-library/blocks/audio/style.css 112 B 0 B
build/block-library/blocks/block/editor-rtl.css 161 B 0 B
build/block-library/blocks/block/editor.css 161 B 0 B
build/block-library/blocks/button/editor-rtl.css 475 B 0 B
build/block-library/blocks/button/editor.css 474 B 0 B
build/block-library/blocks/button/style-rtl.css 515 B 0 B
build/block-library/blocks/button/style.css 515 B 0 B
build/block-library/blocks/buttons/editor-rtl.css 315 B 0 B
build/block-library/blocks/buttons/editor.css 315 B 0 B
build/block-library/blocks/buttons/style-rtl.css 368 B 0 B
build/block-library/blocks/buttons/style.css 368 B 0 B
build/block-library/blocks/calendar/style-rtl.css 208 B 0 B
build/block-library/blocks/calendar/style.css 208 B 0 B
build/block-library/blocks/categories/editor-rtl.css 84 B 0 B
build/block-library/blocks/categories/editor.css 83 B 0 B
build/block-library/blocks/categories/style-rtl.css 79 B 0 B
build/block-library/blocks/categories/style.css 79 B 0 B
build/block-library/blocks/code/style-rtl.css 90 B 0 B
build/block-library/blocks/code/style.css 90 B 0 B
build/block-library/blocks/columns/editor-rtl.css 190 B 0 B
build/block-library/blocks/columns/editor.css 190 B 0 B
build/block-library/blocks/columns/style-rtl.css 422 B 0 B
build/block-library/blocks/columns/style.css 422 B 0 B
build/block-library/blocks/cover/editor-rtl.css 603 B 0 B
build/block-library/blocks/cover/editor.css 604 B 0 B
build/block-library/blocks/cover/style-rtl.css 1.22 kB 0 B
build/block-library/blocks/cover/style.css 1.22 kB 0 B
build/block-library/blocks/embed/editor-rtl.css 486 B 0 B
build/block-library/blocks/embed/editor.css 486 B 0 B
build/block-library/blocks/embed/style-rtl.css 401 B 0 B
build/block-library/blocks/embed/style.css 400 B 0 B
build/block-library/blocks/file/editor-rtl.css 301 B 0 B
build/block-library/blocks/file/editor.css 300 B 0 B
build/block-library/blocks/file/frontend.js 772 B 0 B
build/block-library/blocks/file/style-rtl.css 255 B 0 B
build/block-library/blocks/file/style.css 255 B 0 B
build/block-library/blocks/freeform/editor-rtl.css 2.45 kB 0 B
build/block-library/blocks/freeform/editor.css 2.45 kB 0 B
build/block-library/blocks/gallery/editor-rtl.css 704 B 0 B
build/block-library/blocks/gallery/editor.css 705 B 0 B
build/block-library/blocks/gallery/style-rtl.css 1.06 kB 0 B
build/block-library/blocks/gallery/style.css 1.05 kB 0 B
build/block-library/blocks/group/editor-rtl.css 160 B 0 B
build/block-library/blocks/group/editor.css 160 B 0 B
build/block-library/blocks/group/style-rtl.css 57 B 0 B
build/block-library/blocks/group/style.css 57 B 0 B
build/block-library/blocks/heading/editor-rtl.css 129 B 0 B
build/block-library/blocks/heading/editor.css 129 B 0 B
build/block-library/blocks/heading/style-rtl.css 76 B 0 B
build/block-library/blocks/heading/style.css 76 B 0 B
build/block-library/blocks/html/editor-rtl.css 281 B 0 B
build/block-library/blocks/html/editor.css 281 B 0 B
build/block-library/blocks/image/editor-rtl.css 717 B 0 B
build/block-library/blocks/image/editor.css 716 B 0 B
build/block-library/blocks/image/style-rtl.css 476 B 0 B
build/block-library/blocks/image/style.css 478 B 0 B
build/block-library/blocks/latest-comments/style-rtl.css 281 B 0 B
build/block-library/blocks/latest-comments/style.css 282 B 0 B
build/block-library/blocks/latest-posts/editor-rtl.css 137 B 0 B
build/block-library/blocks/latest-posts/editor.css 137 B 0 B
build/block-library/blocks/latest-posts/style-rtl.css 523 B 0 B
build/block-library/blocks/latest-posts/style.css 522 B 0 B
build/block-library/blocks/legacy-widget/editor-rtl.css 557 B 0 B
build/block-library/blocks/legacy-widget/editor.css 557 B 0 B
build/block-library/blocks/list/style-rtl.css 63 B 0 B
build/block-library/blocks/list/style.css 63 B 0 B
build/block-library/blocks/media-text/editor-rtl.css 176 B 0 B
build/block-library/blocks/media-text/editor.css 176 B 0 B
build/block-library/blocks/media-text/style-rtl.css 492 B 0 B
build/block-library/blocks/media-text/style.css 489 B 0 B
build/block-library/blocks/more/editor-rtl.css 434 B 0 B
build/block-library/blocks/more/editor.css 434 B 0 B
build/block-library/blocks/navigation-link/editor-rtl.css 617 B 0 B
build/block-library/blocks/navigation-link/editor.css 619 B 0 B
build/block-library/blocks/navigation-link/style-rtl.css 1.16 kB 0 B
build/block-library/blocks/navigation-link/style.css 1.16 kB 0 B
build/block-library/blocks/navigation/editor-rtl.css 1.19 kB 0 B
build/block-library/blocks/navigation/editor.css 1.19 kB 0 B
build/block-library/blocks/navigation/style-rtl.css 272 B 0 B
build/block-library/blocks/navigation/style.css 271 B 0 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B 0 B
build/block-library/blocks/nextpage/editor.css 395 B 0 B
build/block-library/blocks/page-list/editor-rtl.css 239 B 0 B
build/block-library/blocks/page-list/editor.css 240 B 0 B
build/block-library/blocks/page-list/style-rtl.css 167 B 0 B
build/block-library/blocks/page-list/style.css 167 B 0 B
build/block-library/blocks/paragraph/editor-rtl.css 157 B 0 B
build/block-library/blocks/paragraph/editor.css 157 B 0 B
build/block-library/blocks/paragraph/style-rtl.css 247 B 0 B
build/block-library/blocks/paragraph/style.css 248 B 0 B
build/block-library/blocks/post-author/editor-rtl.css 209 B 0 B
build/block-library/blocks/post-author/editor.css 209 B 0 B
build/block-library/blocks/post-author/style-rtl.css 183 B 0 B
build/block-library/blocks/post-author/style.css 184 B 0 B
build/block-library/blocks/post-comments-form/style-rtl.css 250 B 0 B
build/block-library/blocks/post-comments-form/style.css 250 B 0 B
build/block-library/blocks/post-content/editor-rtl.css 139 B 0 B
build/block-library/blocks/post-content/editor.css 139 B 0 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B 0 B
build/block-library/blocks/post-excerpt/editor.css 73 B 0 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B 0 B
build/block-library/blocks/post-excerpt/style.css 69 B 0 B
build/block-library/blocks/post-featured-image/editor-rtl.css 338 B 0 B
build/block-library/blocks/post-featured-image/editor.css 338 B 0 B
build/block-library/blocks/post-featured-image/style-rtl.css 100 B 0 B
build/block-library/blocks/post-featured-image/style.css 100 B 0 B
build/block-library/blocks/post-title/style-rtl.css 60 B 0 B
build/block-library/blocks/post-title/style.css 60 B 0 B
build/block-library/blocks/preformatted/style-rtl.css 103 B 0 B
build/block-library/blocks/preformatted/style.css 103 B 0 B
build/block-library/blocks/pullquote/editor-rtl.css 183 B 0 B
build/block-library/blocks/pullquote/editor.css 183 B 0 B
build/block-library/blocks/pullquote/style-rtl.css 318 B 0 B
build/block-library/blocks/pullquote/style.css 318 B 0 B
build/block-library/blocks/query-loop/editor-rtl.css 83 B 0 B
build/block-library/blocks/query-loop/editor.css 82 B 0 B
build/block-library/blocks/query-loop/style-rtl.css 315 B 0 B
build/block-library/blocks/query-loop/style.css 317 B 0 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B 0 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B 0 B
build/block-library/blocks/query-pagination/editor-rtl.css 270 B 0 B
build/block-library/blocks/query-pagination/editor.css 262 B 0 B
build/block-library/blocks/query-pagination/style-rtl.css 168 B 0 B
build/block-library/blocks/query-pagination/style.css 168 B 0 B
build/block-library/blocks/query-title/editor-rtl.css 86 B 0 B
build/block-library/blocks/query-title/editor.css 86 B 0 B
build/block-library/blocks/query/editor-rtl.css 131 B 0 B
build/block-library/blocks/query/editor.css 132 B 0 B
build/block-library/blocks/quote/style-rtl.css 169 B 0 B
build/block-library/blocks/quote/style.css 169 B 0 B
build/block-library/blocks/rss/editor-rtl.css 201 B 0 B
build/block-library/blocks/rss/editor.css 202 B 0 B
build/block-library/blocks/rss/style-rtl.css 290 B 0 B
build/block-library/blocks/rss/style.css 290 B 0 B
build/block-library/blocks/search/editor-rtl.css 189 B 0 B
build/block-library/blocks/search/editor.css 189 B 0 B
build/block-library/blocks/search/style-rtl.css 359 B 0 B
build/block-library/blocks/search/style.css 362 B 0 B
build/block-library/blocks/separator/editor-rtl.css 99 B 0 B
build/block-library/blocks/separator/editor.css 99 B 0 B
build/block-library/blocks/separator/style-rtl.css 251 B 0 B
build/block-library/blocks/separator/style.css 251 B 0 B
build/block-library/blocks/shortcode/editor-rtl.css 512 B 0 B
build/block-library/blocks/shortcode/editor.css 512 B 0 B
build/block-library/blocks/site-logo/editor-rtl.css 440 B 0 B
build/block-library/blocks/site-logo/editor.css 441 B 0 B
build/block-library/blocks/site-logo/style-rtl.css 154 B 0 B
build/block-library/blocks/site-logo/style.css 154 B 0 B
build/block-library/blocks/social-link/editor-rtl.css 164 B 0 B
build/block-library/blocks/social-link/editor.css 165 B 0 B
build/block-library/blocks/social-links/editor-rtl.css 796 B 0 B
build/block-library/blocks/social-links/editor.css 795 B 0 B
build/block-library/blocks/social-links/style-rtl.css 1.32 kB 0 B
build/block-library/blocks/social-links/style.css 1.33 kB 0 B
build/block-library/blocks/spacer/editor-rtl.css 308 B 0 B
build/block-library/blocks/spacer/editor.css 308 B 0 B
build/block-library/blocks/spacer/style-rtl.css 48 B 0 B
build/block-library/blocks/spacer/style.css 48 B 0 B
build/block-library/blocks/table/editor-rtl.css 478 B 0 B
build/block-library/blocks/table/editor.css 478 B 0 B
build/block-library/blocks/table/style-rtl.css 485 B 0 B
build/block-library/blocks/table/style.css 485 B 0 B
build/block-library/blocks/tag-cloud/editor-rtl.css 118 B 0 B
build/block-library/blocks/tag-cloud/editor.css 118 B 0 B
build/block-library/blocks/tag-cloud/style-rtl.css 94 B 0 B
build/block-library/blocks/tag-cloud/style.css 94 B 0 B
build/block-library/blocks/template-part/editor-rtl.css 551 B 0 B
build/block-library/blocks/template-part/editor.css 550 B 0 B
build/block-library/blocks/term-description/editor-rtl.css 90 B 0 B
build/block-library/blocks/term-description/editor.css 90 B 0 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B 0 B
build/block-library/blocks/text-columns/editor.css 95 B 0 B
build/block-library/blocks/text-columns/style-rtl.css 166 B 0 B
build/block-library/blocks/text-columns/style.css 166 B 0 B
build/block-library/blocks/verse/style-rtl.css 87 B 0 B
build/block-library/blocks/verse/style.css 87 B 0 B
build/block-library/blocks/video/editor-rtl.css 569 B 0 B
build/block-library/blocks/video/editor.css 570 B 0 B
build/block-library/blocks/video/style-rtl.css 169 B 0 B
build/block-library/blocks/video/style.css 169 B 0 B
build/block-library/common-rtl.css 1.31 kB 0 B
build/block-library/common.css 1.31 kB 0 B
build/block-library/editor-rtl.css 9.54 kB 0 B
build/block-library/editor.css 9.53 kB 0 B
build/block-library/index.js 142 kB 0 B
build/block-library/reset-rtl.css 506 B 0 B
build/block-library/reset.css 507 B 0 B
build/block-library/style-rtl.css 9.54 kB 0 B
build/block-library/style.css 9.55 kB 0 B
build/block-library/theme-rtl.css 692 B 0 B
build/block-library/theme.css 693 B 0 B
build/block-serialization-default-parser/index.js 1.3 kB 0 B
build/block-serialization-spec-parser/index.js 3.06 kB 0 B
build/blocks/index.js 47 kB 0 B
build/components/index.js 186 kB 0 B
build/components/style-rtl.css 16.2 kB 0 B
build/components/style.css 16.2 kB 0 B
build/compose/index.js 9.96 kB 0 B
build/core-data/index.js 12 kB 0 B
build/customize-widgets/index.js 5.78 kB 0 B
build/customize-widgets/style-rtl.css 666 B 0 B
build/customize-widgets/style.css 667 B 0 B
build/data-controls/index.js 830 B 0 B
build/data/index.js 7.22 kB 0 B
build/date/index.js 31.8 kB 0 B
build/deprecated/index.js 738 B 0 B
build/dom-ready/index.js 576 B 0 B
build/dom/index.js 4.61 kB 0 B
build/edit-navigation/index.js 13.4 kB 0 B
build/edit-navigation/style-rtl.css 2.86 kB 0 B
build/edit-navigation/style.css 2.86 kB 0 B
build/edit-post/classic-rtl.css 454 B 0 B
build/edit-post/classic.css 454 B 0 B
build/edit-post/index.js 334 kB 0 B
build/edit-post/style-rtl.css 6.98 kB 0 B
build/edit-post/style.css 6.97 kB 0 B
build/edit-site/index.js 25.2 kB 0 B
build/edit-site/style-rtl.css 4.91 kB 0 B
build/edit-site/style.css 4.9 kB 0 B
build/edit-widgets/index.js 13.1 kB 0 B
build/edit-widgets/style-rtl.css 2.98 kB 0 B
build/edit-widgets/style.css 2.98 kB 0 B
build/editor/index.js 60.4 kB 0 B
build/editor/style-rtl.css 3.9 kB 0 B
build/editor/style.css 3.9 kB 0 B
build/element/index.js 3.44 kB 0 B
build/escape-html/index.js 739 B 0 B
build/format-library/index.js 5.68 kB 0 B
build/format-library/style-rtl.css 637 B 0 B
build/format-library/style.css 639 B 0 B
build/hooks/index.js 1.76 kB 0 B
build/html-entities/index.js 628 B 0 B
build/i18n/index.js 3.73 kB 0 B
build/is-shallow-equal/index.js 710 B 0 B
build/keyboard-shortcuts/index.js 1.65 kB 0 B
build/keycodes/index.js 1.43 kB 0 B
build/list-reusable-blocks/index.js 2.06 kB 0 B
build/list-reusable-blocks/style-rtl.css 629 B 0 B
build/list-reusable-blocks/style.css 628 B 0 B
build/media-utils/index.js 3.08 kB 0 B
build/notices/index.js 1.07 kB 0 B
build/nux/index.js 2.3 kB 0 B
build/nux/style-rtl.css 718 B 0 B
build/nux/style.css 716 B 0 B
build/plugins/index.js 2.01 kB 0 B
build/primitives/index.js 1.03 kB 0 B
build/priority-queue/index.js 791 B 0 B
build/react-i18n/index.js 924 B 0 B
build/redux-routine/index.js 2.82 kB 0 B
build/reusable-blocks/index.js 2.56 kB 0 B
build/reusable-blocks/style-rtl.css 225 B 0 B
build/reusable-blocks/style.css 225 B 0 B
build/rich-text/index.js 11.7 kB 0 B
build/server-side-render/index.js 1.64 kB 0 B
build/shortcode/index.js 1.68 kB 0 B
build/token-list/index.js 848 B 0 B
build/url/index.js 1.95 kB 0 B
build/viewport/index.js 1.28 kB 0 B
build/warning/index.js 1.13 kB 0 B
build/wordcount/index.js 1.24 kB 0 B

compressed-size-action

@oandregal
Copy link
Member

👋 I've looked a bit into this and wanted to share some feedback.

For context, we've tried this approach at the beginning of global styles (see #22296 for a recap) and the issues boiled down to:

  • Opinions. What if the calendar block had different opinions about defaults? Or how a theme can change the design tokens of this block: I mean, not changing the color, but deciding that the header shouldn't have any color at all. I've pushed at Make colors for calendar optional #29731 an alternative to this PR that works well with text & background that should help illustrate this point.

  • Nested content. What should the colors be if the calendar is not a top-level block (it's part of a container block such as group or columns, or perhaps part of a template part, etc)? It seems like for this approach to work well we have to define first which "containers" create this kind of system. Updates to experimental-theme.json #28163 and Global Styles: composable styles for different contexts #27233 could be useful for previous conversations.

Did you try to implement this with the style system (block supports / theme.json)? I'd be curious how far you can get. I can foresee some issues (the current block uses more colors than we have available via block supports).

@scruffian
Copy link
Contributor Author

What if the calendar block had different opinions about defaults

I don't see that this would be a problem. A block can choose to not specify any colors in which case it would simply inherit from its context. Alternatively it can implement its own colors as the calendar block currently does. This change opens up another option which I think would be very welcome to block developers - it gives blocks a way to know what the default colors of the site are and implement them in a flexible way.

What should the colors be if the calendar is not a top-level block
This is a tricky problem, but it's one that exists already for blocks inside containers. I think the solution above could be useful in solving this though - we could redefine these root level variables in certain contexts. For example we could add:

.has-background-text-color {
--wp--styles--root--text: var(--wp--styles--root--background-color);
}

This would change the variable only in the scope defined by this selector.

Did you try to implement this with the style system (block supports / theme.json)?
I think the problem with this approach is that I still would have no way to access the default text and background colors for the block to set them as defaults. The only way to do it would be to expect them to be set via theme.json, which is possible for blocks supported in core, but it's not practical for themes to set defaults for all possible third party blocks.

The advantage of the proposal is particularly for third party block developers - giving them a way to make their blocks look like the theme.

@scruffian scruffian requested review from youknowriad and mtias March 10, 2021 20:34
@carolinan
Copy link
Contributor

I think the calendar block should have its own color and style options, like the table block.

@youknowriad
Copy link
Contributor

This is interesting proposal :)

So like mentionned by @nosolosw is to that we initially started like that for Global styles:

1- Generate a CSS variable for each style config
2- Ask block authors to use these variables in their CSS appropriately.
3- Do not generate any direct style.

We quickly realized that it doesn't work though because of the CSS variable inheritence: when you apply a background to a container, all blocks inside it that support this variable (think buttons, tables...) get their background change in addition to their container, which is not the expected result. This is why we changed the approach, we decided to avoid step 1 and 2 above and just do the step 3 which is: generate the styles directly based on the config. This approach proved to work in a lot of situations just fine.

But what you're showing in this PR that there might be still value in the original approach if it's only "opt-in" per blocks and not the only way to consume global styles.

What you're doing in this PR is:

For each global style config, generate two things: an actual style (like color: red) and a CSS variable definition (--my-var: red). In some situtations, the CSS variable is used, in others we just rely on the actual style and in others, we need both (containers like the root block or any group block come to my mind when I think about blocks that need both definitions)

So this PR is impactful, it changes Global styles conceptually a bit by introducing "two modes" of application of global styles. I'm not against it personally but we'd have to think it properly:

  • Do we want to always apply the two modes to all declarations? (maybe that's fine and sufficient)
  • Do we want to make the CSS variables mode specific to some contexts but not others (For instance in this PR, I see it being useful for the root context, group block and the actual calendar block) and potentially not useful for others? Do we want an API for block to say whether they allow CSS variables in their global style context?
  • Are there any other heuristics like the property itself (for example colors could generate vars while font sizes or something else not, this is of course not a good example, just useful to express the idea)

I'd love more thoughts from @mtias @mcsf and if we ever we decide to go into this direction, we'd have to make sure to clarify the behavior properly in our docs...

@MaggieCabrera
Copy link
Contributor

I find the most important part of this PR to be that we are giving both plugin and theme authors access to the variables that otherwise they didn't have access to (compared to how they can access others such as blocks') that are very important for the theme since they are on the root level.
I understand the problems with inheritance and maybe not all blocks should be making use of these variables, but I see great value in at least having them available.

@oandregal
Copy link
Member

oandregal commented Mar 11, 2021

I left my brain to think about this while sleeping to see how we could address the issues above. Didn't have a lot of time to sum up my thoughts, so my braindump is a bit wordy. TLDR ― I think the core idea has the potential to enable something we aren't able to provide at the moment: maintaining contextual design links, which touches on things we were talking about at #27233

Let's say we have a calendar as a top-level block (within root) and another calendar within a group. We also have this theme.json:

"root": {
  "text": "var(--wp--preset--color--red)"
},
"core/group": {
  "text": "var(--wp--preset--color--blue)"
},
"core/calendar": {
  "background": "var(--wp--preset--color--red)"
}

At the moment:

  1. If the user changes the value of the presets: make --wp--preset--color--red darker and --wp--preset--color--blue lighter. The top-level calendar block will react to the root change. We don't have a way to wire-up the calendar within the group to react to the environment it lives within. This can only happen at the global level (gs sidebar).
  2. If the user changes the value of the calendar block. The intention is that the block has a color of its own, not related to the parents. Doesn't need any contextual information. This works fine today. This can happen at the global level (GS sidebar) or at the local level (block sidebar).
  3. If the user changes the value of the container blocks (for example, sets the color of the group to yellow and the color of the root to pink). Both calendars will stay as they are, they won't change according to the environment they live in.
    1. This can happen either globally (GS sidebar).
    2. This can happen locally (block sidebar).

As Riad suggested, what if all containers (or blocks that opt-in via an API) output both styles and CSS vars. theme.json input:

"root": {
  "text": "var(--wp--preset--color--red)"
},
"core/group": {
  "text": "var(--wp--preset--color--blue)"
},
"core/calendar": {
  "background": "var(--wp--style--color--text)" // NOTE THIS VARIABLE.
}

The CSS output will be:

:root {
  color: var(--wp--preset--color--red);
  --wp--style--color--text: var(--wp--preset--color--red);
}
.wp-block-group {
  color: var(--wp--preset--color--blue);
  --wp--style--color--text: var(--wp--preset--color--blue);
}

.wp-block-calendar{
  color: var(--wp--style--color--text); // NOTE THIS VARIABLE.
}

With this CSS we can make both 1 and 3.1 work because the value of the variable used by the calendar depends on the environment (root, group, etc) but it's agnostic as to which environment it lives in.

We can do this with one variable per each style property we expose via theme.json. If we wanted all properties, this would be the whole list:

--wp--style--border--color
--wp--style--border--radius
--wp--style--border--style
--wp--style--border--width
--wp--style--color--text
--wp--style--color--background
--wp--style--color--link
--wp--style--color--gradients
--wp--style--spacing--padding
--wp--style--typography--font-size
--wp--style--typography--font-family
--wp--style--typography--font-weight
--wp--style--typography--line-height
--wp--style--typography--text-decoration
--wp--style--typography--text-transform

However, we still need to make 3.2 work as well.

To make it backward-compatible, we need an approach that doesn't serialize anything to the DOM because we can't rewrite old posts. What if we use the preset classes to set the variables as well? Example:

What we do now:

.has-red-color {
  color: red;
}

// At the moment, we only enqueue this if the block
// defines a preset different than the defaults.
.wp-block-columns.has-red-color {
  color: #c6352e;
}

What we could do:

// Color is set for any block with the class.
.has-red-color {
  color: red;
}

// Variables are set only for "containers"
.wp-block-group.has-red-color,
.wp-block-columns.has-red-color {
  --wp--style--color--text: red;
}

// We still do this if the block
// defines its own presets.
// It'll overrride the above's ruleset
// if it's present.
.wp-block-columns.has-red-color {
  color: #c6352e;
  --wp--style--color--text: #c6352e;
}

This would work for 3.2, but not fully: what if the user selects for the container a custom color (which doesn't attach the preset classes to the block but uses inline styles instead). For new blocks, we could add the CSS variable as inline styles for the container, but this won't work to address old posts.

So, this is how far I've gotten to develop this idea. The issue I am not sure how to address is custom colors set at the block level for old posts. But the rest seems that it could work really nicely and reduces the need for "nested contexts" we were talking about in #27233 Perhaps we only need to be able to add template parts to the equation. I see a couple of ways to do it, but don't want to divert the conversation from this.

@oandregal
Copy link
Member

edited my comment ☝️ to fix a couple of typos

@oandregal oandregal mentioned this pull request Mar 11, 2021
82 tasks
@oandregal
Copy link
Member

#29891 may be relevant to this discussion. In particular, as per design mockups, there's going to be a background element blocks can tap into. The specific implementation of elements (chaining selectors, CSS Custom Properties, etc) is going to be defined as we implement each.

@youknowriad
Copy link
Contributor

@scruffian @nosolosw I've been thinking about this PR again and I think we should do it, but I also think that we should be doing it with the following rules:

  • On root level generate both CSS variables and regular styles
  • On block level (or block context) which means whenever someone writes this in "theme.json"
"my/block": {
    "color": { "text": "red" }
}

In this case, we should check the config of the block itself:

  • if we do not find the block or do not find any config, generate regular styles (no css variables)
  • if we find a style (new top level property that is different than "supports" because I think these two thing are separate) config in block.json like that:
"style": {
   "color": {
      "text": "variable" // values here can be: "variable", "default", or [ "variable", "default"]
   }
}

generate the style according to the config.

  • block supports (hooks) can also use this style to generate the styles properly

Reasoning

  • This allows us to avoid the "skipSerialization" flag we're introducing to different flags and blocks and instead have everything rely on the CSS variable for these cases. (for instance setting the color of the button block)
  • block supports is a way to add features to blocks but doesn't map 1-1 to theme.json
  • This proposal reintroduces the behavior that was originally used for Global styles but that proved to be non useful and that breaks if applied consistently to all styles but it does solve some use-cases where regular styles applied to the wrapper don't work.

I'd love your thoughts on that @mtias @mcsf @scruffian @nosolosw @ockham @gziolo

@gziolo
Copy link
Member

gziolo commented Mar 29, 2021

This allows us to avoid the "skipSerialization" flag we're introducing to different flags and blocks and instead have everything rely on the CSS variable for these cases. (for instance setting the color of the button block)

When talking privately with @nosolosw I asked if we could use CSS variables instead of "skipSerialization" flag and he mentioned some blockers. If what you are proposing resolves them, then I'm all for the proposed approach. Otherwise, we will be forced to find a way to pass all the generated styles and class names to the element that isn't a wrapper. That would mean also that developers would have to explicitly use some new API method that is responsible for that. If CSS variables is an option then we should make sure it is used as the API you outlined is far simpler than the amount of work to understand and properly apply "skipSerialization".

@scruffian
Copy link
Contributor Author

I agree this is much simpler than skipSerialization. It seems to give a lot of power while remaining very simple.

@ockham
Copy link
Contributor

ockham commented Mar 29, 2021

  • if we find a style (new top level property that is different than "supports" because I think these two thing are separate) config in block.json like that:
"style": {
  "color": {
     "text": "variable" // values here can be: "variable", "default", or [ "variable", "default"]
  }
}

generate the style according to the config.

Apologies if this is obvious (I'm still trying to wrap my head around a number of these concepts), but what happens if the value is "default" or [ "variable", "default"]?

@youknowriad
Copy link
Contributor

Apologies if this is obvious (I'm still trying to wrap my head around a number of these concepts), but what happens if the value is "default" or [ "variable", "default"]?

Just the regular global styles behavior, so in this particular case it results in .my-block { color: 'red' } if it's in theme.json and just an inline style color: red if it's a block attribute value.

@ockham
Copy link
Contributor

ockham commented Apr 1, 2021

I've been staring at this for a while, and I'm afraid I still don't really grasp the proposal 😅

One thing I've noticed is that this allows for a rather large number of different combinations of theme.json and block.json settings, which can generate quite different outputs in a site-wide generated CSS file (which is created based on settings in both files?), and inline style (block style attributes/markup?).

Would it be possible to list all different combinations, and spell out what the "global" generated CSS, and block attributes/markup would look like? I'm afraid I can't really weigh in on this otherwise.

One off-the-cuff question would be: If this affects block attributes/markup, won't it lead to deprecations upon theme switch?

@youknowriad
Copy link
Contributor

@ockham would this comment help with the understanding of the proposal here #26752 (comment)

@youknowriad
Copy link
Contributor

youknowriad commented Apr 6, 2021

I've spent some time thinking about this PR and the proposals above more and I came up to the conclusion that if we do it, it will suffer from the same issues that forced us to drop the CSS variables behavior of global styles in the first place. Let me clarify:

Imagine there's a block (say table) that relies on the background color and apply it to its cells like so:

table td {
   background-color: var(--wp-style-color-background);
}

And in theme.json we define a background color in the root

color: { background: 'red' }

What happens here is that we'll have:

  • Background color red applied to the canvas (root)
  • CSS variables defined at the root level
  • Background color applied to all table cells ---> this is not expected IMO (imagine you applied the background color to an intermediary container block)

In other words, this proposal only doesn't work for properties that doesn't cascade and only works for the ones that cascade (text color) and even for these, why not just rely on the regular cascade.

So I'm leaning towards avoiding this proposal entirely at least for v1 of Global styles.

@scruffian
Copy link
Contributor Author

@youknowriad I'm not exactly sure why you think this is a bad idea, but I've removed the change to the calendar block in case that was your concern. Please could you give more details about why you don't like this approach?

From a themes perspective it will be very useful to have access to colors like the background that the user has set, as we might want to use it in places that won't cascade naturally.

@youknowriad
Copy link
Contributor

the background that the user has set, as we might want to use it in places that won't cascade naturally.

I tried explaining here #29714 (comment) in general trying to benefit from a cascade like behavior for things that don't cascade can cause unexpected results.

Would you mind giving an example?

@scruffian
Copy link
Contributor Author

Would you mind giving an example?

Sure. So lets say I want to style table blocks in my theme, and I want the header of the table to contrast with the body like this:

Screenshot 2021-04-30 at 15 33 50

If I use CSS to achieve this, then if the user changes their background color to black using Global Styles, the header of the table won't be high contrast like this anymore.

Screenshot 2021-04-30 at 15 36 36

However if we had these values as CSS variables then I could use those variables in my CSS. Then when the user changed their colors the table would look like this:

Screenshot 2021-04-30 at 15 39 41

Does that help?

@youknowriad
Copy link
Contributor

@scruffian what happens if the table is inside a group block and that the user changes the background and text color for that particular group?

@scruffian
Copy link
Contributor Author

The table would still inherit the values from root, so it might look like this:
Screenshot 2021-04-30 at 16 01 39

@youknowriad
Copy link
Contributor

@scruffian I don't understand why it inherits just the top level background/text colors? Imagine it's the sidebar where we invert the colors or there's a frame around the content where we invert the colors?

@scruffian
Copy link
Contributor Author

If it were to inherit the rules from the group block then it would look like this:
Screenshot 2021-04-30 at 16 23 03

@youknowriad
Copy link
Contributor

Ok understood, so we're saying this:

  • Each container should define variables for their properties.
  • Blocks can use these variables to style things in their markup.

unlike my example here #29714 (comment) you're not using the "background color" as a background but more as a "text color". It does seem very weird to me in the first place because why would something change for me as a user when setting a "background color" to a specific area. That said, maybe we can be liberal here and accept that themes can do this (not blocks).

The issue becomes that we'll be generating a lot of variables assignments, we can try it though and see. cc @nosolosw @mtias @mcsf

Also, how do we know which blocks generate these variables and where will we do it?

@scruffian
Copy link
Contributor Author

I think that setting variables for root will be useful. I'm less sure that we need to do the same for every container. It's probably sufficient most of the time to simply have the root variables.

@scruffian
Copy link
Contributor Author

Closing in favour of #39432

@scruffian scruffian closed this Mar 14, 2022
@scruffian scruffian deleted the add/root-css-vars branch March 14, 2022 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Calendar Affects the Calendar Block Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants