Google Fonts und font-display

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Hallo! Dieser ganze Artikel handelt von einer Zeit vor Mai 2019, in der Google Fonts keine Möglichkeit bot, font-display zu verwenden, ohne die Schriften selbst zu hosten.

Um font-display mit Google Fonts zu verwenden, fügen Sie einen URL-Parameter wie &display=swap zur URL hinzu, z. B. https://fonts.googleapis.com/css?family=Open+Sans&display=swap. Wenn Sie den Code jetzt von Google Fonts kopieren, ist dies der Standard, sodass Sie ihn automatisch erhalten. Sie möchten ihn jedoch möglicherweise hinzufügen, wenn Sie vorhandene URLs zu Google Fonts herumliegen haben oder ihn in etwas wie optional ändern möchten, wenn Sie dies bevorzugen.

Zach Leatherman merkt an, dass es noch einiges zu wünschen übrig lässt, wie z. B. stabile URLs für die Schriften, damit wir die Schriften in unserem eigenen CSS verknüpfen könnten, was den derzeit erforderlichen Doppel-Hop verhindert.


Das ist der Originalartikel

Der font-display Deskriptor in @font-face Blöcken ist wirklich großartig. Er leistet allein schon viel, um die wahrgenommene Leistung beim Laden von Webfonts zu verbessern. Das Laden von Webfonts ist knifflig und ein Werkzeug wie dieses, das so gut funktioniert, ist eine große Sache für das Web.

Es ist eine so große Sache, dass Googles eigener Pagespeed Insights / Lighthouse Sie dafür beanstanden wird, wenn Sie ihn nicht verwenden. Eine grausame Ironie, da ihre eigenen Google Fonts (leicht das meistgenutzte Repository für benutzerdefinierte Schriften im Web) keine Möglichkeit bieten, font-display zu verwenden.

Zusammengefasst von Daniel Dudas hier

Google Developers schlägt vor, Lighthouse zu verwenden -> Lighthouse warnt vor der Nichtverwendung von font-display beim Laden von Schriften -> Webseite verwendet Google Fonts so, wie es auf Google Fonts vorgeschlagen wird -> Google Fonts unterstützt font-display nicht -> Facepalm.

Im Wesentlichen hätten wir Entwickler gerne eine Möglichkeit, font-display in den @font-face Block zu bekommen, den Google so liefert

@font-face {
  font-family: "Open Sans Regular";
  src: url("...");
  font-display: swap;
}

Oder eine Art Alternative, die genauso einfach und genauso effektiv ist.

Scheint, als wären Query-Parameter eine Möglichkeit

Wenn Sie eine Google Schriftart verwenden, erhalten Sie eine URL, die ein Stylesheet liefert und die Schriftart funktionieren lässt. So

https://fonts.googleapis.com/css?family=Roboto

Sie unterstützen auch URL-Parameter für verschiedene Dinge, wie Gewichte

https://fonts.googleapis.com/css?family=Open+Sans:400,700

Und Untergruppen

http://fonts.googleapis.com/css?family=Creepster&text=TRICKS
https://fonts.googleapis.com/css?family=Open+Sans:400,700&subset=cyrillic

Also, warum nicht…

http://fonts.googleapis.com/css?family=Creepster&display=swap

Der Projektleiter sagt, dass Caching ein Problem damit ist (obwohl dies von einigen widerlegt wurde, da sie bereits willkürliche Textparameter unterstützen).

Das Hinzufügen von Query-Parametern reduziert x-Site-Cache-Treffer. Wenn wir am Ende etwas für font-display plus eine Reihe von Parametern für variable Schriften haben, könnte uns das Probleme bereiten.

Sie sagen das später noch einmal in dem Thread, also klingt es unwahrscheinlich, dass wir bald Query-Parameter bekommen werden, aber ich wäre froh, wenn ich falsch liege.

Option: Herunterladen & Selbst hosten

Alle Google Fonts sind Open Source, daher können wir uns eine Kopie davon besorgen, um sie für alles zu verwenden, was wir wollen.

Sobald die Schriftdateien selbst gehostet und bereitgestellt sind, schreiben wir im Grunde @font-face Blöcke, um sie selbst zu verknüpfen, und können jeden font-display einfügen, den wir wollen.

Option: Abrufen & Ändern

Robin Richtsfeld hat eine Idee gepostet, einen Ajax-Aufruf von JavaScript für die Schrift auszuführen, dann die Antwort zu ändern, um font-display einzufügen und sie einzuspritzen.

