Framework-Tools für Schriftarten-Fallbacks

Ralph Meier
Janicklas Ralph James

Auf Websites, auf denen Schriftarten mit font-display: swap geladen werden, kommt es häufig zu einem Layout Shift (CLS), wenn die Webschriftart geladen und durch die Fallback-Schriftart ersetzt wird.

Sie können CLS verhindern, indem Sie die Größe der Fallback-Schriftart an die der primären Schriftart anpassen. Mit Eigenschaften wie size-adjust, ascent-override, descent-override und line-gap-override in der @font-face-Regel können die Messwerte einer Fallback-Schriftart überschrieben werden. So haben Entwickler mehr Kontrolle darüber, wie Schriftarten angezeigt werden. Weitere Informationen zu Schriftart-Fallbacks und den Überschreibungseigenschaften finden Sie in diesem Beitrag. Eine funktionierende Implementierung dieser Technik können Sie sich auch in dieser Demo ansehen.

In diesem Artikel erfahren Sie, wie Anpassungen der Schriftgröße in den Frameworks Next.js und Nuxt.js implementiert werden, um den CSS-Code für Fallback-Schriftarten zu generieren und den CLS-Wert zu reduzieren. Außerdem wird gezeigt, wie Sie Fallback-Schriftarten mit Querschnitt-Tools wie Fontaine und Capsize erstellen können.

Hintergrund

font-display: swap wird im Allgemeinen verwendet, um FOIT (Flash of unvisible Text) zu verhindern und Inhalte schneller auf dem Bildschirm anzuzeigen. Über den Wert swap wird dem Browser mitgeteilt, dass Text, in dem die Schriftart verwendet wird, sofort in einer Systemschriftart angezeigt werden und diese erst ersetzen soll, wenn die benutzerdefinierte Schriftart bereit ist.

Das größte Problem mit swap ist der Effekt der Störgeräusche, bei dem der Bildschirminhalt durch den unterschiedlichen Zeichenumfang der beiden Schriftarten hin und her geschoben wird. Dies führt insbesondere bei textlastigen Websites zu schlechten CLS-Werten.

Die folgenden Bilder zeigen ein Beispiel für das Problem. Für das erste Bild wird font-display: swap verwendet, ohne dass versucht wurde, die Größe der Fallback-Schriftart anzupassen. Das zweite Beispiel zeigt, wie die Anpassung der Größe mit der CSS-Regel @font-face den Ladevorgang verbessert.

Ohne Anpassung der Schriftgröße

body {
  font-family: Inter, serif;
}
Text, dessen Schriftart und -größe sich plötzlich ändern, was zu irritierenden Effekten führt.

Nach dem Anpassen der Schriftgröße

body {
  font-family: Inter, fallback-inter, serif;
  }

@font-face {
  font-family: "fallback-inter";
  ascent-override: 90.20%;
  descent-override: 22.48%;
  line-gap-override: 0.00%;
  size-adjust: 107.40%;
  src: local("Arial");
}
Text, der reibungslos in eine andere Schriftart übergeht.

Das Anpassen der Größe der Fallback-Schriftart kann eine effektive Strategie sein, um Layoutverschiebungen beim Laden von Schriftarten zu verhindern. Die komplett neue Logik zu implementieren kann jedoch schwierig sein, wie in diesem Beitrag zu Schriftarten-Fallbacks beschrieben. Glücklicherweise gibt es bereits verschiedene Tools, die dies bei der Entwicklung von Apps erleichtern.

Schriftart-Fallbacks mit Next.js optimieren

Next.js bietet eine integrierte Möglichkeit zur Aktivierung der Fallback-Schriftartoptimierung. Diese Funktion ist standardmäßig aktiviert, wenn Sie Schriftarten mit der Komponente @next/font laden.

Die Komponente @next/font wurde in Next.js Version 13 eingeführt. Die Komponente stellt eine API zum Importieren von Google Fonts oder benutzerdefinierten Schriftarten in Ihre Seiten bereit und beinhaltet ein integriertes automatisches Selbst-Hosting von Schriftartdateien.

Die Messwerte für die Fallback-Schriftarten werden automatisch berechnet und in die CSS-Datei eingefügt.

