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

Webfonts: register and enqueue fonts by font-family #39559

Merged
merged 17 commits into from
Apr 4, 2022

Conversation

zaguiini
Copy link
Member

@zaguiini zaguiini commented Mar 17, 2022

What?

Part of #39332.

Why?

It's an attempt to make the webfonts API more flexible and save transferred data. We're now registering font families (individual font faces grouped by font-family) and enqueueing them as needed.

  1. We more closely match the behavior of wp scripts and styles and accommodate functionality that WordPress developers are already familiar with.
  2. We allow API consumers more flexibility in how and when they enqueue webfonts, rather than forcing them to enqueue all fonts indiscriminately.

How?

We're creating a hash of the font-family attribute and grouping registered font faces to their respective font families;

We then introduce enqueueing and do not add registered font-families to the output by default -- they must be explicitly added through enqueueing. All fonts are enqueued when opening the editor so fonts picked when making changes show up correctly.

Webfonts should be enqueued after the after_setup_theme hook runs because that's where registration happens. So we should recommend hooking into init or wp_loaded to enqueue fonts since it's guaranteed to be registered at the time that these hooks are run.

Testing a webfont loaded via theme.json:

Using the Bennett theme as an example, we edit its theme.json file and replace fontFamilies with the following:

"fontFamilies": [
    {
        "fontFamily": "Roboto",
        "name": "Roboto",
        "slug": "roboto",
        "fontFace": [
            {
                "fontFamily": "Roboto",
                "fontWeight": "900",
                "fontStyle": "normal",
                "fontStretch": "normal",
                "src": [ "file:./assets/fonts/Roboto-Regular.ttf" ]
            },
        ]
    }
],

Then, we create a functions.php in the bennett theme directory and add the following:

<?php

add_action( 'init', function() {
	wp_enqueue_webfont( 'Roboto' );
} );

Testing a webfont programmatically through PHP:

Next, to test the PHP registration using the wp_register_webfont function, in functions.php add the following:

add_action( 'after_setup_theme', function() {
	wp_register_webfont(
		array(
			'font-family'  => 'Roboto',
			'font-style'   => 'normal',
			'font-stretch' => 'normal',
			"font-weight" => "900",
			'src'          => get_theme_file_uri( '/assets/fonts/Roboto-Regular.ttf' ),
		)
	);
} );

add_action( 'wp_loaded', function() {
	wp_enqueue_webfont( 'Roboto' );
} );

Refresh the page and Roboto should be there. You can try adding another font of the same family in italic (font-style: italic) and changing the src. It should load both fonts.

When you remove wp_enqueue_webfont, Roboto should not be loaded anymore.

@zaguiini
Copy link
Member Author

zaguiini commented Mar 23, 2022

@hellofromtonya this is ready for review and adapted to your comments.

@aristath please take a look when possible 🙏

Copy link
Contributor

@creativecoder creativecoder left a comment

Choose a reason for hiding this comment

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

The overall approach is looking good and makes sense to me.

I think this is best reviewed in tandem with #39593, as the first real test is if it helps us remove unused font-face declarations to avoid unnecessarily bloating the html.

lib/compat/wordpress-6.0/class-wp-webfonts.php Outdated Show resolved Hide resolved
@zaguiini zaguiini force-pushed the try/register-and-enqueue-webfonts-by-family branch from b92fdda to b86cad6 Compare March 28, 2022 19:34
@zaguiini zaguiini force-pushed the try/register-and-enqueue-webfonts-by-family branch from f7a2b9d to 9263fce Compare March 28, 2022 20:44
@zaguiini zaguiini force-pushed the try/register-and-enqueue-webfonts-by-family branch from 5dbbc48 to 10454fe Compare March 29, 2022 21:33
@zaguiini zaguiini self-assigned this Mar 29, 2022
zaguiini and others added 6 commits April 4, 2022 07:32
The API, although looking really good, is not ready for Core.
So we must move it from wordpress-6.0 to experimental,
and only add it there when it's ready to enter WordPress.

Relocate files to /lib/experimental.

Per the Gutenberg PHP > File structure documentation
https://github.com/WordPress/gutenberg/tree/trunk/lib#file-structure.
Tests for methods that have a `_doing_it_wrong()` require
an `expectedIncorrectUsage` annotation, proper usage of test fixture methods,
and the usage of `__METHOD__` when invoking `_doing_it_wrong()`.

