Framework-Tools für Schriftarten-Fallbacks

Janicklas Ralph James
Janicklas Ralph James

Websites, auf denen Schriftarten mit font-display: swap geladen werden, leiden häufig unter einer Layoutverschiebung (CLS), wenn die Webschriftart geladen und gegen die Fallback-Schriftart ausgetauscht wird.

Sie können CLS verhindern, indem Sie die Abmessungen der Fallback-Schriftart an die der Hauptschriftart anpassen. Mithilfe von Eigenschaften wie size-adjust, ascent-override, descent-override und line-gap-override in der Regel @font-face können die Messwerte einer Fallback-Schriftart überschrieben werden, sodass Entwickler mehr Kontrolle darüber haben, wie Schriftarten angezeigt werden. Weitere Informationen zu Schrift-Fallbacks und den Überschreibungseigenschaften finden Sie in diesem Beitrag. Eine funktionierende Implementierung dieser Technik sehen Sie in dieser Demo.

In diesem Artikel erfahren Sie, wie Anpassungen der Schriftgröße in den Next.js- und Nuxt.js-Frameworks implementiert werden, um das Fallback-Schrift-CSS zu generieren und den CLS zu reduzieren. Außerdem wird gezeigt, wie Sie mithilfe von Tools wie Fontaine und Capsize Fallback-Schriftarten generieren können.

Hintergrund

font-display: swap wird in der Regel verwendet, um das Aufblitzen unsichtbaren Texts (FOIT, Flash of Invisible Text) zu verhindern und Inhalte schneller auf dem Bildschirm anzuzeigen. Der Wert von swap teilt dem Browser mit, dass Text mit der Schriftart sofort mit einer Systemschriftart angezeigt werden soll und die Systemschriftart nur ersetzt werden soll, wenn die benutzerdefinierte Schriftart bereit ist.

Das größte Problem bei swap ist der störende Effekt, bei dem der Unterschied in der Schriftgröße der beiden Schriftarten dazu führt, dass sich der Bildschirminhalt verschiebt. Dies führt zu schlechten CLS-Werten, insbesondere bei Websites mit viel Text.

Die folgenden Bilder zeigen ein Beispiel für das Problem. Im ersten Bild wird font-display: swap verwendet, ohne dass die Größe der Fallback-Schrift angepasst wurde. Im zweiten Beispiel wird gezeigt, wie sich das Laden durch die Anpassung der Größe mithilfe der CSS-Regel @font-face verbessern lässt.

Ohne Anpassung der Schriftgröße

body {
  font-family: Inter, serif;
}
Text, der plötzlich in Schriftart und Größe wechselt und dadurch einen irritierenden Effekt erzeugt.

Nach der Anpassung 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 nahtlos in eine andere Schriftart übergeht.

Die Größe der Fallback-Schrift anzupassen, kann eine effektive Strategie sein, um Layoutverschiebungen beim Laden der Schrift zu verhindern. Die Logik von Grund auf zu implementieren, kann jedoch schwierig sein, wie in diesem Beitrag zu Schrift-Fallbacks beschrieben. Glücklicherweise gibt es bereits mehrere Tools, die die Entwicklung von Apps erleichtern.

Schrift-Fallbacks mit Next.js optimieren

Next.js bietet eine integrierte Möglichkeit, die Fallback-Schriftoptimierung zu aktivieren. 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 bietet eine API, mit der Sie Google Fonts oder benutzerdefinierte Schriftarten in Ihre Seiten importieren können. Außerdem ist das automatische Self-Hosting von Schriftdateien integriert.

Bei Verwendung werden die Fallback-Schriftmetriken automatisch berechnet und in die CSS-Datei eingefügt.

Wenn Sie beispielsweise die Schriftart „Roboto“ verwenden, würden Sie sie in CSS normalerweise so 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 zu einem anderen Schriftschnitt:

  1. Verschieben Sie die Roboto-Schriftdeklaration in Ihr JavaScript, indem Sie die Funktion „Roboto“ aus „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, der festlegt, ob eine automatische Fallback-Schriftart verwendet werden soll, um die kumulative Layoutverschiebung zu reduzieren. Die Standardeinstellung ist "true". Next.js legt die Fallback-Schriftart automatisch auf Arial oder Times New Roman fest, je nach Schriftart (serifenlos oder Serifenschrift).

