Skip to content

Classic Themes: Enable Fonts and thus global styles#73971

Merged
youknowriad merged 7 commits intotrunkfrom
add/enable-fonts-classic-themes
Dec 16, 2025
Merged

Classic Themes: Enable Fonts and thus global styles#73971
youknowriad merged 7 commits intotrunkfrom
add/enable-fonts-classic-themes

Conversation

@youknowriad
Copy link
Contributor

What?

Closes #64409

This PR enables the Fonts page for classic themes. That said, the fonts page relies on Global styles working to be able to work properly:

  • We need to be able to save global styles
  • We need global styles to generate CSS properly to be able to use the fonts in posts, pages...

This basically means that by enabling fonts, we're literally enabling all of global styles for classic themes (the UI for global styles remain hidden for the context of this PR).

I tested this briefly using 2019 theme, I installed some fonts, used them in some posts... Things are working decently to be honest. Now, I'm well aware that enabling global styles CSS generation can potentially have some side effects on these themes.

So I'd like some help from folks to test different kind of classic themes to see if this PR impacts frontend rendering in any way. Also check that you can install fonts and use them.

@youknowriad youknowriad self-assigned this Dec 12, 2025
@youknowriad youknowriad added [Type] Enhancement A suggestion for improvement. Needs Testing Needs further testing to be confirmed. [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. [Feature] Font Library labels Dec 12, 2025
@github-actions
Copy link

github-actions bot commented Dec 12, 2025

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: youknowriad <[email protected]>
Co-authored-by: SirLouen <[email protected]>
Co-authored-by: t-hamano <[email protected]>
Co-authored-by: jasmussen <[email protected]>
Co-authored-by: tellthemachines <[email protected]>
Co-authored-by: matiasbenedetto <[email protected]>
Co-authored-by: mrleemon <[email protected]>
Co-authored-by: Drivingralle <[email protected]>
Co-authored-by: annezazu <[email protected]>

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

Copy link
Member

@SirLouen SirLouen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Report

Description

✅ This report validates that the indicated patch works as expected.

Environment

  • WordPress: 7.0-alpha-61215-src
  • PHP: 8.2.29
  • Server: nginx/1.29.3
  • Database: mysqli (Server: 8.4.7 / Client: mysqlnd 8.2.29)
  • Browser: Chrome 142.0.0.0
  • OS: Windows 10/11
  • Theme: Twenty Seventeen 4.0
  • MU Plugins: None activated
  • Plugins:
    • Gutenberg 22.3.0-rc.1
    • Test Reports 1.2.1

Testing Instructions

  1. Go to Appearance > Fonts
  2. Upload a new font
  3. Create a new post
  4. Add a paragraph, and in Block > Typography select Font
  5. Select the uploaded font

Actual Results

  1. ✅ Issue resolved with patch.

Additional Notes

  • @youknowriad can you do a little overview of what is being introduced apart from adding fonts for classic themes? Like a more comprehensive list of items to be tested. Judging by the code, I feel that more things can be achieved apart from just what I tested.

Supplemental Artifacts

image image

@SirLouen
Copy link
Member

SirLouen commented Dec 12, 2025

More Testing

Fonts not selectable in

2010 theme

image

2011 theme

image

And 2020 also tested.

@youknowriad
Copy link
Contributor Author

can you do a little overview of what is being introduced apart from adding fonts for classic themes? Like a more comprehensive list of items to be tested. Judging by the code, I feel that more things can be achieved apart from just what I tested.

It's explained in the description. The only visible addition here is "fonts for classic themes" but to be able to do that, we had to lift some conditions to generate CSS out of global styles for classic themes. And my fear is whether the removal of these conditions has any unwanted effect on the frontend of sites using classic themes (with or without custom fonts). I have no way to know 100% outside testing classic themes and ensure the changes don't impact them.

@youknowriad
Copy link
Contributor Author

Are they binded to the theme when you upload them?

Yes, like all global styles changes, you have to go to the "fonts" page and "activate them" again. Making them persist with theme switches is out of scope.

@SirLouen
Copy link
Member

Are they binded to the theme when you upload them?

Yes, like all global styles changes, you have to go to the "fonts" page and "activate them" again. Making them persist with theme switches is out of scope.

Ok, all good then 👍

@SirLouen
Copy link
Member

Tested now in

  • 2010✅
  • 2011✅
  • 2012✅
  • 2013✅
  • 2015✅
  • 2016✅
  • 2017✅
  • 2019✅
  • 2020✅
  • 2021✅
    Looking good in the front end for all variants.

@@ -0,0 +1,144 @@
<?php
/**
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole file is only here to override the Core behavior, but in reality there's no really change here from core behavior outside calling the overridden Gutenberg theme.json functions...

* @param WP_Theme $theme Theme object used to create response.
* @return WP_REST_Response Modified response object.
*/
function gutenberg_rest_theme_global_styles_link_rel_7_0( $response, $theme ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just makes the global style id available in theme endpoint. I believe @t-hamano opened a trac ticket about this a few days ago as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. https://core.trac.wordpress.org/ticket/64402

However, this is a bug report for block themes that do not have a theme.json, and this bug will eventually be fixed once the font library is exposed to all themes.

@jasmussen
Copy link
Contributor

Nice win!

@SirLouen
Copy link
Member

SirLouen commented Dec 12, 2025

@youknowriad after experimenting a bit with lib/compat/wordpress-7.0/global-styles.php I've created a test in #73974 that could be worth checking. I've added this as a PR to this branch.

Apart from this, for the rest all looking good to me. Maybe some collisions could appear with blocks or custom themes, but I could not find anything else.

@youknowriad
Copy link
Contributor Author

I really appreciate the help with both the automated tests and the testing. Thanks a lot :). I'm going to leave this PR open for a bit more feedback and testing and maybe we can move forward early next week.

Comment on lines +49 to +57
if ( str_contains( $font_family_name, ',' ) ) {
$font_family_name = explode( ',', $font_family_name )[0];
}
$font_family_name = trim( $font_family_name, "\"'" );

// Skip if no font family is defined.
if ( empty( $font_family_name ) ) {
continue;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get this section.
If the $font_family_name happens to be a string with comma separated font names, it will convert it into an array

But after conversion to array, it executes a trim? Maybe you were looking for an array_map('trim', ...)? I'm have not dug too much into the format of the fontFamily, but finally it checks again if it's empty. Is there any chance of having a fontFamily like this , ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not able to reply the full question here but I suggest that we keep the code as is. This code is copied as is exactly from Core, it's only in Gutenberg because it's not filtrable so we need to override/copy the full function.

Copy link
Member

@SirLouen SirLouen Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@youknowriad ok, I'm still trying to figure out how Gutenberg integrates with Core not as straightforward, as I thought.

I'm assuming you took the parse_settings from src/wp-includes/fonts/class-wp-font-face-resolver.php for this section and removed some elements for convenience, and then when 7.0 is released, this file will be ignored and changes will be manually merged into Core?

In this case, I'm going to send a PR in core to fix this part 👍

PS: I have tested and its not problematic as is returning just the first font family not the whole list so this section is technically correct.

@SirLouen
Copy link
Member

SirLouen commented Dec 13, 2025

Additional Testing

I've been playing around with a custom classic theme with a default global font:

Here the playground testing environment:
https://playground.wordpress.net/?blueprint-url=https%3A%2F%2Fgist.githubusercontent.com%2FSirLouen%2F07cd5efa2e9ae0df553c933593f6feff%2Fraw%2F8e184826660caeca70e72b9f3f4973d9b6b310a9%2Fblueprint.json&gutenberg-branch=add%2Fenable-fonts-classic-themes

This is the raw blueprint: https://gist.githubusercontent.com/SirLouen/07cd5efa2e9ae0df553c933593f6feff/raw/8e184826660caeca70e72b9f3f4973d9b6b310a9/blueprint.json

I've added a font to the custom theme.

And then added a custom font to a paragraph of text

But the font is not applying in the_excerpt which is probably expected as it's being removed from all block styles and full fallback to default styles.

✅ But in the the_content its working fine and taking precedence.

Template Code

<!-- wp:paragraph -->
<p>Experimenting without font</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph {"fontFamily":"limelight"} -->
<p class="has-limelight-font-family">Experimenting with font</p>
<!-- /wp:paragraph -->

Backend:

image

Frontend with the_excerpt

image

Frontend with the_content

image

@tellthemachines
Copy link
Contributor

tellthemachines commented Dec 15, 2025

I can see a few styles added to the global styles inline CSS stylesheet, but mostly they either don't apply to the markup structure of classic themes (wp-site-blocks classname isn't output for classic themes) or they are sufficiently low specificity that they're unlikely to override theme styles. Or they are basic styles that most themes use already, like auto margins on center-aligned elements.

This is not to say there's no possibility of breaking things for any theme. A theme with very low specificity styles might see some of them overridden by these global styles. It's not practical to test every single theme out there though, so I guess we have to make a call on whether some potential breakage is acceptable or not.

These are the styles that have been added
:where(body) {
    margin: 0;
}

.wp-site-blocks > .alignleft {
    float: left;
    margin-right: 2em;
}

.wp-site-blocks > .alignright {
    float: right;
    margin-left: 2em;
}

.wp-site-blocks > .aligncenter {
    justify-content: center;
    margin-left: auto;
    margin-right: auto;
}
.is-layout-flow > .alignleft {
    float: left;
    margin-inline-start: 0;margin-inline-end: 2em;}

.is-layout-flow > .alignright {
    float: right;
    margin-inline-start: 2em;margin-inline-end: 0;}

.is-layout-flow > .aligncenter {
    margin-left: auto !important;
    margin-right: auto !important;
}

.is-layout-constrained > .alignleft {
    float: left;
    margin-inline-start: 0;margin-inline-end: 2em;}

.is-layout-constrained > .alignright {
    float: right;
    margin-inline-start: 2em;margin-inline-end: 0;}

.is-layout-constrained > .aligncenter {
    margin-left: auto !important;
    margin-right: auto !important;
}

.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) {
    margin-left: auto !important;
    margin-right: auto !important;
}
body {
    padding-top: 0px;
    padding-right: 0px;
    padding-bottom: 0px;
    padding-left: 0px;
}

