The experimental-theme.json specification structures the way themes provide styling information for blocks, among other things. However, as it currently stands, the _value_ of the style declarations are evaluated as text that is passed down to the CSS output unmodified.
Take this example:
"core/heading/h1": {
"styles": {
"color": {
"background": "red",
"text": "var(--wp--preset--color--primary)",
"link": "blue",
},
"typography": {
"fontSize": "calc(1px * var(--wp--preset--font-size--huge))"
}
}
}
When processed (and the core, theme, and user data is merged) it'll be converted to a CSS stylesheet like this:
h1 {
background: red;
color: var(--wp--preset--color--primary);
--wp--link--color: blue;
font-size: calc(1px * var(--wp--preset--font-size--huge);
}
Note how the values of the style declarations are exactly the same. This works fine for the web, as long as it is a valid CSS declaration that browsers understand. However, this is problematic for supporting Global Styles on mobile (see). Issues that we have are:
calc are not supported.var(--wp--preset--color--primary) but also attaching a new value for --wp--link--color per node).For context, I also wanted to share some other things that are relevant to styles on mobile:
*.native.scss files + some attributes of the block (background color). Ex: create a post in a site you can access from mobile, add a button and change the background color to a custom color. Save and check that the mobile app shows the same color.There are some areas I'd welcome some feedback:
Colors seem to be the first target the mobile team is considering for block level styles. What about the others style properties that we have, would we be interested in supporting them in the future or aren't they relevant for the mobile app? I'm thinking on things like spacing/padding that are highly tied to the available canvas/viewport. For reference, this is the full list of style attributes we currently aim to support: colors (text, background, links, gradients), typography (font-size, font-family, font-weight, line-height), spacing (margin, padding). cc @pinarol
We need to restrict the style declarations in theme.json to a subset of CSS, so we can reference every style prop to a raw value mobile can use. What would be the more complex declaration we want to support?
What would be the more complex use case we want to support in theme.json? Would it be enough for themes if we provide a mechanism that can substitute this declaration: calc(1px * var(--wp--preset--font-size--huge))? I mean, unit conversion + reference some variable stored somewhere. cc @kjellr
Can we use css-wide keywords such as initial, inherit, unset? cc @pinarol
What would be the more complex use case we want to support in theme.json? Would it be enough for themes if we provide a mechanism that can substitute this declaration: calc(1px * var(--wp--preset--font-size--huge))? I mean, unit conversion + reference some variable stored somewhere. cc @kjellr
Yeah, a calc() that references another variable is probably the most common complex use case. You'll also need to make sure that complex gradients will work correctly too (We've already run into numerous issues with those). In general, I'd expect most of the standard CSS functions to work in this context.
I can imagine the image filters and transform functions would be very beneficial to have access to when it comes to image-based blocks. But I know those get pretty complicated.
One thing for sure: If we're limiting these to a subset of CSS, we should be sure to implement errors/warnings for theme authors when an unsupported value is entered.
Colors seem to be the first target the mobile team is considering for block level styles. What about the others style properties that we have, would we be interested in supporting them in the future or aren't they relevant for the mobile app? I'm thinking on things like spacing/padding that are highly tied to the available canvas/viewport. For reference, this is the full list of style attributes we currently aim to support: colors (text, background, links, gradients), typography (font-size, font-family, font-weight, line-height), spacing (margin, padding). cc @pinarol
Ideally we want to unlock all the block settings for mobile users. Having said that we sometimes hit the wall to make everything WYSIWYG, but we are trying our best to make it so.
Colors
Colors is the first thing we'll be adapting. We already have colors in some of our blocks like Button, Cover. We are using themes endpoint to resolve colors from the palette. And we want to bring colors into Group, Paragraph/Heading very soon.
Background ✔️
Text ✔️
Gradient ✔️
Link ✔️
Spacing
Margin✔️
Padding✔️
I don't have a good understanding about all the use cases for this one. Currently there's only 1 example which is Cover: Add Padding Styles. And this one looks as something we'd definitely be interested in brining to mobile.
I have 2 concerns about this one though.
What's the unit of the space, px? em? Is the unit configurable by users or theme authors? I don't think we can render em on mobile 🤔
calc() usage and possibility of relative values.
calc(100% - 30px); //just to note we can use percentages but we can't combine them with px values so any such expression needs to be programmatically calculated on JS side.
calc(2em * 5);
❓ Can I ask what are some common needs behind using calc()? Maybe it is something we wouldn't be interested in supporting anyway. Or if the use case is simple then we can represent the same thing with a different expression?
Typography
This is the most tricky one so let me ask some questions first.
❓Is there a list of font families that are planned to be supported?
❓Is it possible for theme authors (or users?) to add new fonts?
cc @iamthomasbishop
Can we use css-wide keywords such as initial, inherit, unset? cc @pinarol
Unfortunately we don't have support for them on mobile.
@pinarol font-family is on the roadmap, but we haven't gotten into it yet https://github.com/WordPress/gutenberg/issues/23204 The idea would be that theme authors can provide their own list, I'm not sure at this point if core should provide a set of defaults or not.
The idea would be that theme authors can provide their own list
Supporting a dynamic set of fonts that are determined during runtime is super tricky on mobile, I think we'd never aim towards that target. There are some system fonts available on iOS/Android, and it is possible to bundle additional custom fonts inside the app but it is a static thing, can't change with the theme. Plus, some custom fonts don't play well with accessibility features (like bigger font size settings) and can generate unexpected bugs. Not mentioning the possible licensing issues that can result from using custom fonts.
It may be _technically_ possible to choose a safe set of fonts which are by default supported by iOS/Android/Web and provide that set instead. But I doubt it would be that useful if they don't match the theme. 😬
A more realistic short term goal for mobile may be just allowing to change size related things, like font size, line height etc.
Either ways, I'd prefer prioritizing other aspects of GS on mobile side, like colors (text, background, links, gradients) and spacing (margin, padding). cc @iamthomasbishop if he wants to correct me or add something.
Can I ask what are some common needs behind using calc()?
@pinarol I'm sure there are many more examples that the web folks can speak to, but one way I've used it is to extend something beyond its container's bounds. For example if I want an image that extends 40px beyond its container's bounds, I would say (in CSS) width: calc(100% + 80px); and then offset to the left by -40px w/ margin or translate. I think it's helpful especially when the element's container is dynamic. Hopefully we can find or use a reliable method of translating from calc to whatever is usable on our end — I think that'd be really helpful.
I don't think we can render em on mobile
I think that's right. As far as I can tell, RN only supports "logical pixels", which is essentially the same as "points" on iOS and "dp" (device-independent pixels) on Android. I think we'd need to either find or build a translation mechanism to support em, rem, and so on, but _if_ we can find a way to translate to and from various unit types — well, that would be huge — for spacings and type scale especially, which are foundational.
I think we're in good shape when it comes to solid colors, bc it seems like we have pretty wide color-type support — hex, rgb, rgba, hsl, etc. Gradients I'm not as sure about. I know we've had some challenges implementing gradients on mobile but I'm not sure if they're because of support constraints or knowledge gaps.
I agree with just about everything you said above on fonts. The purely dynamic approach is essentially a no-go as far as I can tell. The "bundling additional fonts" approach is compelling, but even if we were to bundle a set of fonts that covers a large portion of the most popular ones, there are a bunch of things that could go wrong (most notably accessibility, dynamic font-size, weights, etc).
I agree that we probably want to de-prioritize fonts in the immediate term and focus on colors, gradients, and spacing. It would be wise to have someone on the team do a technical exploration spike soon in order to learn more about our options wrt fonts, but the other things should give us some quick wins in the meantime.
From the look of it, it doesn't look like this theme.json spec would be a major blocker for mobile. Or rather I don't believe changing the spec would help the mobile case much.
Concerning CSS variables their names look quit explicit and match the experimental-theme.json schema so it should not be difficult to find the value of a variable in the config.
However we would not be able to support blocks overwriting those variables. Not sure if this practice is supported/encouraged at this point for the web?
Concerning CSS functions, I don't see any way to support all the features they provide for native, even if we change the spec.
If we're simply multiplying a CSS variable by a constant (like in calc(1px * var(--wp--preset--font-size--huge);) or something simple like that we can probably "pre-compute" the result and use it in our React Native code.
However as soon as we use a percentage or other other types of construct, it becomes dynamic and the formula needs to be given as it is to the CSS engine. So it simply cannot work on native.
In that case, we should probably discourage theme authors from using this kind of formulas.
Though if we look at the implicit block attributes that we plan to have on the web:
All can easily have a static value (not use formulas) without degrading the UX
Most helpful comment
Supporting a dynamic set of fonts that are determined during runtime is super tricky on mobile, I think we'd never aim towards that target. There are some system fonts available on iOS/Android, and it is possible to bundle additional custom fonts inside the app but it is a static thing, can't change with the theme. Plus, some custom fonts don't play well with accessibility features (like bigger font size settings) and can generate unexpected bugs. Not mentioning the possible licensing issues that can result from using custom fonts.
It may be _technically_ possible to choose a safe set of fonts which are by default supported by iOS/Android/Web and provide that set instead. But I doubt it would be that useful if they don't match the theme. 😬
A more realistic short term goal for mobile may be just allowing to change size related things, like font size, line height etc.
Either ways, I'd prefer prioritizing other aspects of GS on mobile side, like colors (text, background, links, gradients) and spacing (margin, padding). cc @iamthomasbishop if he wants to correct me or add something.