Wenn Sie beispielsweise eine Roboto-Schriftart verwenden, würden Sie diese in der Regel wie folgt in CSS definieren:

@font-face {
  font-family: 'Roboto';
  font-display: swap;
  src: url('/fonts/Roboto.woff2') format('woff2'), url('/fonts/Roboto.woff') format('woff');
  font-weight: 700;
}

body {
  font-family: Roboto;
}

So migrieren Sie zur nächsten/Schriftart:

  1. Verschieben Sie die Deklaration der Roboto-Schriftart in Ihr JavaScript, indem Sie die Roboto-Funktion von 'next/font' importieren. Der Rückgabewert der Funktion ist ein Klassenname, den Sie in Ihrer Komponentenvorlage verwenden können. Denken Sie daran, dem Konfigurationsobjekt display: swap hinzuzufügen, um die Funktion zu aktivieren.

     import { Roboto } from '@next/font/google';
    
    const roboto = Roboto({
      weight: '400',
      subsets: ['latin'],
      display: 'swap' // Using display swap automatically enables the feature
    })
    
  2. Verwenden Sie in Ihrer Komponente den generierten Klassennamen: javascript export default function RootLayout({ children }: { children: React.ReactNode; }) { return ( <html lang="en" className={roboto.className}> <body>{children}</body> </html> ); }

Die Konfigurationsoption adjustFontFallback:

Für @next/font/google:Ein boolescher Wert, mit dem festgelegt wird, ob eine automatische Fallback-Schriftart verwendet werden soll, um die Cumulative Layout Shift zu reduzieren. Die Standardeinstellung ist "true". Next.js setzt die Fallback-Schriftart je nach Schriftart (Serif bzw. Sans-Serif) automatisch auf Arial oder Times New Roman.

Für @next/font/local:Ein String oder boolescher Wert für „Falsch“, mit dem festgelegt wird, ob eine automatische Fallback-Schriftart verwendet werden soll, um die Cumulative Layout Shift zu reduzieren. Mögliche Werte sind Arial, Times New Roman oder false. Der Standardwert ist Arial. Wenn Sie eine Serifenschrift verwenden möchten, sollten Sie diesen Wert auf Times New Roman setzen.

Eine weitere Option für Google Fonts

Falls die Verwendung der Komponente next/font nicht möglich ist, können Sie diese Funktion auch mit Google Fonts über das Flag optimizeFonts nutzen. Bei Next.js ist die optimFonts-Funktion bereits standardmäßig aktiviert. Mit dieser Funktion wird das CSS von Google Fonts in die HTML-Antwort eingefügt. Außerdem können Sie die Funktion zur Anpassung von Fallback-Schriftarten aktivieren, indem Sie das Flag experimental.adjustFontFallbacksWithSizeAdjust in der Datei "next.config.js" festlegen, wie im folgenden Snippet gezeigt:

// In next.config.js
module.exports = {
 experimental: {
   adjustFontFallbacksWithSizeAdjust: true,
 },
}

Hinweis: Es gibt keinen Plan, diese Funktion mit dem neu eingeführten app-Verzeichnis zu unterstützen. Langfristig ist es ideal, next/font zu verwenden.

Schriftart-Fallbacks mit Nuxt anpassen

@nuxtjs/fontaine ist ein Modul für das Nuxt.js-Framework, mit dem automatisch die Messwerte für die Fallback-Schriftart berechnet und das Fallback-CSS für @font-face generiert wird.

Aktivieren Sie das Modul, indem Sie @nuxtjs/fontaine in die Modulkonfiguration aufnehmen:

import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['@nuxtjs/fontaine'],
})

Wenn Sie Google Fonts verwenden oder für eine Schriftart keine @font-face-Deklaration vorhanden ist, können Sie diese als zusätzliche Optionen deklarieren.

In den meisten Fällen kann das Modul die @font-face-Regeln aus Ihrem CSS-Code lesen und automatisch die Details wie Schriftfamilie, Fallback-Schriftfamilie und Anzeigetyp ableiten.

Wenn die Schriftart an einer Stelle definiert ist, die vom Modul nicht sichtbar ist, können Sie die Messwertinformationen übergeben, wie im folgenden Code-Snippet gezeigt.

