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 mit der Fallback-Schriftart ausgetauscht 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 dargestellt 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, in dem diese Schriftart verwendet wird, 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;
}
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");
}
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:
Verschieben Sie die Roboto-Schriftartdeklaration in Ihr JavaScript, indem Sie den Roboto importieren aus 'next/font' abrufen. 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 })
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 die Fallback-Schriftart je nach Schriftart automatisch auf Arial
oder Times New Roman
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 mit dem neu eingeführten Verzeichnis app
zu unterstützen. Langfristig ist es ideal, 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 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 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 wie folgt 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
.
Importieren Sie createFontStack aus dem Kernpaket:
import { createFontStack } from '@capsizecss/core';
Importieren Sie die Schriftartmesswerte für jede der gewünschten Schriftarten (siehe Schriftartmesswerte oben):
javascript import lobster from '@capsizecss/metrics/lobster'; import helveticaNeue from '@capsizecss/metrics/helveticaNeue'; import arial from '@capsizecss/metrics/arial';`
Erstellen Sie den Schriftartstapel 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