const loadFont = (url) => {
  // the 'fetch' equivalent has caching issues
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.onreadystatechange = () => {
    if (xhr.readyState == 4 && xhr.status == 200) {
      let css = xhr.responseText;
      css = css.replace(/}/g, 'font-display: swap; }');

      const head = document.getElementsByTagName('head')[0];
      const style = document.createElement('style');
      style.appendChild(document.createTextNode(css));
      head.appendChild(style);
    }
  };
  xhr.send();
}

loadFont('https://fonts.googleapis.com/css?family=Rammetto+One');

Clever! Obwohl ich mir nicht ganz sicher bin, wie das in die Welt des Schriftladens passt. Da wir das Laden dieser Schrift nun in JavaScript handhaben, ist die Ladeleistung davon abhängig, wann und wie wir das Skript laden, das dies ausführt. Wenn wir das tun wollen, sollten wir uns vielleicht mit der Verwendung des offiziellen webfontloader befassen?

Option: Service Workers

Ähnlich wie oben können wir die Schrift abrufen und ändern, aber auf Service-Worker-Ebene, damit wir sie (vielleicht effizienter) cachen können. Adam Lane hat dies geschrieben

self.addEventListener("fetch", event => {
  event.respondWith(handleRequest(event))
});

async function handleRequest(event) {
  const response = await fetch(event.request);
  if (event.request.url.indexOf("https://fonts.googleapis.com/css") === 0 && response.status < 400) {
    // Assuming you have a specific cache name setup   
    const cache = await caches.open("google-fonts-stylesheets");
    const cacheResponse = await cache.match(event.request);
    if (cacheResponse) {
      return cacheResponse;
  }
  const css = await response.text();
  const patched = css.replace(/}/g, "font-display: swap; }");
  const newResponse = new Response(patched, {headers: response.headers});
  cache.put(event.request, newResponse.clone());
    return newResponse;
  }
  return response;
}

Selbst Google stimmt zu, dass die Verwendung von Service Workern zur Unterstützung von Google Fonts eine gute Idee ist. Workbox, ihre Bibliothek zur Abstraktion der Service-Worker-Verwaltung, verwendet Google Fonts als erste Demo auf der Homepage

// Cache the Google Fonts stylesheets with a stale while revalidate strategy.
workbox.routing.registerRoute(
  /^https:\/\/fonts\.googleapis\.com/,
  workbox.strategies.staleWhileRevalidate({
    cacheName: 'google-fonts-stylesheets',
  }),
);

// Cache the Google Fonts webfont files with a cache first strategy for 1 year.
workbox.routing.registerRoute(
  /^https:\/\/fonts\.gstatic\.com/,
  workbox.strategies.cacheFirst({
    cacheName: 'google-fonts-webfonts',
    plugins: [
      new workbox.cacheableResponse.Plugin({
        statuses: [0, 200],
      }),
      new workbox.expiration.Plugin({
        maxAgeSeconds: 60 * 60 * 24 * 365,
      }),
    ],
  }),
);

Option: Cloudflare Workers

Pier-Luc Gendreau hat sich mit der Verwendung von Cloudflare Workers beschäftigt, um dies zu handhaben, hat dann aber mit Supercharge Google Fonts mit Cloudflare und Service Workern nachgelegt, anscheinend für noch bessere Leistung.

Es gibt ein Repo.

Option: Auf @font-feature-values warten

Einer der Gründe, warum Google bei diesem Thema möglicherweise zögert (sie sagen dasselbe), ist, dass es eine neue CSS @rule namens @font-feature-values gibt, die *genau für diese Situation* entwickelt wurde. Hier ist die Spezifikation:

Dieser Mechanismus kann verwendet werden, um eine Standard-Display-Richtlinie für eine gesamte Schriftfamilie festzulegen, und ermöglicht es Entwicklern, eine Display-Richtlinie für @font-face-Regeln festzulegen, die nicht direkt unter ihrer Kontrolle stehen. Wenn beispielsweise eine Schrift von einem Drittanbieter-Schriftenanbieter bereitgestellt wird, kontrolliert der Entwickler die @font-face-Regeln nicht, kann aber dennoch eine Standard-Schrift-Display-Richtlinie für die bereitgestellte Schriftfamilie festlegen. Die Möglichkeit, eine Standardrichtlinie für eine gesamte Schriftfamilie festzulegen, ist auch nützlich, um den "Lösegeldschein-Effekt" (d. h. inkompatible Schriftgesichter) zu vermeiden, da die Display-Richtlinie dann auf die gesamte Schriftfamilie angewendet wird.

Es scheint keine große Bewegung in dieser Hinsicht zu geben (nur ein wenig), aber es scheint nicht gerade großartig, darauf zu warten.