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

Wrong local font file being referenced by @font-face generated from theme.json #42190

Closed
mateuswetah opened this issue Jul 6, 2022 · 10 comments · Fixed by #47254
Closed

Wrong local font file being referenced by @font-face generated from theme.json #42190

mateuswetah opened this issue Jul 6, 2022 · 10 comments · Fixed by #47254
Assignees
Labels
[Type] Bug An existing feature does not function as intended

Comments

@mateuswetah
Copy link
Contributor

Description

When using the settings.typography.fontFamilies[].fontFace setting in theme.json, we have a nice way to let Gutenberg create @font-face css for ourselves.

Sadly, that feature is causing a bug by generating a src list prepended by `local('Name of the font'). The internals are done here:

This seems nice, as it automatically handles the possibility of having local fonts installed on the user system. The problem is that by taking the $font_familiy name here, we don't consider that the user may have installed the font from separate files to bold, medium, light, etc. And those files should be listed as different local files.

I am not 100% sure that this is the cause of the bug that I will describe here, but I do feel we should have some option to disable or at least configure this prepending.

Step-by-step reproduction instructions

  1. Install on your computer a font with different files for each weight. For example, "El Messiri" regular (ElMessiri-Regular.ttf) and bold (ElMessiri-Bold.tff) variations from here.
  2. In your FSE theme, have the font files also available in a folder. Here I am using assets/fonts/static/;
  3. Create a theme.json file with the following settings configuration:
{
  "settings": {
      "typography": {
	  "lineHeight": true,
	  "fontFamilies": [
		{
			"fontFamily": "\"El Messiri\", system-ui, -apple-system, \"Segoe UI\", \"Liberation Sans\", sans-serif",
			"name": "Titles (El Messiri)",
			"slug": "headings",
			"fontFace": [
				{
					"fontFamily": "\"El Messiri\"",
					"fontWeight": "400",
					"fontStyle": "normal",
					"src": [ "file:./assets/fonts/static/ElMessiri-Regular.ttf" ]
				},
				{
					"fontFamily": "\"El Messiri\"",
					"fontWeight": "700",
					"fontStyle": "normal",
					"src": [ "file:./assets/fonts/static/ElMessiri-Bold.ttf" ]
				}
			]
		}
          ]
       }
    }
}
  1. Use the font family in any page just to demonstrate it. Have a heading block bold, for example.
  2. Upload your theme and page to any web hosting service.
  3. Access the page. Via browser inspector, we can see that the generated @font-face will be something like this:
@font-face {
  font-family: "El Messiri";
  font-style: normal;
  font-weight: 400;
  font-display: fallback;
  src: local("El Messiri"),
    url("https://your-host.com/wp-content/themes/your-theme/assets/fonts/static/ElMessiri-Regular.ttf")
      format("truetype");
}
@font-face {
  font-family: "El Messiri";
  font-style: normal;
  font-weight: 700;
  font-display: fallback;
  src: local("El Messiri"),
    url("https://your-host.com/wp-content/themes/your-theme/assets/fonts/static/ElMessiri-Bold.ttf")
      format("truetype");
}

The font will appear bold in computers where the local font is not installed, but regular where it is. (attachments bellow). In other words, is like if the font-face gives up loading the bold font once it finds the regular one.

I know it sounds weird, but I am bringing this here as the issue is completely solved if we remove the local('El Messiri') from the font-face css.

Screenshots, screen recording, code snippet

font_working
font_not_working

Environment info

  • WordPress 6.0.0, Gutenberg 13.5.2
  • Tested on latest Google Chrome, Opera and Firefox. Weirdly, Firefox does present the error, but after a considerable time (something like 30 secs) it loads the bold font correctly.
  • Tested on a Windows 11.

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

Yes

@aristath
Copy link
Member

aristath commented Jul 12, 2022

The use of local() fonts in the CSS is a bit debated... Google Fonts for years was defining it, and then only recently removed it (see google/fonts#2620)
It's true, local can cause the font-family to not be displayed as intended by the designer if the user has a different variation installed on their system locally, with the same name as the one defined in the CSS.
However, as soon as Google removed local() from their fonts CSS, it was pointed out that this is an accessibility & performance issue (see google/fonts#2855)
It's not a clear-cut bug... We should see what the pros and cons of each implementation are, and then find a balanced solution 👍

@mateuswetah
Copy link
Contributor Author

Nice to know these details @aristath.

I personally don't get why the error occurred with my client since she was downloading the font file from Google Fonts itself... But I also agree that it is a nice thing to have by default. Would just be good to have a filter or something like that to either remove it or change the name passed to the local()

@elbsegler63
Copy link

See also in the tt2 forum:
https://wordpress.org/support/topic/font-weight-300-is-not-displayed/

A workaround in the child themes theme.json or in the additional CSS cannot be a permanent solution.

@eHtmlu
Copy link

eHtmlu commented Dec 10, 2022

@aristath I'm not sure if the actual point has been made clear enough here as there are two different topics being discussed here. Actually I think you guys were talking past each other.

The initial comment refers to the following bug:
Currently WordPress passes the font family name to local() but the local() function actually needs the name of the specific font. For example local("El Messiri Bold") instead of local("El Messiri").

So because WordPress passes only the font family name (local("El Messiri")), only the regular font will be loaded, no matter what font-weight or font-style is defined in @font-face.

I had the same problem with "Source Sans Pro". However, because it's a logical error I am sure that the problem occurs with all font families that have different files for weight and style (so very most fonts). This means that most fonts have big problems when the font is installed on user's system. Even if the files installed are exactly the same as the ones the site supplies.

Therefore, in my opinion, the label "[Feature] Webfonts" does not fit here, as there is definitely a bug.

@lime
Copy link

lime commented Dec 30, 2022

Chiming in to second what @eHtmlu said – this bug is caused by Wordpress outputting only the family name, not the full name of the font face.

This would match the way it's phrased over at MDN (emphasis mine):

/* <font-face-name> values */
src: local(font); /* Unquoted name */
src: local(some font); /* Name containing space */
src: local("font"); /* Quoted name */

<font-face-name>
Specifies the full name or postscript name of a locally-installed font face using the local() function, which uniquely identifies a single font face within a larger family. The name can optionally be enclosed in quotes.

In my case, local(Montserrat) leads to Montserrat-Regular being rendered everywhere, regardless of font weight. For the time being, I can circumvent this by setting "fontFamily": "Montserrat-Custom-Name", effectively disabling the call to local().

@lime
Copy link

lime commented Dec 30, 2022

As for solving it, it seems like we would need to know either the Full name or the PostScript name of the font face. I would imagine there are a couple of options:

  1. Use the filename, which may or may not match the PostScript name ("Montserrat-SemiBoldItalic").
  2. Guess the full name by combining family, common weight names, and style ("Montserrat SemiBold Italic").
  3. Actually read the names from the font file.
  4. Allow the user to specify the local name to use, either as a separate attribute or as just another item in the src list.

Just looking at a couple of fonts on my machine, I would not expect a very high hit rate for options 1 & 2. Still, if it's meant as a zero-config best guess, maybe that's acceptable? Option 1 has the benefit of giving some control back to the user, as they can choose to tweak the filenames of self-hosted font files.

Option 3 would be the most correct, but is probably not desirable due to the added complexity, unless we already read the font files for some other reason.

Option 4 would probably be my preference, even if we use one of the other options by default. Maybe we could allow "src": [ "local(Foo-Bar)", "file:./..." ] , and skip the automagic addition if one exists?

@eHtmlu
Copy link

eHtmlu commented Dec 30, 2022

@carolinan Please consider classifying this issue as a bug rather than a feature, because WordPress uses local() in a wrong way, which results in wrong font faces.

@carolinan carolinan added the [Type] Bug An existing feature does not function as intended label Jan 2, 2023
@Luehrsen
Copy link
Contributor

Luehrsen commented Jan 7, 2023

I strongly support dropping the default addition of local() to the webfonts stylesheet.

Not only is the usage from WordPress questionable, most big vendors have dropped the usage of local as well, due to the plethora of potential issues due to version mismatch and such.

I've prepared a core ticket and patch to drop local from the stylesheet.

https://core.trac.wordpress.org/ticket/57430#ticket

@Luehrsen
Copy link
Contributor

Luehrsen commented Jan 8, 2023

However, as soon as Google removed local() from their fonts CSS, it was pointed out that this is an accessibility & performance issue (see google/fonts#2855)

I fail to see the reasoning behind the accessibility issues. The reporting user mentions performance as an issue, but that seems to be in the same lane as using images and other static assets.

To be fair, in terms of accessibility, I believe the contrary to be the case: Using local and possibly creating a version mismatch between a locally installed version and the intended version can lead to legibility issues, which can become an accessibility issue.

It's not a clear-cut bug...

The fact that Google dropped the use of local worldwide over 2 years ago and that there is no resistance or outcry leads me to believe that this issue is not as ambiguous as it may seem.

@spacedragn
Copy link

I can confirm that local() is a showstopper for several other folks, as reported on the “Create Block Theme” support forum. The immediate solution for developers is rollback to vendor-hosted fonts. Not ideal! This is my fix until local() is removed from this implementation or debugged thoroughly for all browsers.

See:
https://wordpress.org/support/topic/font-weights-styles-not-working-in-firefox/
https://wordpress.org/support/topic/google-roboto-font-appearance-wont-work/
https://wordpress.org/support/topic/bold-italic-google-font-pt-serif-not-working/
https://wordpress.org/support/topic/bold-font-weight-is-not-working/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Bug An existing feature does not function as intended
Projects
None yet
10 participants