באתרים שנטענים בגופנים עם האפשרות font-display: exchange יש לעיתים קרובות שינוי בפריסה (CLS) כשגופן האינטרנט נטען ומוחלף בגופן החלופי.
כדי למנוע CLS, צריך להתאים את המידות של הגופן החלופי כך שיתאימו לגופן הראשי. מאפיינים כמו size-adjust
, ascent-override
, descent-override
ו-line-gap-override
בכלל @font-face
יכולים לשנות את המדדים של גופן חלופי ולתת למפתחים שליטה רבה יותר על אופן ההצגה של גופנים. בפוסט הזה אפשר לקרוא מידע נוסף על חלופות של גופנים ועל מאפייני ברירת המחדל. אפשר גם לראות איך השיטה הזו מיושמת באופן פעיל בהדגמה הזו.
המאמר הזה מסביר איך התאמות של גודל גופן מיושמות במסגרות Next.js ו-Nixt.js כדי ליצור את ה-CSS החלופי של הגופן ולהפחית את ה-CLS. היא גם מדגימה איך ליצור גופנים חלופיים באמצעות כלים לחיתוך פריטים, כמו Fontaine ו-Capsize.
רקע
הפונקציה font-display: switch משמשת בדרך כלל למניעת FOIT (הבהוב של טקסט בלתי נראה) ולהצגה מהירה יותר של תוכן במסך. הערך של swap
מורה לדפדפן שהטקסט שבו נעשה שימוש בגופן צריך להיות מוצג מיד באמצעות גופן מערכת ולהחליף את גופן המערכת רק כאשר הגופן המותאם אישית מוכן.
הבעיה הגדולה ביותר ב-swap
היא האפקט הצורם, שבו ההבדל בגודל התווים בשני הגופנים גורם להזזה של תוכן המסך. המצב הזה מוביל לציוני CLS נמוכים, במיוחד באתרים עם הרבה טקסט.
התמונות הבאות מציגות דוגמה לבעיה. בתמונה הראשונה נעשה שימוש ב-font-display: swap
ללא ניסיון להתאים את גודל הגופן החלופי. השנייה מראה איך התאמת הגודל באמצעות הכלל @font-face
של CSS משפרת את חוויית הטעינה.
בלי לשנות את גודל הגופן
body {
font-family: Inter, serif;
}
אחרי שינוי גודל הגופן
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");
}
שינוי הגודל של הגופן החלופי יכול להיות אסטרטגיה יעילה למניעת שינוי של פריסת הגופנים, אבל יישום הלוגיקה מההתחלה יכול להיות מסובך, כפי שמתואר בפוסט הזה על חלופות של גופנים. למרבה המזל, קיימים מספר אפשרויות של כלים שמקלים על תהליך הפיתוח של אפליקציות.
איך מבצעים אופטימיזציה לחלופות של גופנים ב-Next.js
Next.js מספק דרך מובנית להפעלת אופטימיזציה של גופן חלופי. התכונה הזו מופעלת כברירת מחדל כשטוענים גופנים באמצעות הרכיב @next/font.
הרכיב @next/font הושק בגרסה 13 של Next.js. הרכיב מספק ממשק API לייבוא Google Fonts או גופנים מותאמים אישית אל הדפים שלכם, והוא כולל אירוח עצמי מובנה של קובצי גופנים.
כשמשתמשים בהם, מדדי הגופן החלופי מחושבים באופן אוטומטי ומוחדרים לקובץ ה-CSS.
לדוגמה, אם משתמשים בגופן Roboto, מגדירים אותו ב-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;
}
כדי לעבור לפריט הבא/גופן:
כדי להעביר את הצהרת הגופן Roboto ל-JavaScript, יש לייבא את הפונקציה Roboto מהכלי 'next/font'. הערך המוחזר של הפונקציה יהיה שם מחלקה שניתן להשתמש בו בתבנית הרכיב. חשוב לזכור להוסיף את
display: swap
לאובייקט ההגדרה כדי להפעיל את התכונה.import { Roboto } from '@next/font/google'; const roboto = Roboto({ weight: '400', subsets: ['latin'], display: 'swap' // Using display swap automatically enables the feature })
ברכיב, משתמשים בשם המחלקה שנוצר:
javascript export default function RootLayout({ children }: { children: React.ReactNode; }) { return ( <html lang="en" className={roboto.className}> <body>{children}</body> </html> ); }
אפשרות ההגדרה adjustFontFallback:
עבור @next/font/google
: ערך בוליאני שמגדיר אם יש להשתמש בגופן חלופי אוטומטי כדי להקטין את Cumulative Layout Shift (CLS). ברירת המחדל היא TRUE. Next.js מגדיר באופן אוטומטי את גופן הגיבוי ל-Arial
או ל-Times New Roman
, בהתאם לסוג הגופן (serif לעומת Sans Serif בהתאמה).
עבור @next/font/local
: מחרוזת או ערך בוליאני שמגדיר אם יש להשתמש בגופן חלופי אוטומטי כדי להקטין את Cumulative Layout Shift (CLS). הערכים האפשריים הם Arial
, Times New Roman
או false
. ברירת המחדל היא Arial
. אם ברצונך להשתמש בגופן serif, כדאי להגדיר את הערך הזה כ-Times New Roman
.
אפשרות נוספת לגופנים של Google
אם אין אפשרות להשתמש ברכיב next/font
, גישה נוספת לשימוש בתכונה הזו עם Google Fonts היא באמצעות הדגל optimizeFonts
. התכונה OptimizeFonts כבר מופעלת כברירת מחדל ב-Next.js. התכונה הזו ממקמת את ה-CSS של Google Font בתגובת ה-HTML. אפשר גם להפעיל את תכונת ההתאמה של החלופות הפונטיות על ידי הגדרת הדגל experimental.adjustFontFallbacksWithSizeAdjust
בקובץ next.config.js, כפי שמוצג בקטע הקוד הבא:
// In next.config.js
module.exports = {
experimental: {
adjustFontFallbacksWithSizeAdjust: true,
},
}
הערה: אין תוכנית לתמוך בתכונה הזו עם גרסת הבטא החדשה של app
. בטווח הארוך, מומלץ להשתמש ב-next/font
.
איך לשנות חלופות של גופנים באמצעות Nuxt
@nuxtjs/fontaine הוא מודול ל-framework של Nuxt.js שמחשב באופן אוטומטי את ערכי המדדים של הגופן החלופי ויוצר את ה-CSS החלופי @font-face
.
כדי להפעיל את המודול, מוסיפים @nuxtjs/fontaine
להגדרת המודולים:
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
modules: ['@nuxtjs/fontaine'],
})
אם נעשה שימוש ב-Google Fonts או שאין לך הצהרת @font-face
לגופן, אפשר להצהיר עליהם כאפשרויות נוספות.
ברוב המקרים, המודול יכול לקרוא את הכללים של @font-face
מה-CSS ולהסיק באופן אוטומטי פרטים כמו משפחת הגופנים, משפחת הגופנים החלופית וסוג התצוגה.
אם הגופן מוגדר במקום שאינו גלוי למודול, ניתן להעביר את מידע הערכים כפי שמוצג בקטע הקוד הבא.
export default defineNuxtConfig({
modules: ['@nuxtjs/fontaine'],
fontMetrics: {
fonts: ['Inter', { family: 'Some Custom Font', src: '/path/to/custom/font.woff2' }],
},
})
המודול סורק באופן אוטומטי את ה-CSS כדי לקרוא את הצהרות ה- @font-face ויוצר את כללי החלופה של @font-face.
@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%;
}
עכשיו אפשר להשתמש ב-Roboto override
כגופן החלופי ב-CSS, כפי שמוצג בדוגמה הבאה
:root {
font-family: 'Roboto';
/* This becomes */
font-family: 'Roboto', 'Roboto override';
}
יצירת שירות ה-CSS בעצמכם
אפשר גם להשתמש בספריות עצמאיות כדי ליצור CSS להתאמות של גודל גופן חלופי.
שימוש בספריית Fontaine
אם אתם לא משתמשים ב-Nuxt או ב-Next.js, אפשר להשתמש ב-Fontaine. Fontaine הוא הספרייה הבסיסית שמפעילה את @nuxtjs/fontaine. אפשר להשתמש בספרייה הזו בפרויקט כדי להחדיר באופן אוטומטי גופן חלופי ב-CSS באמצעות יישומי הפלאגין Vite או Webpack.
נניח שבקובץ ה-CSS מוגדר גופן Roboto:
@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 מספק את הטרנספורמרים של Vite ו-Webpack כדי להתחבר לשרשרת ה-build בקלות. מפעילים את הפלאגין כפי שמוצג ב-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
}
אם משתמשים ב-Vite, מוסיפים את הפלאגין באופן הבא:
javascript
// Vite
export default {
plugins: [FontaineTransform.vite(options)]
}
אם משתמשים ב-Webpack, יש להפעיל אותו באופן הבא:
// Webpack
export default {
plugins: [FontaineTransform.webpack(options)]
}
המודול יסרוק באופן אוטומטי את הקבצים שלכם כדי לשנות את כללי ה- @font-face:
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%;
}
עכשיו אתם יכולים להשתמש ב-Roboto override
כגופן חלופי ב-CSS.
css
:root {
font-family: 'Roboto';
/* This becomes */
font-family: 'Roboto', 'Roboto override';
}
שימוש בספריית Capsize
אם אתם לא משתמשים ב-Next.js , Nuxt , Webpack או Vite, אפשרות נוספת היא להשתמש בספריית Capsize כדי ליצור את ה-CSS החלופי.
ממשק api חדש של createFontStack
ה-API הוא חלק מחבילת @capsize/core שנקראת createFontStack
, שבה אפשר להשתמש במערך של מדדי גופנים באותו סדר שבו מציינים את מקבץ הגופנים (המאפיין font-family
).
כאן אפשר לעיין במסמכי התיעוד בנושא שימוש באותיות רישיות.
דוגמה
נתייחס לדוגמה הבאה: גופן האינטרנט הרצוי הוא Lobster, עם חזרה ל-H התראה Newe ולאחר מכן Arial. ב-CSS, font-family: Lobster, 'Helvetica Neue', Arial
.
מייבאים את createFontStack מחבילת הליבה:
import { createFontStack } from '@capsizecss/core';
מייבאים את מדדי הגופנים לכל אחד מהגופנים הרצויים (ניתן לעיין ב'מדדי גופנים למעלה'):
javascript import lobster from '@capsizecss/metrics/lobster'; import helveticaNeue from '@capsizecss/metrics/helveticaNeue'; import arial from '@capsizecss/metrics/arial';`
יוצרים את מקבץ הגופנים ומעבירים את המדדים כמערך, באותו סדר שבו משתמשים במאפיין ה-CSS מסוג font-family.
javascript const { fontFamily, fontFaces } = createFontStack([ lobster, helveticaNeue, arial, ]);
הפעולה הזו תחזיר את הערך הבא:
{
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%;
}
}
]
}
צריך להוסיף את הקוד fontFamily ואת הקוד fontFaces ל-CSS. הקוד הבא מראה כיצד ליישם אותה בגיליון סגנונות CSS, או בתוך בלוק <style>
.
<style type="text/css">
.heading {
font-family:
}
</style>
הפעולה הזו תיצור את ה-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%;
}
אפשר גם להשתמש בחבילה @capsize/metrics כדי לחשב את ערכי הביטול, ולהחיל אותם על ה-CSS בעצמכם.
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));
אישורים
תמונה ראשית (Hero) מאת אלכסנדר אנדרוז בתוכנית Unense.