WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.5k stars 4.2k forks source link

Make elements font options referenceable #64443

Open matiasbenedetto opened 2 months ago

matiasbenedetto commented 2 months ago

What problem does this address?

Should WordPress make element font options referenceable?

Currently, there's no way to reference, for example, the font family selection for the website's headings because the values of this option are printed in selector-value CSS.

image

Example of the current theme.json config:

{
    "styles": {
        "elements": {
            "heading": {
                "typography": {
                    "fontStyle": "normal",
                    "fontWeight": "400",
                    "fontFamily": "var:preset|font-family|abel"
                }
            }
        }
    }
}

This config is printed like this in CSS:

h1, h2, h3, h4, h5, h6{
     font-family: var(--wp--preset--font-family--abel);
}

This works to set the font family of headings but cannot be referenced in any other part of the styles. Let's say you have a theme and you want to reference the font selection of the heading. That's currently impossible. The only current workaround is using fonts with a 'positional' slug (for example, 'heading-font') and style variations. This way, when the variation is applied, the 'heading font' will change. But style variations are a pre-defined part of a theme, and they cannot be created using the editor (without plugins such as Create Block Theme). We could solve this limitation by using the elements font selection as 'positional' variables for fonts. This will allow users to change an entire theme by installing a font using the font library and selecting it in the elements font panel.

What is your proposed solution?

WordPress should make element font options referenceable. Should it print the CSS variables with the element's font family styles? I imagine that WordPress could print CSS variables for the font options in theme.json. This way, the element's font options can be referenced and reused across the site and theme. Font switching will be possible without pre-defined theme style variations that cannot be created in the editor.

Example of how the printed CSS variable could look:

--wp--element--headings--font-family: Abel, sans-serif;
--wp--element--headings--font-style: Italic;

The resulting CSS for headings could look like this:

h1, h2, h3, h4, h5, h6{
     font-family: var(--wp--element--headings--font-family);
     font-style: var(--wp--element--headings--font-style);
}

Custom CSS of the theme could reuse these variables:

.my-custom-block{
    font-family: var(--wp--element--headings--font-family);
}

Other parts of theme JSON could reference this setting, too:

{
    "styles": {
        "blocks": {
            "core/quote": {
                "typography": {
                    "fontFamily": "var(--wp--element--headings--font-family)",
                    "fontStyle": "var:element|headings|font-style"
                }
            }
        }
    }
}
jffng commented 2 months ago

I am not sure it makes sense to automatically generate variables for all the font styles. It reminds me of https://github.com/WordPress/gutenberg/issues/38998, specifically the part about design tokens.

Could this be solved by referencing the style?

For example:

{
    "styles": {
        "blocks": {
            "core/quote": {
                "typography": {
                    "ref": "styles.element.typography.heading"
                }
            }
        }
    },
}

This would apply all the typography settings of the heading, to the block.

The same idea could be applied for referencing the values in custom CSS, by generating a custom variable that references an existing styles value:

{
    "custom": {
        "typography": {
            "headings": {
                "fontFamily": {
                    "ref": "styles.element.typography.heading.fontFamily"
                 }
            }
        }
    }
}

Which would result in:

--wp--custom--typography--headings--font-family: Abel, sans-serif;
matiasbenedetto commented 2 months ago

Thanks @jffng for your input! It looks like the alternative you propose makes sense. I just found that the ref is not working for that use case. It seems to be a bug, I'm investigating it.

This theme.json

{
    "$schema": "https://schemas.wp.org/trunk/theme.json",
    "styles": {
        "elements": {
            "heading":{
                "typography": {
                    "fontFamily": "var(--wp--preset--font-family--system-ui)"
                }
            }
        }
    },
    "settings": {
        "typography": {
            "fontFamilies": [
                {
                    "fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif",
                    "name": "System Font",
                    "slug": "system-ui"
                }
            ]
        },
        "useRootPaddingAwareAlignments": true,
        "custom": {
            "typography": {
                "headings": {
                    "fontFamily": {
                        "ref": "styles.elements.heading.typography.fontFamily"
                    }
                }
            }
        }
    },
    "version": 2
}

Is producing this CSS:

--wp--custom--typography--headings--font-family--ref: styles.elements.heading.typography.fontFamily;
matiasbenedetto commented 2 months ago

I just found that the ref is not working for that use case. It seems to be a bug, I'm investigating it.

Update: there's a known limitation. ref is not working inside settings, so unfortunately this is not currently possible.

{
  "settings":{
        "custom": {
            "typography": {
                "headings": {
                    "fontFamily": {
                        "ref": "styles.elements.heading.typography.fontFamily"
                    }
                }
            }
       }
  }
}

There's an issue requesting to fix/implement that: #57286 Allow use of ref in theme.json settings, as is possible with styles

jasmussen commented 2 months ago

There's some nuance in this outline that I'm likely missing, so let me know where I'm wrong. I'd also appreciate additional insights from @WordPress/gutenberg-design.

It sounds like you want to be able to reference the values of one element in another. The use case I keep coming back to here is one of using color. My site has background and text colors, and I want to use those two for designing my buttons:

  1. Outline buttons should have text-color border.
  2. Fill/solid buttons should have text-color background, and site-background color text.

1 can already be accomplished, simply don't set a color (the equivalent of border: 1px solid;) and currentColor will be applied. 2 I need to reference the stored value.

If the motivation for the elements mentioned here, and specifically typography, is the same as that for the color example, then I'd agree it's something we want. However we want this for every property, not just fonts, and we want a user interface for it. Related: #49279 and #48581.