a:where(:not(.wp-element-button)) {
    text-decoration: underline;
}

:root :where(.wp-element-button, .wp-block-button__link) {
    background-color: #32373c;
    border-width: 0;
    color: #fff;
    font-family: inherit;
    font-size: inherit;
    font-style: inherit;
    font-weight: inherit;
    letter-spacing: inherit;
    line-height: inherit;
    padding-top: calc(0.667em + 2px);
    padding-right: calc(1.333em + 2px);
    padding-bottom: calc(0.667em + 2px);
    padding-left: calc(1.333em + 2px);
    text-decoration: none;
    text-transform: inherit;
}

@youknowriad
Copy link
Contributor Author

@tellthemachines Thanks that's very useful, I wonder if there's a way to disable "layout" styles (all the alignments stuff) automatically when theme.json is not present or something.

I also wonder why we're generating things like

a:where(:not(.wp-element-button)) {
    text-decoration: underline;
}

even in global styles, I mean links are supposed to be underlined by default (from the browser), so why do we even need this style.

The other element style is also weird.

@youknowriad
Copy link
Contributor Author

Overall, I do agree that the potential for regressions is very small with these styles, so I'm kind of inclined to say that it's probably ok to ship and monitor any issues over the next few days/weeks.

@youknowriad youknowriad force-pushed the add/enable-fonts-classic-themes branch from 10c6c83 to 71b637d Compare December 15, 2025 08:56
@youknowriad youknowriad force-pushed the add/enable-fonts-classic-themes branch from 71b637d to 0f78075 Compare December 15, 2025 10:21
@youknowriad youknowriad dismissed SirLouen’s stale review December 15, 2025 11:58

