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

Theme JSON: add localized css variables to inline classes #59469

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from

Conversation

jonathan-dejong
Copy link

@jonathan-dejong jonathan-dejong commented Feb 29, 2024

What?

This adds a localized CSS variable for a given CSS variable under an automatically generated theme.json class name.
I don't expect the first commit of this PR to be final. I expect there to be a need to conditionally set if the variable should be created or not based on what the property is.

Why?

I was looking at ways of making the button styles more flexible, especially with things like psuedo classes (:hover, etc) and getting around the issue that there is no way to style these presently when also setting colors directly in the block control.

I am aware there is some open discussions on adding hover controls etc. to buttons and other elements but as far as I've seen they are not close to resolution.

So I came up with this change in the code which results in outputting a variable ready for use.
With this, I was able to use dynamic color manipulation to allow my buttons psuedo classes to modify the buttons look nicely regardless of what color combination I add from the color palette.
Here's a nice article on color manipulation: https://blog.jim-nielsen.com/2021/css-relative-colors/

Here's a sample of what the output CSS classes would look like:

.has-secondary-400-background-color {
    background-color: var(--wp--preset--color--secondary-400) !important;
    --background-color: var(--wp--preset--color--secondary-400);
}

.has-secondary-200-color {
    color: var(--wp--preset--color--secondary-200) !important;
    --color: var(--wp--preset--color--secondary-200);
}

And here's some sample use case with the :hover psuedo class:

/* important is needed because the colors set by Gutenberg is also set to important. */
.wp-block-button .wp-block-button__link.has-text-color:hover {
	color: hsl(from var(--color) h s l / .15) !important;
}

.wp-block-button .wp-block-button__link.has-background-color:hover {
	background-color: hsl(from var(--background-color) calc(h + 180deg) s l) !important;
}

Using this I can actually achieve a dynamic standardised look for my hover effects in my theme with any colors!

This is also just one example use case based on my own experience, I am sure there are other examples where localized CSS variables would be very useful.

Another example that comes to mind would be adding content, usually icons, with the :before or :after psuedo element.

.wp-block-button .wp-block-button__link.has-text-color:after{
	/* This is our color manipulation, our icon have 20% less saturation than our text. */
	color: hsl(from var(--color) h calc(s - 20%) l);
	/* regular dashicons stuff… */
	content: "\f319";
	font-family: dashicons;
	display: inline-block;
	line-height: 1;
	font-weight: 400;
	font-style: normal;
	width: 20px;
	height: 20px;
	font-size: 20px;
	vertical-align: top;
	text-align:center;
}

And since CSS variable scoping goes "element -> child elements" this would even work if we have an inline SVG with a fill color we want to change based on the text color of our button.
For example:

.wp-block-button .wp-block-button__link.has-text-color svg path{
	/* Let's make sure our path fill is the same as the parent elements color. */
	fill: var(--color);
}

/* A more complex example where we have classes for layers of our icon. */
.wp-block-button .wp-block-button__link.has-background-color svg .icon__background{
	/* background should be the buttons background but slightly darker. */
	fill: color: hsl(from var(--background-color) h s calc(l - 20%) );
}
.wp-block-button .wp-block-button__link.has-text-color svg .icon__symbol{
	/* the symbol on our background should use the text color with less alpha */
	fill: rgb(from var(--color) r g b / .5);
}

I'm using buttons as the example here because they're typical interactive elements that we may want to manipulate based on state, but the logic applies to any element.

How?

This PR adds the property with the css variable syntax by appending the -- prefix and uses the same variable value var() that we are already using to set the property itself.

One thing that needs to be considered more deeply is probably variable scoping and how that could have unwanted effects.. but from my testing and thinking about it I don't think it should be an issue.
This implementation is always scoped to the generated classes and therefore the elements using them and their child elements.

The only way I can see a theoretical problem is if a developer have in their theme set a CSS Variable on a higher level parent element, then use the variable on some child elements in their CSS and we override their variables with these classes because our element is inserted inbetween their expected parent and the child.

My personal opinion is that this is a very edge case scenario unlikely to be an actual real world issue and therefore shouldn't be a dealbreaker for implementing something like this.

Testing Instructions

  1. Open a post or page in the block editor.
  2. Insert a button block.
  3. Manually set a color and background color
  4. Check the applied dynamically created style in the web tools inspector on the frontend (or backend).

OR
simply check the rendered inline theme.json CSS on the frontend.

Testing Instructions for Keyboard

N/A

Screenshots or screencast

Result in browser for custom text and background color classes:

Screenshot 2024-02-29 at 10 58 32

Copy link

github-actions bot commented Feb 29, 2024

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Type-related labels to choose from: [Type] Automated Testing, [Type] Breaking Change, [Type] Bug, [Type] Build Tooling, [Type] Code Quality, [Type] Copy, [Type] Developer Documentation, [Type] Enhancement, [Type] Experimental, [Type] Feature, [Type] New API, [Type] Task, [Type] Technical Prototype, [Type] Performance, [Type] Project Management, [Type] Regression, [Type] Security, [Type] WP Core Ticket, Backport from WordPress Core.
  • Labels found: First-time Contributor, CSS Styling.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

Copy link

github-actions bot commented Feb 29, 2024

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 props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: jonathan-dejong <jonathandejong@git.wordpress.org>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions github-actions bot added the First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository label Feb 29, 2024
Copy link

👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @jonathan-dejong! In case you missed it, we'd love to have you join us in our Slack community.

If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information.

@skorasaurus skorasaurus added the CSS Styling Related to editor and front end styles, CSS-specific issues. label Feb 29, 2024
@youknowriad
Copy link
Contributor

Thanks for your efforts, to be really clear, it's very unclear to me how this fits in the global styles architecture.
I agree there's a huge value in being able to manipulate and use colors using CSS.
That said, I feel like this solution is a hack because CSS there's no way to say "get current background color" or something (in fact for color it's already possible to use currentColor). In fact there's a proposal to add it w3c/csswg-drafts#5292

For the solution here my main concern is that it has a huge potential for conflicts with variables used in themes and it adds a lot of CSS to compensate for a missing CSS feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CSS Styling Related to editor and front end styles, CSS-specific issues. First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants