เว็บไซต์ที่โหลดแบบอักษรโดยใช้ font-display: swap (แสดงแบบอักษรสลับ) มักเกิดจากการเปลี่ยนเลย์เอาต์ (CLS) เมื่อแบบอักษรของเว็บโหลดขึ้นและมีการสลับกับแบบอักษรสำรอง
คุณป้องกัน CLS ได้โดยการปรับขนาดแบบอักษรสำรองให้ตรงกับของแบบอักษรหลัก พร็อพเพอร์ตี้ เช่น size-adjust
, ascent-override
, descent-override
และ line-gap-override
ในกฎ @font-face
จะช่วยลบล้างเมตริกของแบบอักษรสำรอง ซึ่งช่วยให้นักพัฒนาแอปควบคุมวิธีแสดงแบบอักษรได้มากขึ้น อ่านข้อมูลเพิ่มเติมเกี่ยวกับแบบอักษรสำรองและคุณสมบัติการลบล้างได้ในโพสต์นี้ นอกจากนี้คุณยังสามารถดูการนำเทคนิคนี้ไปใช้งานได้ในการสาธิตนี้
บทความนี้จะสำรวจวิธีใช้การปรับขนาดแบบอักษรในเฟรมเวิร์ก Next.js และ Nuxt.js เพื่อสร้าง CSS แบบอักษรสำรองและลด CLS นอกจากนี้ยังสาธิตวิธีสร้างแบบอักษรสำรองโดยใช้เครื่องมือตัดแบบข้ามส่วน เช่น Fontaine และ Capsize ด้วย
ที่มา
font-display: swap โดยทั่วไปจะใช้เพื่อป้องกัน FOIT (Flash ของข้อความที่มองไม่เห็น) และเพื่อแสดงเนื้อหาบนหน้าจอได้เร็วขึ้น ค่าของ swap
จะบอกเบราว์เซอร์ว่าข้อความที่ใช้แบบอักษรควรแสดงทันทีโดยใช้แบบอักษรของระบบและจะแทนที่แบบอักษรของระบบเมื่อแบบอักษรที่กำหนดเองพร้อมใช้งานแล้วเท่านั้น
ปัญหาใหญ่ที่สุดของ swap
คือเอฟเฟกต์ที่น่าตกใจ ซึ่งความแตกต่างระหว่างขนาดตัวอักษรของแบบอักษรทั้ง 2 แบบจะทําให้เนื้อหาบนหน้าจอเลื่อนไปเรื่อยๆ ซึ่งทำให้คะแนน CLS ต่ำ โดยเฉพาะเว็บไซต์ที่มีข้อความจำนวนมาก
รูปภาพต่อไปนี้แสดงตัวอย่างปัญหา รูปภาพแรกใช้ font-display: swap
โดยไม่พยายามปรับขนาดแบบอักษรสำรอง บทความที่ 2 แสดงให้เห็นว่าการปรับขนาดโดยใช้กฎ @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 เปิดตัวใน Next.js เวอร์ชัน 13 คอมโพเนนต์ดังกล่าวมี 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 หรือไม่ ค่าเริ่มต้นคือ True Next.js จะตั้งค่าแบบอักษรสำรองของคุณเป็น Arial
หรือ Times New Roman
โดยอัตโนมัติโดยขึ้นอยู่กับประเภทแบบอักษร (serif กับ sans-serif ตามลำดับ)
สำหรับ @next/font/local
: สตริงหรือค่าบูลีนเท็จที่กำหนดว่าควรใช้แบบอักษรสำรองอัตโนมัติเพื่อลด Cumulative Layout Shift ค่าที่เป็นไปได้คือ Arial
, Times New Roman
หรือ false
ค่าเริ่มต้นคือ Arial
หากต้องการใช้แบบอักษร Serif ลองตั้งค่านี้เป็น Times New Roman
อีกตัวเลือกหนึ่งสำหรับ Google Fonts
หากไม่สามารถใช้คอมโพเนนต์ next/font
วิธีอื่นๆ ในการใช้ฟีเจอร์นี้กับ Google Fonts คือการใช้แฟล็ก optimizeFonts
Next.js มีการเปิดใช้ฟีเจอร์ OptimizeFonts เป็นค่าเริ่มต้นอยู่แล้ว ฟีเจอร์นี้จะรวม Google Font CSS ไว้ในการตอบสนอง HTML นอกจากนี้ คุณยังสามารถเปิดใช้ฟีเจอร์การปรับแบบอักษรสำรองได้โดยการตั้งค่าแฟล็ก experimental.adjustFontFallbacksWithSizeAdjust
ใน next.config.js ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
// In next.config.js
module.exports = {
experimental: {
adjustFontFallbacksWithSizeAdjust: true,
},
}
หมายเหตุ: เราไม่มีแผนที่จะรองรับฟีเจอร์นี้ด้วยไดเรกทอรี app
ที่เพิ่งเปิดตัว ในระยะยาว เราขอแนะนำให้ใช้ next/font
วิธีปรับแบบอักษรสำรองด้วย Nuxt
@nuxtjs/fontaine คือโมดูลสำหรับเฟรมเวิร์กของ 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
สมมติว่าคุณกำหนดแบบอักษร 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;
}
Fontaine มีตัวแปลงรหัส Vite และ Webpack ให้เสียบเข้ากับเชนบิลด์อย่างง่ายดาย เปิดใช้ปลั๊กอินตามที่แสดงใน 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)]
}
โมดูลจะสแกนไฟล์โดยอัตโนมัติเพื่อแก้ไขกฎ @แบบอักษร:
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
)
คุณสามารถดูเอกสารเกี่ยวกับการใช้ Capsize ที่นี่
ตัวอย่าง
ลองพิจารณาตัวอย่างต่อไปนี้: แบบอักษรเว็บที่ต้องการคือ Lobster โดยกลับไปใช้ Helvetica Neue และตามด้วย 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 ชุดแบบอักษร
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));
กิตติกรรมประกาศ
รูปภาพหลักโดย Alexander Andrews ใน Unsplash