export default defineNuxtConfig({
  modules: ['@nuxtjs/fontaine'],
  fontMetrics: {
  fonts: ['Inter', { family: 'Some Custom Font', src: '/path/to/custom/font.woff2' }],
},
})

Das Modul scannt automatisch Ihren CSS-Code, um die @font-face-Deklarationen zu lesen, und generiert die @font-face-Fallback-Regeln.

@font-face {
  font-family: 'Roboto';
  font-display: swap;
  src: url('/fonts/Roboto.woff2') format('woff2'), url('/fonts/Roboto.woff') format('woff');
  font-weight: 700;
}
/* This will be generated. */
@font-face {
  font-family: 'Roboto override';
  src: local('BlinkMacSystemFont'), local('Segoe UI'), local('Roboto'), local('Helvetica Neue'),
    local('Arial'), local('Noto Sans');
  ascent-override: 92.7734375%;
  descent-override: 24.4140625%;
  line-gap-override: 0%;
}

Sie können in Ihrem CSS-Code jetzt Roboto override als Fallback-Schriftart verwenden, wie im folgenden Beispiel gezeigt.

:root {
  font-family: 'Roboto';
  /* This becomes */
  font-family: 'Roboto', 'Roboto override';
}

CSS selbst generieren

Eigenständige Bibliotheken helfen Ihnen beim Generieren des CSS-Codes für Fallback-Schriftgrößenanpassungen.

Fontaine-Bibliothek verwenden

Wenn Sie nicht Nuxt oder Next.js verwenden, können Sie Fontaine verwenden. Fontaine ist die zugrunde liegende Bibliothek für @nuxtjs/fontaine. Sie können diese Bibliothek in Ihrem Projekt verwenden, um CSS-Code für Fallback-Schriftarten mithilfe von Vite- oder Webpack-Plug-ins automatisch einzufügen.

Angenommen, in der CSS-Datei ist eine Roboto-Schriftart definiert:

@font-face {
  font-family: 'Roboto';
  font-display: swap;
  src: url('/fonts/Roboto.woff2') format('woff2'), url('/fonts/Roboto.woff') format('woff');
  font-weight: 700;
}

Fontaine stellt Vite- und Webpack-Transformer bereit, mit denen sich das Plug-in ganz einfach in die Build-Kette einbinden lässt. Aktivieren Sie das Plug-in, wie im folgenden JavaScript-Code gezeigt.

import { FontaineTransform } from 'fontaine'

const options = {
  fallbacks: ['BlinkMacSystemFont', 'Segoe UI', 'Helvetica Neue', 'Arial', 'Noto Sans'],
  // You may need to resolve assets like `/fonts/Roboto.woff2` to a particular directory
  resolvePath: (id) => 'file:///path/to/public/dir' + id,
  // overrideName: (originalName) => `${name} override`
  // sourcemap: false
}

Wenn Sie Vite verwenden, fügen Sie das Plug-in so hinzu: javascript // Vite export default { plugins: [FontaineTransform.vite(options)] }

Wenn Sie Webpack verwenden, aktivieren Sie es so:

// Webpack
export default {
  plugins: [FontaineTransform.webpack(options)]
}

Das Modul scannt automatisch Ihre Dateien, um die @font-face-Regeln zu ändern: css @font-face { font-family: 'Roboto'; font-display: swap; src: url('/fonts/Roboto.woff2') format('woff2'), url('/fonts/Roboto.woff') format('woff'); font-weight: 700; } /* This will be generated. */ @font-face { font-family: 'Roboto override'; src: local('BlinkMacSystemFont'), local('Segoe UI'), local('Roboto'), local('Helvetica Neue'), local('Arial'), local('Noto Sans'); ascent-override: 92.7734375%; descent-override: 24.4140625%; line-gap-override: 0%; }

Sie können jetzt Roboto override als Fallback-Schriftart in CSS verwenden. css :root { font-family: 'Roboto'; /* This becomes */ font-family: 'Roboto', 'Roboto override'; }

Die Capsize-Bibliothek verwenden

