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 Größe 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. In dieser Demo können Sie sich ebenfalls eine funktionierende Implementierung dieser Technik ansehen.

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 FOIT (Flash von unsichtbaren 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 die Schriftart und Größe ändert, was einen irritierenden Effekt verursacht.

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 reibungslos in eine andere Schriftart übergeht.

Das Anpassen der Größe der Fallback-Schriftart kann eine effektive Strategie sein, um Layoutverschiebungen beim Laden einer Schriftart zu verhindern. Die von Grund auf neu zu implementierende Logik kann jedoch schwierig sein, wie in diesem Beitrag zu Schriftarten-Fallbacks beschrieben. Glücklicherweise gibt es bereits mehrere Tools, die dies bei der 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 setzen.

Weitere Option für Google Fonts

Wenn die Verwendung der Komponente „next/font“ keine Option ist, kannst du 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

Eigenständige Bibliotheken können Ihnen auch dabei helfen, den CSS-Code für Anpassungen der Schriftgröße im Fallback zu 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 Fallback-Schrift-CSS 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 eine einfache Einbindung in die Build-Kette ermöglichen. 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 createFontStack-API

Die API ist Teil des @capsize/core-Pakets namens createFontStack, das ein Array mit Schriftmesswerten in derselben Reihenfolge akzeptiert, in der Sie Ihren Schriftstapel angeben (Eigenschaft font-family).

Weitere Informationen 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 Messwerte zu den Schriftarten für jede der gewünschten Schriftarten (siehe „Messwerte zur Schriftart“ oben): 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-Code die Codes "fontFamily" und "fontFaces" hinzufügen. Der folgende Code zeigt, wie er in einem CSS-Style-Sheet oder innerhalb eines <style>-Blocks implementiert wird.

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

  
</style>

Das führt zum folgenden CSS-Code:

.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 CSS 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));