Should be addressed.

@SirLouen
Copy link
Member

SirLouen commented Dec 15, 2025

The only section that is unclear to me is this in lib/compat/wordpress-7.0/global-styles.php

/**
 * Prints font-face styles for fonts on the frontend.
 *
 * @since Gutenberg 20.0.0
 */
function gutenberg_print_font_faces() {
	$font_face_styles = gutenberg_get_font_face_styles();
	if ( ! empty( $font_face_styles ) ) {
		printf( "<style id='wp-fonts-local'>\n%s\n</style>\n", $font_face_styles );
	}
}
add_action( 'wp_head', 'gutenberg_print_font_faces', 50 );

Theoretically, this is the only part that has been added to override core behavior in
src/wp-includes/fonts/class-wp-font-face-resolver.php

As I've said, I'm not sure how these changes are being integrated into core, but if this function is going to be integrated as-is, it will incur the problem I commented on in #73794 which should be addressed (each call generates a whole new font family style). So basically it first should check in $font_Face_styles if wp-fonts-local already exists or not, before printing (and I would add the unit test somewhere)

PS: Also, shouldn't the @since Gutenberg 20.0.0 be updated?

@youknowriad
Copy link
Contributor Author

@SirLouen you can check how this is going to be integrated into Core in this PR

@tellthemachines
Copy link
Contributor

I wonder if there's a way to disable "layout" styles (all the alignments stuff) automatically when theme.json is not present or something.

We don't want to disable all layout styles because the flex and grid styles are needed in classic themes for Row/Stack/Grid blocks (or any other blocks that have flex or grid layouts). Currently those are the only ones we output for classic themes, but this PR changes that so we maybe should introduce some mechanism to not output flow/constrained layout styles.

