Sites die lettertypen laden met font-display: swap hebben vaak last van een lay-outverschuiving ( CLS ) wanneer het weblettertype wordt geladen en wordt gewisseld met het fallback-lettertype.
U kunt CLS voorkomen door de afmetingen van het fallback-lettertype aan te passen zodat deze overeenkomen met die van het primaire lettertype. Eigenschappen zoals size-adjust
, ascent-override
, descent-override
en line-gap-override
in de @font-face
regel kunnen helpen de statistieken van een fallback-lettertype te overschrijven, waardoor ontwikkelaars meer controle krijgen over hoe lettertypen worden weergegeven. Je kunt in dit bericht meer lezen over lettertype-fallbacks en de override-eigenschappen. In deze demo kunt u ook een werkende implementatie van deze techniek zien.
In dit artikel wordt onderzocht hoe aanpassingen aan de lettergrootte worden geïmplementeerd in de Next.js- en Nuxt.js-frameworks om de fallback-font-CSS te genereren en de CLS te verminderen. Het laat ook zien hoe u reservelettertypen kunt genereren met behulp van transversale tools zoals Fontaine en Capsize.
Achtergrond
font-display: swap wordt over het algemeen gebruikt om FOIT (flits van onzichtbare tekst) te voorkomen en om de inhoud sneller op het scherm weer te geven. De waarde van swap
vertelt de browser dat tekst die het lettertype gebruikt, onmiddellijk moet worden weergegeven met een systeemlettertype en dat het systeemlettertype pas mag worden vervangen als het aangepaste lettertype gereed is.
Het grootste probleem met swap
is het schokkende effect, waarbij het verschil in tekengrootte van de twee lettertypen ertoe leidt dat de scherminhoud verschuift. Dit leidt tot slechte CLS-scores, vooral voor websites met veel tekst.
De volgende afbeeldingen tonen een voorbeeld van het probleem. De eerste afbeelding maakt gebruik van font-display: swap
zonder poging om de grootte van het fallback-lettertype aan te passen. De tweede laat zien hoe het aanpassen van de grootte met behulp van de CSS @font-face
regel de laadervaring verbetert.
Zonder de lettergrootte aan te passen
body {
font-family: Inter, serif;
}
![Tekst die plotseling van lettertype en grootte verandert, waardoor een schokkend effect ontstaat.](https://developer.chrome.google.cn/static/blog/framework-tools-font-fallback/image/text-suddenly-changes-f-ad5f294238b66.gif?authuser=9&hl=nl)
Na het aanpassen van de lettergrootte
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");
}
![Tekst die vloeiend overgaat naar een ander lettertype.](https://developer.chrome.google.cn/static/blog/framework-tools-font-fallback/image/text-transitions-smoothl-200e9965ef42b.gif?authuser=9&hl=nl)
Het aanpassen van de grootte van het fallback-lettertype kan een effectieve strategie zijn om te voorkomen dat de lay-out van het laden van lettertypen verschuift, maar het vanaf het begin implementeren van de logica kan lastig zijn, zoals beschreven in dit bericht over fallbacks van lettertypen . Gelukkig zijn er al verschillende toolopties beschikbaar om dit gemakkelijker te maken tijdens het ontwikkelen van apps.
Hoe lettertype-fallbacks te optimaliseren met Next.js
Next.js biedt een ingebouwde manier om fallback-lettertypeoptimalisatie mogelijk te maken. Deze functie is standaard ingeschakeld wanneer u lettertypen laadt met behulp van de component @next/font .
De component @next/font is geïntroduceerd in Next.js versie 13. De component biedt een API om Google Fonts of aangepaste lettertypen in uw pagina's te importeren en bevat ingebouwde automatische zelfhosting van lettertypebestanden.
Bij gebruik worden de fallback-lettertypestatistieken automatisch berekend en in het CSS-bestand geïnjecteerd.
Als u bijvoorbeeld een Roboto-lettertype gebruikt, definieert u dit doorgaans als volgt in 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;
}
body {
font-family: Roboto;
}
Migreren naar volgend/lettertype:
Verplaats de Roboto-lettertypedeclaratie naar uw Javascript door de 'Roboto'-functie van 'next/font' te importeren. De retourwaarde van de functie is een klassenaam die u kunt gebruiken in uw componentsjabloon. Vergeet niet om
display: swap
naar het configuratieobject om de functie in te schakelen.import { Roboto } from '@next/font/google'; const roboto = Roboto({ weight: '400', subsets: ['latin'], display: 'swap' // Using display swap automatically enables the feature })
Gebruik in uw component de gegenereerde klassenaam:
javascript export default function RootLayout({ children }: { children: React.ReactNode; }) { return ( <html lang="en" className={roboto.className}> <body>{children}</body> </html> ); }
De aanpassingsFontFallback -configuratieoptie:
Voor @next/font/google
: een Booleaanse waarde die instelt of er een automatisch fallback-lettertype moet worden gebruikt om de cumulatieve lay-outverschuiving te verminderen. De standaardwaarde is waar. Next.js stelt uw reservelettertype automatisch in op Arial
of Times New Roman
afhankelijk van het lettertype (respectievelijk schreefloos en schreefloos).
Voor @next/font/local
: Een tekenreeks of een Booleaanse false-waarde die instelt of een automatisch fallback-lettertype moet worden gebruikt om de cumulatieve lay-outverschuiving te verminderen. De mogelijke waarden zijn Arial
, Times New Roman
of false
. De standaardinstelling is Arial
. Als u een schreeflettertype wilt gebruiken, kunt u overwegen deze waarde in te stellen op Times New Roman
.
Een andere optie voor Google-lettertypen
Als het gebruik van de next/font
component geen optie is, is een andere benadering om deze functie met Google Fonts te gebruiken via de optimizeFonts
vlag. Next.js heeft de optimizeFonts-functie al standaard ingeschakeld. Met deze functie wordt de CSS van Google Font in het HTML-antwoord opgenomen. Verder kunt u de functie voor het aanpassen van lettertype-fallbacks inschakelen door de experimental.adjustFontFallbacksWithSizeAdjust
-vlag in uw next.config.js in te stellen, zoals weergegeven in het volgende fragment:
// In next.config.js
module.exports = {
experimental: {
adjustFontFallbacksWithSizeAdjust: true,
},
}
Opmerking : er zijn geen plannen om deze functie te ondersteunen met de nieuw geïntroduceerde app
directory. Op de lange termijn is het ideaal om next/font
te gebruiken.
Hoe u lettertype-fallbacks kunt aanpassen met Nuxt
@nuxtjs/fontaine is een module voor het Nuxt.js-framework dat automatisch de metrische waarden van het fallback-lettertype berekent en de fallback @font-face
CSS genereert.
Schakel de module in door @nuxtjs/fontaine
toe te voegen aan uw modulesconfiguratie:
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
modules: ['@nuxtjs/fontaine'],
})
Als u Google Fonts gebruikt of geen @font-face
declaratie voor een lettertype heeft, kunt u deze als extra opties declareren.
In de meeste gevallen kan de module de @font-face
regels uit uw CSS lezen en automatisch de details afleiden, zoals de lettertypefamilie, de fallback-lettertypefamilie en het weergavetype.
Als het lettertype is gedefinieerd op een plaats die niet door de module kan worden gevonden, kunt u de metrische gegevens doorgeven zoals weergegeven in het volgende codefragment.
export default defineNuxtConfig({
modules: ['@nuxtjs/fontaine'],
fontMetrics: {
fonts: ['Inter', { family: 'Some Custom Font', src: '/path/to/custom/font.woff2' }],
},
})
De module scant automatisch uw CSS om de @font-face-declaraties te lezen en genereert de fallback @font-face-regels.
@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%;
}
U kunt nu Roboto override
gebruiken als reservelettertype in uw CSS, zoals weergegeven in het volgende voorbeeld
:root {
font-family: 'Roboto';
/* This becomes */
font-family: 'Roboto', 'Roboto override';
}
Zelf de CSS genereren
Op zichzelf staande bibliotheken kunnen u ook helpen bij het genereren van de CSS voor noodaanpassingen van de lettergrootte.
Fontaine-bibliotheek gebruiken
Als u Nuxt of Next.js niet gebruikt, kunt u Fontaine gebruiken. Fontaine is de onderliggende bibliotheek die @nuxtjs/fontaine aanstuurt. U kunt deze bibliotheek in uw project gebruiken om automatisch fallback-font-CSS te injecteren met behulp van Vite- of Webpack-plug-ins.
Stel je voor dat je een Roboto-lettertype hebt gedefinieerd in het CSS-bestand:
@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 biedt Vite- en Webpack- transformatoren die eenvoudig in de bouwketen kunnen worden aangesloten. Schakel de plug-in in zoals weergegeven in het volgende JavaScript.
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
}
Als u Vite gebruikt, voegt u de plug-in als volgt toe: javascript // Vite export default { plugins: [FontaineTransform.vite(options)] }
Als u Webpack gebruikt, schakelt u dit als volgt in:
// Webpack
export default {
plugins: [FontaineTransform.webpack(options)]
}
De module scant automatisch uw bestanden om de @font-face-regels te wijzigen: 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%; }
U kunt nu Roboto override
gebruiken als uw reservelettertype in CSS. css :root { font-family: 'Roboto'; /* This becomes */ font-family: 'Roboto', 'Roboto override'; }
Met behulp van de Capsize-bibliotheek
Als u Next.js, Nuxt, Webpack of Vite niet gebruikt, is een andere optie het gebruik van de Capsize-bibliotheek om de fallback-CSS te genereren.
Nieuwe createFontStack- api
De API maakt deel uit van het @capsize/core pakket genaamd createFontStack
, dat een reeks lettertypestatistieken accepteert in dezelfde volgorde als waarin u uw lettertypestapel zou specificeren (de eigenschap font-family
).
U kunt hier de documentatie over het gebruik van Capsize raadplegen.
Voorbeeld
Beschouw het volgende voorbeeld: Het gewenste weblettertype is Lobster, terugvallend op Helvetica Neue en vervolgens Arial. In CSS, font-family: Lobster, 'Helvetica Neue', Arial
.
Importeer createFontStack vanuit het kernpakket:
import { createFontStack } from '@capsizecss/core';
Importeer de lettertypestatistieken voor elk van de gewenste lettertypen (zie Lettertypestatistieken hierboven):
javascript import lobster from '@capsizecss/metrics/lobster'; import helveticaNeue from '@capsizecss/metrics/helveticaNeue'; import arial from '@capsizecss/metrics/arial';`
Maak uw lettertypestapel, geef de statistieken door als een array en gebruik dezelfde volgorde als u zou doen via de font-family CSS-eigenschap.
javascript const { fontFamily, fontFaces } = createFontStack([ lobster, helveticaNeue, arial, ]);
Dit retourneert het volgende:
{
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%;
}
}
]
}
U moet de fontFamily- en fontFaces-code aan uw CSS toevoegen. De volgende code laat zien hoe u deze kunt implementeren in een CSS-stijlblad of binnen een <style>
-blok.
<style type="text/css">
.heading {
font-family:
}
</style>
Dit levert de volgende CSS op:
.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%;
}
U kunt ook het pakket @capsize/metrics gebruiken om de overschrijvingswaarden te berekenen en deze zelf op de CSS toepassen.
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));
Dankbetuigingen
Heldenafbeelding door Alexander Andrews op Unsplash .