Yazı tiplerini font-display: swap ile yükleyen siteler, web yazı tipi yüklendiğinde ve yedek yazı tipiyle değiştirildiğinde genellikle düzen kayması (CLS) sorunu yaşar.
Yedek yazı tipinin boyutlarını birincil yazı tipiyle eşleşecek şekilde ayarlayarak CLS'yi önleyebilirsiniz. @font-face
kuralındaki size-adjust
, ascent-override
, descent-override
ve line-gap-override
gibi özellikler, yedek yazı tipinin metriklerini geçersiz kılarak geliştiricilerin yazı tiplerinin nasıl görüntüleneceği üzerinde daha fazla kontrol sahibi olmasına yardımcı olabilir. Yedek yazı tipleri ve geçersiz kılma mülkleri hakkında daha fazla bilgiyi bu yayında bulabilirsiniz. Bu tekniğin çalışan bir uygulamasını bu demoda da görebilirsiniz.
Bu makalede, yedek yazı tipi CSS'sini oluşturmak ve CLS'yi azaltmak için yazı tipi boyutu ayarlarının Next.js ve Nuxt.js çerçevelerinde nasıl uygulandığı incelenmektedir. Ayrıca, Fontaine ve Capsize gibi kesişimsel araçları kullanarak yedek yazı tiplerini nasıl oluşturabileceğinizi de gösterir.
Arka plan
font-display: replace, genellikle FOIT'yi (görünmez metnin flaşı) önlemek ve içeriği ekranda daha hızlı görüntülemek için kullanılır. swap
değeri, tarayıcıya yazı tipini kullanan metnin bir sistem yazı tipiyle hemen görüntülenmesi ve sistem yazı tipinin yalnızca özel yazı tipi hazır olduğunda değiştirilmesi gerektiğini bildirir.
swap
ile ilgili en büyük sorun, iki yazı tipinin karakter boyutlarındaki farkın ekran içeriğinin kaymasına neden olduğu sarsıcı etkidir. Bu durum, özellikle çok fazla metin içeren web sitelerinde CLS puanlarının düşmesine neden olur.
Aşağıdaki resimlerde sorunun bir örneği gösterilmektedir. İlk resimde, yedek yazı tipinin boyutunu ayarlama girişimi olmadan font-display: swap
kullanılmaktadır. İkinci resimde, CSS @font-face
kuralı kullanılarak boyutun ayarlanmasının yükleme deneyimini nasıl iyileştirdiği gösterilmektedir.
Yazı tipi boyutunu ayarlamadan
body {
font-family: Inter, serif;
}
Yazı tipi boyutunu ayarladıktan sonra
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");
}
Yedek yazı tipinin boyutunu ayarlamak, yazı tipi yükleme düzeni kaymasını önlemek için etkili bir strateji olabilir ancak mantığı sıfırdan uygulamak, yazı tipi yedekleri hakkındaki bu yayında açıklandığı gibi zor olabilir. Neyse ki uygulama geliştirirken bu işlemi kolaylaştırmak için çeşitli araç seçenekleri mevcuttur.
Next.js ile yedek yazı tiplerini optimize etme
Next.js, yedek yazı tipi optimizasyonunu etkinleştirmek için yerleşik bir yöntem sağlar. Bu özellik, @next/font bileşenini kullanarak yazı tiplerini yüklediğinizde varsayılan olarak etkindir.
@next/font bileşeni, Next.js sürüm 13'te kullanıma sunuldu. Bileşen, Google Fonts'u veya özel yazı tiplerini sayfalarınıza aktarmak için bir API sağlar ve yazı tipi dosyalarının yerleşik, otomatik olarak barındırılmasını içerir.
Yedek yazı tipi metrikleri kullanıldığında otomatik olarak hesaplanır ve CSS dosyasına eklenir.
Örneğin, Roboto yazı tipi kullanıyorsanız bunu CSS'de genellikle aşağıdaki gibi tanımlarsınız:
@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;
}
Sonraki yazı tipine geçmek için:
"next/font" adresinden "Roboto" işlevini içe aktararak Roboto yazı tipi tanımını JavaScript'inize taşıyın. İşlevin döndürdüğü değer, bileşen şablonunuzda kullanabileceğiniz bir sınıf adı olur. Özelliği etkinleştirmek için yapılandırma nesnesine
display: swap
eklemeyi unutmayın.import { Roboto } from '@next/font/google'; const roboto = Roboto({ weight: '400', subsets: ['latin'], display: 'swap' // Using display swap automatically enables the feature })
Bileşeninizde oluşturulan sınıf adını kullanın:
javascript export default function RootLayout({ children }: { children: React.ReactNode; }) { return ( <html lang="en" className={roboto.className}> <body>{children}</body> </html> ); }
adjustFontFallback yapılandırma seçeneği:
@next/font/google
için: Cumulative Layout Shift'i azaltmak için otomatik yedek yazı tipinin kullanılıp kullanılmayacağını belirleyen bir boole değeri. Varsayılan değer, doğru değeridir. Next.js, yedek yazı tipinizi yazı tipi türüne (sırasıyla serif ve sans-serif) göre otomatik olarak Arial
veya Times New Roman
olarak ayarlar.
@next/font/local
için: Cumulative Layout Shift'i azaltmak için otomatik yedek yazı tipinin kullanılıp kullanılmayacağını belirleyen bir dize veya yanlış bir boole değeri. Olası değerler Arial
, Times New Roman
veya false
'dir. Varsayılan değer: Arial
. Serif yazı tipi kullanmak istiyorsanız bu değeri Times New Roman
olarak ayarlayabilirsiniz.
Google yazı tipleri için başka bir seçenek
next/font
bileşenini kullanmak mümkün değilse bu özelliği Google Fonts ile kullanmanın başka bir yolu da optimizeFonts
işaretçisidir. Next.js'de optimizeFonts özelliği varsayılan olarak etkindir. Bu özellik, Google yazı tipi CSS'sini HTML yanıtına satır içi olarak ekler. Ayrıca, next.config.js dosyanızda experimental.adjustFontFallbacksWithSizeAdjust
işaretini ayarlayarak aşağıdaki snippet'te gösterildiği gibi yazı tipi yedek ayarı özelliğini etkinleştirebilirsiniz:
// In next.config.js
module.exports = {
experimental: {
adjustFontFallbacksWithSizeAdjust: true,
},
}
Not: Bu özelliğin, yeni kullanıma sunulan app
dizini ile desteklenmesi planlanmamaktadır. Uzun vadede next/font
kullanmanızı öneririz.
Nuxt ile yazı tipi yedekleri nasıl ayarlanır?
@nuxtjs/fontaine, Nuxt.js çerçevesi için yedek yazı tipi metriği değerlerini otomatik olarak hesaplayan ve yedek @font-face
CSS'sini oluşturan bir modüldür.
Modül yapılandırmanıza @nuxtjs/fontaine
ekleyerek modülü etkinleştirin:
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
modules: ['@nuxtjs/fontaine'],
})
Google Fonts kullanıyorsanız veya yazı tipi için @font-face
bildiriminiz yoksa bunları ek seçenek olarak tanımlayabilirsiniz.
Çoğu durumda modül, CSS'nizdeki @font-face
kurallarını okuyabilir ve yazı tipi ailesi, yedek yazı tipi ailesi ve görüntüleme türü gibi ayrıntıları otomatik olarak tahmin edebilir.
Yazı tipi, modül tarafından bulunamayan bir yerde tanımlanmışsa metrik bilgilerini aşağıdaki kod snippet'inde gösterildiği gibi iletebilirsiniz.
export default defineNuxtConfig({
modules: ['@nuxtjs/fontaine'],
fontMetrics: {
fonts: ['Inter', { family: 'Some Custom Font', src: '/path/to/custom/font.woff2' }],
},
})
Modül, @font-face bildirimlerini okumak için CSS'nizi otomatik olarak tarar ve yedek @font-face kurallarını oluşturur.
@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%;
}
Artık CSS'nizde yedek yazı tipi olarak Roboto override
'ü kullanabilirsiniz. Aşağıdaki örnekte gösterildiği gibi
:root {
font-family: 'Roboto';
/* This becomes */
font-family: 'Roboto', 'Roboto override';
}
CSS'yi kendiniz oluşturma
Bağımsız kitaplıklar, yedek yazı tipi boyutu ayarlamaları için CSS oluşturmanıza da yardımcı olabilir.
Fontaine kitaplığını kullanma
Nuxt veya Next.js kullanmıyorsanız Fontaine'ı kullanabilirsiniz. Fontaine, @nuxtjs/fontaine'ı destekleyen temel kitaplıktır. Projenizde bu kitaplığı, Vite veya Webpack eklentilerini kullanarak yedek yazı tipi CSS'sini otomatik olarak eklemek için kullanabilirsiniz.
CSS dosyasında Roboto yazı tipi tanımlandığını varsayalım:
@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, derleme zincirine kolayca bağlanabilmeniz için Vite ve Webpack dönüştürücüleri sağlar. Eklentiyi aşağıdaki JavaScript'te gösterildiği gibi etkinleştirin.
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 kullanıyorsanız eklentiyi şu şekilde ekleyin:
javascript
// Vite
export default {
plugins: [FontaineTransform.vite(options)]
}
Webpack kullanıyorsanız aşağıdaki şekilde etkinleştirin:
// Webpack
export default {
plugins: [FontaineTransform.webpack(options)]
}
Modül, @font-face kurallarını değiştirmek için dosyalarınızı otomatik olarak tarar:
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%;
}
Artık CSS'de yedek yazı tipiniz olarak Roboto override
'ü kullanabilirsiniz.
css
:root {
font-family: 'Roboto';
/* This becomes */
font-family: 'Roboto', 'Roboto override';
}
Capsize kitaplığını kullanma
Next.js, Nuxt, Webpack veya Vite kullanmıyorsanız yedek CSS'yi oluşturmak için Capsize kitaplığını da kullanabilirsiniz.
Yeni createFontStack API'si
API, yazı tipi yığınınızı (font-family
mülkü) belirttiğiniz sırayla bir yazı tipi metriği dizisi kabul eden createFontStack
adlı @capsize/core paketinin bir parçasıdır.
Capsize'i kullanmayla ilgili dokümanları burada bulabilirsiniz.
Örnek
Aşağıdaki örneği inceleyin: İstenilen web yazı tipi Lobster, yedek olarak Helvetica Neue ve ardından Arial. CSS'de, font-family: Lobster, 'Helvetica Neue', Arial
.
createFontStack işlevini ana paketten içe aktarın:
import { createFontStack } from '@capsizecss/core';
İstediğiniz yazı tiplerinin her biri için yazı tipi metriklerini içe aktarın (yukarıdaki Yazı Tipi Metrikleri'ne bakın):
javascript import lobster from '@capsizecss/metrics/lobster'; import helveticaNeue from '@capsizecss/metrics/helveticaNeue'; import arial from '@capsizecss/metrics/arial';`
Yazı tipi ailesi CSS mülkündeki sıranızı kullanarak, metrikleri bir dizi olarak ileterek yazı tipi yığınınızı oluşturun.
javascript const { fontFamily, fontFaces } = createFontStack([ lobster, helveticaNeue, arial, ]);
Bu işlem aşağıdaki sonucu döndürür:
{
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%;
}
}
]
}
CSS'nize fontFamily ve fontFaces kodunu eklemeniz gerekir. Aşağıdaki kodda, bu özelliğin bir CSS stil sayfasında veya <style>
bloğunda nasıl uygulanacağı gösterilmektedir.
<style type="text/css">
.heading {
font-family:
}
</style>
Bu işlem, aşağıdaki CSS'yi oluşturur:
.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%;
}
Ayrıca, geçersiz kılma değerlerini hesaplamak ve CSS'ye kendiniz uygulamak için @capsize/metrics paketini de kullanabilirsiniz.
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));