Wenn Sie Next.js, Nuxt, Webpack oder Vite nicht verwenden, können Sie auch die Capsize-Bibliothek verwenden, um das Fallback-CSS zu generieren.

Neue createFontStack API

Die API ist Teil des @capsize/core-Pakets namens createFontStack, das ein Array von Schriftartmesswerten in derselben Reihenfolge akzeptiert, in der Sie Ihr Schriftart-Stack (die font-family-Eigenschaft) angeben würden.

Weitere Informationen zur Verwendung von Capsize finden Sie hier.

Beispiel

Sehen Sie sich das folgende Beispiel an: Die gewünschte Web-Schriftart ist Lobster, bei dem auf Helvetica Neue und dann auf Arial zurückgegriffen wird. Im CSS-Code: font-family: Lobster, 'Helvetica Neue', Arial.

  1. Importieren Sie createFontStack aus dem Core-Paket:

    import { createFontStack } from '@capsizecss/core';
    
  2. Importieren Sie die Messwerte für jede gewünschte Schriftart (siehe oben auf der Seite „Schriftartenmesswerte“): javascript import lobster from '@capsizecss/metrics/lobster'; import helveticaNeue from '@capsizecss/metrics/helveticaNeue'; import arial from '@capsizecss/metrics/arial';`

  3. Erstellen Sie einen Schriftart-Stack und übergeben Sie die Messwerte als Array. Verwenden Sie dabei dieselbe Reihenfolge wie bei der CSS-Eigenschaft „font-family“. javascript const { fontFamily, fontFaces } = createFontStack([ lobster, helveticaNeue, arial, ]);

Es wird Folgendes zurückgegeben:

{
  fontFamily: Lobster, 'Lobster Fallback: Helvetica Neue', 'Lobster Fallback: Arial',
  fontFaces: [
    {
      '@font-face' {
      'font-family': '"Lobster Fallback: Helvetica Neue"';
      src: local('Helvetica Neue');
      'ascent-override': '115.1741%';
      'descent-override': '28.7935%';
      'size-adjust': '86.8251%';
      }
     '@font-face' {
       'font-family': '"Lobster Fallback: Arial"';
       src: local('Arial');
       'ascent-override': 113.5679%;
       'descent-override': 28.392%;
       'size-adjust': 88.053%;
     }
   }
 ]
}

Sie müssen den fontFamily- und fontFaces-Code in den CSS-Code einfügen. Der folgende Code zeigt, wie er in einem CSS-Stylesheet oder innerhalb eines <style>-Blocks implementiert wird.

<style type="text/css">
  .heading {
    font-family: 
  }

  
</style>

Dadurch wird der folgende CSS-Code erstellt:

.heading {
  font-family: Lobster, 'Lobster Fallback: Helvetica Neue',
    'Lobster Fallback: Arial';
}

@font-face {
  font-family: 'Lobster Fallback: Helvetica Neue';
  src: local('Helvetica Neue');
  ascent-override: 115.1741%;
  descent-override: 28.7935%;
  size-adjust: 86.8251%;
}
@font-face {
  font-family: 'Lobster Fallback: Arial';
  src: local('Arial');
  ascent-override: 113.5679%;
  descent-override: 28.392%;
  size-adjust: 88.053%;
}

Sie können auch das Paket @capsize/metrics verwenden, um die Überschreibungswerte zu berechnen und sie selbst auf den CSS-Code anzuwenden.

const fontMetrics = require(`@capsizecss/metrics/inter`);
const fallbackFontMetrics = require(`@capsizecss/metrics/arial`);
const mainFontAvgWidth = fontMetrics.xAvgWidth / fontMetrics.unitsPerEm;
const fallbackFontAvgWidth = fallbackFontMetrics.xAvgWidth / fallbackFontMetrics.unitsPerEm;
let sizeAdjust = mainFontAvgWidth / fallbackFontAvgWidth;
let ascent = fontMetrics.ascent / (unitsPerEm * fontMetrics.sizeAdjust));
let descent = fontMetrics.descent / (unitsPerEm * fontMetrics.sizeAdjust));
let lineGap = fontMetrics.lineGap / (unitsPerEm * fontMetrics.sizeAdjust));

Danksagungen

Hero-Image von Alexander Andrews auf Unsplash