Framework-Tools für Schriftarten-Fallbacks

Janicklas Ralph James
Janicklas Ralph James

Bei 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 Hauptschriftart 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. Entwickler haben so mehr Kontrolle darüber, wie Schriftarten angezeigt werden. Weitere Informationen zu Schriftarten-Fallbacks und zum Überschreiben finden Sie in diesem Beitrag. In dieser Demo können Sie sich ebenfalls eine funktionierende Implementierung dieser Technik ansehen.

In diesem Artikel wird erläutert, wie Anpassungen der Schriftgröße in den Frameworks Next.js und Nuxt.js implementiert werden, um den CSS-Code der Fallback-Schriftart zu generieren und den CLS-Wert zu reduzieren. Außerdem wird gezeigt, wie Sie mit Cross-Cut-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, der diese Schriftart verwendet, sofort in einer Systemschriftart angezeigt werden soll und die Systemschrift erst dann ersetzen soll, wenn die benutzerdefinierte Schriftart verfügbar ist.

Das größte Problem bei swap ist der Verzerrungseffekt, bei dem aufgrund der unterschiedlichen Zeichengrößen der beiden Schriftarten eine Verschiebung des Bildschirminhalts zur Folge hat. Dies führt vor allem bei textlastigen Websites zu schlechten CLS-Werten.

Die folgenden Bilder zeigen ein Beispiel für das Problem. Im ersten Bild wird font-display: swap verwendet. Dabei wurde nicht versucht, die Größe der Fallback-Schriftart anzupassen. Das zweite Beispiel zeigt, wie sich durch das Anpassen der Größe mit der CSS-Regel @font-face der Ladevorgang verbessert.

Ohne Anpassung der Schriftgröße

body {
  font-family: Inter, serif;
}
Text, bei dem sich die Schriftart und -größe plötzlich ändert, was zu Unklarheiten 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 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 Tooloptionen, die dies bei der Entwicklung von Apps erleichtern.

Schriftart-Fallbacks mit Next.js optimieren

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

Die Komponente @next/font wurde in der Next.js-Version 13 eingeführt. Die Komponente bietet ein API zum Importieren von Google Fonts oder benutzerdefinierten Schriftarten in Ihre Seiten und umfasst ein integriertes automatisches Selbsthosting von Schriftartdateien.

Die Messwerte für 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 migrierst du zur nächsten Schriftart:

  1. Verschieben Sie die Roboto-Schriftartdeklaration in Ihr JavaScript, indem Sie die Roboto-Funktion aus "next/font" importieren. Der Rückgabewert der Funktion ist ein Klassenname, den Sie in Ihrer Komponentenvorlage verwenden können. Denken Sie daran, display: swap zum Konfigurationsobjekt 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 der 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 Cumulative Layout Shift zu reduzieren. Die Standardeinstellung ist "true". Next.js legt abhängig von der Schriftart automatisch entweder Arial oder Times New Roman als Fallback-Schriftart fest (Serif oder Sans Serif).

Für @next/font/local:Ein String oder boolescher Wert für „false“, der festlegt, ob eine automatische Fallback-Schriftart verwendet werden soll, um Cumulative Layout Shift 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.

Eine 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 bereits standardmäßig aktiviert. Mit dieser Funktion wird der CSS-Code der Google-Schriftart in die HTML-Antwort eingebunden. Außerdem können Sie die Anpassungsfunktion für Schrift-Fallbacks aktivieren, indem Sie das Flag experimental.adjustFontFallbacksWithSizeAdjust in Ihrer Datei „next.config.js“ festlegen, wie im folgenden Snippet gezeigt:

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

Hinweis: Es ist nicht geplant, diese Funktion im neu eingeführten Verzeichnis app zu unterstützen. Langfristig ist es am besten, next/font zu verwenden.

Schriftarten-Fallbacks mit Nuxt anpassen

@nuxtjs/fontaine ist ein Modul für das Nuxt.js-Framework, das automatisch die Messwerte für die Fallback-Schriftart berechnet und den CSS-Code @font-face für das Fallback 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 für eine Schriftart keine @font-face-Deklaration 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 die Details wie Schriftart, Fallback-Schriftfamilie und Anzeigetyp automatisch ableiten.

Wenn die Schriftart an einem Ort definiert ist, der vom Modul nicht gefunden werden kann, 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 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 können Ihnen auch beim Generieren von CSS für Anpassungen der Schriftgröße im Fallback helfen.

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 mit Fallback-Schriftarten mithilfe von Vite- oder Webpack-Plug-ins automatisch einzufügen.

Angenommen, Sie haben in der CSS-Datei 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 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 du Webpack verwendest, aktiviere 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 jetzt Roboto override als Fallback-Schriftart in CSS verwenden. css :root { font-family: 'Roboto'; /* This becomes */ font-family: 'Roboto', 'Roboto override'; }

Capsize-Bibliothek verwenden

Wenn Sie nicht Next.js, Nuxt, Webpack oder Vite verwenden, können Sie auch die Capsize-Bibliothek verwenden, um den Fallback-CSS-Code 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 Web-Schriftart ist Lobster, wobei zuerst Helvetica Neue und dann Arial verwendet werden. 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 den Schriftartstack 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 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>

Daraufhin wird das folgende CSS generiert:

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

Danksagungen

Hero-Image von Alexander Andrews auf Unsplash