Für @next/font/local:Ein String oder ein boolescher Wert „false“, der festlegt, ob eine automatische Fallback-Schriftart verwendet werden soll, um die kumulative Layoutverschiebung zu reduzieren. Mögliche Werte sind Arial, Times New Roman und false. Der Standardwert ist Arial. Wenn Sie eine Serifenschrift verwenden möchten, sollten Sie diesen Wert auf Times New Roman festlegen.

Weitere Option für Google Fonts

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

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

Hinweis: Diese Funktion wird nicht für das neu eingeführte Verzeichnis app unterstützt. Langfristig sollten Sie next/font verwenden.

Schrift-Fallbacks mit Nuxt anpassen

@nuxtjs/fontaine ist ein Modul für das Nuxt.js-Framework, das automatisch die Werte der Fallback-Schriftmetriken berechnet und das Fallback-@font-face-CSS generiert.

Aktivieren Sie das Modul, indem Sie @nuxtjs/fontaine zur Modulkonfiguration hinzufügen:

import { defineNuxtConfig } from 'nuxt'

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

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

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

Wenn die Schriftart an einem Ort definiert ist, der vom Modul nicht gefunden werden kann, kannst du die Messwertinformationen wie im folgenden Code-Snippet gezeigt übergeben.

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

Das Modul scannt automatisch Ihr CSS, um die @font-face-Deklarationen zu lesen, und generiert die Fallback-@font-face-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 Roboto override jetzt als Fallback-Schriftart in Ihrem CSS verwenden, wie im folgenden Beispiel gezeigt:

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

CSS selbst generieren

Mit eigenständigen Bibliotheken können Sie auch das CSS für Anpassungen der Fallback-Schriftgröße generieren.

Fontaine-Bibliothek verwenden

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

Angenommen, Sie haben in der CSS-Datei die Schriftart „Roboto“ 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 bietet Vite- und Webpack-Transformer, die sich ganz einfach in die Build-Chain einbinden lassen. 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 Ihre Dateien automatisch, 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 Roboto override jetzt als Fallback-Schriftart in CSS verwenden. css :root { font-family: 'Roboto'; /* This becomes */ font-family: 'Roboto', 'Roboto override'; }

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 API createFontStack

Die API ist Teil des Pakets @capsize/core mit dem Namen createFontStack. Sie akzeptiert ein Array von Schriftschnittmesswerten in derselben Reihenfolge, in der Sie Ihren Schriftschnittstapel (das Attribut font-family) angeben würden.

Eine Dokumentation zur Verwendung von Capsize finden Sie hier.

Beispiel

Betrachten Sie das folgende Beispiel: Die gewünschte Webschrift ist Lobster, als Rückfalloption wird Helvetica Neue und dann Arial verwendet. In CSS: font-family: Lobster, 'Helvetica Neue', Arial.

  1. Importieren Sie „createFontStack“ aus dem Kernpaket:

    import { createFontStack } from '@capsizecss/core';
    
  2. Importieren Sie die Schriftmetriken für jede der gewünschten Schriftarten (siehe oben unter „Schriftmetriken“): javascript import lobster from '@capsizecss/metrics/lobster'; import helveticaNeue from '@capsizecss/metrics/helveticaNeue'; import arial from '@capsizecss/metrics/arial';`

  3. Erstellen Sie Ihren Schriftstapel und übergeben Sie die Messwerte als Array in derselben Reihenfolge wie über die 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 Ihrem CSS den Code für fontFamily und fontFaces hinzufügen. Im folgenden Code wird gezeigt, wie Sie sie in einem CSS-Stylesheet oder in einem <style>-Block implementieren.

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

  
</style>

Das ergibt folgendes CSS:

.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 selbst auf das Preisvergleichsportal 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));