@youknowriad
Copy link
Contributor Author

We don't want to disable all layout styles because the flex and grid styles are needed in classic themes for Row/Stack/Grid blocks (or any other blocks that have flex or grid layouts). Currently those are the only ones we output for classic themes, but this PR changes that so we maybe should introduce some mechanism to not output flow/constrained layout styles.

Yes, I figured after looking the output CSS, and I think I've addressed that already in the PR

@youknowriad youknowriad merged commit 0a447bc into trunk Dec 16, 2025
48 of 50 checks passed
@youknowriad youknowriad deleted the add/enable-fonts-classic-themes branch December 16, 2025 09:22
@github-actions github-actions bot added this to the Gutenberg 22.4 milestone Dec 16, 2025
@youknowriad
Copy link
Contributor Author

One thing we can try now that this PR landed is to enable the "global styles UI" in classic themes too. I'm not going to work on it now cause I have a lot on my plate already, so anyone feel free to try it. But I can also circle back to it later.

@sirreal
Copy link
Member

sirreal commented Dec 18, 2025

This seems to have cuased #74087.

sirreal added a commit that referenced this pull request Dec 18, 2025
@westonruter
Copy link
Member

Citing WordPress/wordpress-develop#10623 (comment):

This commit breaks a couple things:

  1. Live Preview in the Customizer
  2. The CSS cascade.

See Trac comment and repro steps.

youknowriad added a commit to youknowriad/gutenberg that referenced this pull request Jan 13, 2026
## What?

This PR restores the `$is_block_theme` check that was inadvertently removed in WordPress#73971 when enabling Global Styles for classic themes.

## Why?

For classic themes, the Customizer's Additional CSS should continue to be printed separately via `wp_custom_css_cb()` at priority 101 in `wp_head`, preserving its position at the end of the `<head>` for highest CSS specificity.

Without this check, classic themes experience two issues:
1. Live preview in the Customizer doesn't work for Additional CSS changes
2. Additional CSS loses its cascade advantage due to being merged into the global styles stylesheet

For block themes, the Customizer CSS is merged into the global styles stylesheet before the global styles custom CSS, maintaining the intended cascade order.

## Testing Instructions

### Classic Theme (Twenty Twenty-One):
1. Activate Twenty Twenty-One theme
2. Go to Customizer > Additional CSS
3. Add: `body { background-color: lime; }`
4. Verify live preview works instantly
5. Save and view frontend - verify lime background is applied
6. Check HTML source - `<style id="wp-custom-css">` should appear near end of `<head>`

### Block Theme (Twenty Twenty-Four):
1. Activate Twenty Twenty-Four theme
2. Go to Customizer > Additional CSS
3. Add: `body { background-color: lime; }`
4. Verify live preview works instantly
5. Save and view frontend - verify lime background is applied
6. Check HTML source - CSS should be inside `<style id="global-styles-inline-css">`
youknowriad added a commit to youknowriad/gutenberg that referenced this pull request Jan 13, 2026
## What?

This PR restores the `$is_block_theme` check that was inadvertently removed in WordPress#73971 when enabling Global Styles for classic themes.

## Why?

For classic themes, the Customizer's Additional CSS should continue to be printed separately via `wp_custom_css_cb()` at priority 101 in `wp_head`, preserving its position at the end of the `<head>` for highest CSS specificity.

Without this check, classic themes experience two issues:
1. Live preview in the Customizer doesn't work for Additional CSS changes
2. Additional CSS loses its cascade advantage due to being merged into the global styles stylesheet

For block themes, the Customizer CSS is merged into the global styles stylesheet before the global styles custom CSS, maintaining the intended cascade order.

## Testing Instructions

### Classic Theme (Twenty Twenty-One):
1. Activate Twenty Twenty-One theme
2. Go to Customizer > Additional CSS
3. Add: `body { background-color: lime; }`
4. Verify live preview works instantly
5. Save and view frontend - verify lime background is applied
6. Check HTML source - `<style id="wp-custom-css">` should appear near end of `<head>`

### Block Theme (Twenty Twenty-Four):
1. Activate Twenty Twenty-Four theme
2. Go to Customizer > Additional CSS
3. Add: `body { background-color: lime; }`
4. Verify live preview works instantly
5. Save and view frontend - verify lime background is applied
6. Check HTML source - CSS should be inside `<style id="global-styles-inline-css">`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Font Library [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. Needs Testing Needs further testing to be confirmed. [Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consider exposing the Font Library for classic themes

7 participants