This commit:

- Fixes the test fixtures to use snake_case format and calling of the parent fixtures.
- Refactors `get_font_slug()` tests into data providers (preferred in Core) and separates tests that will trigger `_doing_it_wrong()` to use the annotation.
- Uses `__METHOD__` instead of `__FUNCTION__` in each `_doing_it_wrong()` instance.
The `WP_Webfonts::generate_styles()` should not be aware of how to
reorganize the webfonts from grouped by font-family to grouped by
provider. Why? This is a separate task from generating styles for
the webfonts.

This commit creates a private method called `get_webfonts_by_provider()`
to encapsulate the know-how for this reorganizational work.

It also includes a micro-optimization that eliminates an extra
`foreach` loop and the building of an unnecessary `$webfonts`
array of arrays.
@hellofromtonya hellofromtonya force-pushed the try/register-and-enqueue-webfonts-by-family branch from f5f8339 to 90cc444 Compare April 4, 2022 12:42
@hellofromtonya
Copy link
Contributor

Rebased against latest trunk to resolve merge conflicts.

lib/load.php Outdated Show resolved Hide resolved
lib/load.php Show resolved Hide resolved
Copy link
Contributor

@hellofromtonya hellofromtonya left a comment

Choose a reason for hiding this comment

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

Scope of this PR - LGTM 👍

Other changes (such as tests, wiring theme.json enqueue, etc.) will be done in other PR(s).

@zaguiini zaguiini merged commit 4bd51e1 into trunk Apr 4, 2022
@zaguiini zaguiini deleted the try/register-and-enqueue-webfonts-by-family branch April 4, 2022 13:52
@github-actions github-actions bot added this to the Gutenberg 13.0 milestone Apr 4, 2022
return $variations;
}

class WP_Theme_JSON_Resolver_Gutenberg extends WP_Theme_JSON_Resolver_6_0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

This file no longer seems to be loaded at all? I'd like to modify get_theme_data but I'm not sure how now...

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, looks like I was stuck in a bad merge state...

@bradhogan
Copy link

Is this now the way fonts should be loaded into a block theme? Any official documentation on this?

@zaguiini
Copy link
Member Author

zaguiini commented Apr 14, 2022

Hey @bradley2083,

Please read #39332 (comment).

@bradhogan
Copy link

@zaguiini Thanks for sharing that. So I'm still not 100% clear but sounds like we still need to use font-face declarations for the time being?

@zaguiini
Copy link
Member Author

zaguiini commented Apr 14, 2022

Sorry, @bradley2083.

We now have separated registration and enqueueing of fonts, just like we have with scripts and styles.

#39988 will enqueue the fonts listed in theme.json, even if they're registered programmatically (i.e. through the wp_register_webfont method).

After that, we'll work on #40363, so we can enqueue automatically the fonts picked in global styles.

So no, you won't need to use font-face declarations. The Webfonts API should be sufficient. Right now, you can use it to register and enqueue webfonts through the API.

When #39988 gets merged, you can use solely theme.json to register and enqueue fonts. Note that the picker in global styles won't work for externally/programmatically registered webfonts, only for the fonts explicitly listed in theme.json.

This problem will be addressed in #40363, so externally registered webfonts will be considered when enqueueing fonts to the front-end.

@bradhogan
Copy link

Ok got it. Thanks @zaguiini I'll start to play around with using wp_register_webfont I assume this is too early to have any documentation / examples for this stuff atm?

@zaguiini
Copy link
Member Author

Yeah, right, @bradley2083. It's not going to be included in 6.0, so too early. But the methods in webfonts.php do have some documentation. It should be straightforward to understand what's going on.

@gigitux
Copy link
Contributor

gigitux commented May 3, 2022

We noticed that with the new Gutenberg versions (from 13.0) the Global Styles for WC Blocks plugin doesn’t apply anymore.

Screen Capture on 2022-05-03 at 16-08-09

It seems that the problem is caused by this PR, in particular, this this change.

I don't have a lot of context on this part of the code. Could you take a look? Thanks!

cc @zaguiini @hellofromtonya

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants