Yazı tipi yedekleri için çerçeve araçları

Janicklas Ralph James
Janicklas Ralph James

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: swap genellikle FOIT'i (Görünmez metnin yanıp sönmesi) önlemek ve içerikleri 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ı tipi kullanılarak hemen gösterilmesi gerektiğini ve sistem yazı tipinin yalnızca özel yazı tipi hazır olduğunda değiştirilmesi gerektiğini söyler.

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 metin ağırlıklı web siteleri için düşük CLS puanlarına 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 ayarlama

body {
  font-family: Inter, serif;
}
Yazı tipi ve boyutu aniden değişen metinler rahatsız edici bir etki yaratır.

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");
}
Farklı bir yazı tipine sorunsuz şekilde geçiş yapan metin.

Yedek yazı tipinin boyutunu ayarlamak, yazı tipi yükleme düzeni kaymasını önlemek için etkili bir strateji olabilir ancak yazı tipi yedekleri hakkındaki bu yayında açıklandığı gibi, mantığı sıfırdan uygulamak zor olabilir. Neyse ki uygulama geliştirirken bu süreci 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 13 sürümünde kullanıma sunulmuştur. Bileşen, Google yazı tiplerini veya özel yazı tiplerini sayfalarınıza aktarmak için bir API sağlar ve yazı tipi dosyalarının yerleşik otomatik kendi kendine barındırma özelliğini 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:

  1. "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
    })
    
  2. 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 true'dur. 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'tir. 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 kullanmak için optimizeFonts işaretçisini de kullanabilirsiniz. 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 metrik değerlerini otomatik olarak hesaplayan ve yedek @font-face CSS'yi 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 bir yazı tipi için @font-face beyanınız yoksa bunları ek seçenekler olarak belirtebilirsiniz.

Ç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. Vite veya Webpack eklentilerini kullanarak yedek yazı tipi CSS'sini otomatik olarak eklemek için projenizde bu kitaplığı 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, yapı zincirine kolayca bağlanmak 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.

  1. createFontStack işlevini ana paketten içe aktarın:

    import { createFontStack } from '@capsizecss/core';
    
  2. İstediğiniz yazı tiplerinin her biri için yazı tipi metriklerini içe aktarın (yukarıdaki Yazı Tipi Metrikleri bölümüne bakın): javascript import lobster from '@capsizecss/metrics/lobster'; import helveticaNeue from '@capsizecss/metrics/helveticaNeue'; import arial from '@capsizecss/metrics/arial';`

  3. Yazı tipi yığınınızı oluştururken metrikleri bir dizi olarak iletin. Bu işlemi, font-family CSS mülkü aracılığıyla yaptığınız gibi aynı sırayla yapın. 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%;
     }
   }
 ]
}

fontFamily ve fontFaces kodunu CSS'nize 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));