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

Janicklas Ralph James
Janicklas Ralph James

font-display: change kodunu içeren yazı tipleri yükleyen sitelerde, web yazı tipi yüklendiğinde ve yerine yedek yazı tipi kullanıldığında genellikle bir düzen kayması (CLS) yaşanır.

Yedek yazı tipinin boyutlarını, birincil yazı tipinin boyutlarıyla eşleşecek şekilde ayarlayarak CLS'yi engelleyebilirsiniz. @font-face kuralındaki size-adjust, ascent-override, descent-override ve line-gap-override gibi özellikler, yedek yazı tipi metriklerinin geçersiz kılınmasına yardımcı olabilir. Bu sayede geliştiriciler, yazı tiplerinin görüntülenme şekli üzerinde daha fazla kontrol sahibi olabilir. Yazı tipi yedekleri ve geçersiz kılma özellikleri hakkında daha fazla bilgiyi bu yayında bulabilirsiniz. Ayrıca, bu demoda bu tekniğin çalışan bir uygulamasını görebilirsiniz.

Bu makalede, yedek yazı tipi CSS'sini oluşturmak ve CLS'yi azaltmak için Next.js ve Nuxt.js çerçevelerinde yazı tipi boyutu ayarlamalarının nasıl uygulandığı açıklanmaktadır. Ayrıca Fontaine ve Capsize gibi çapraz kesme araçlarını kullanarak yedek yazı tiplerini nasıl oluşturabileceğinizi de öğrenebilirsiniz.

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ı arasındaki farkın ekran içeriğinin değişmesine neden olduğu rahatsız edici efekttir. 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 boyutu ayarlanmaya çalışılmadan font-display: swap kullanılmıştır. İkincisinde ise CSS @font-face kuralı kullanılarak boyutun düzenlenmesinin yükleme deneyimini nasıl iyileştirdiği gösterilmektedir.

Yazı tipi boyutunu ayarlamadan

body {
  font-family: Inter, serif;
}
Metinlerin yazı tipi ve boyutu aniden değiştiği için rahatsız edici bir efekt uygulanı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");
}
Düzgün bir şekilde farklı bir yazı tipine geçiş yapan metinler.

Yedek yazı tipinin boyutunu ayarlamak, yazı tipi yükleme düzeni kaymasını önlemek için etkili bir strateji olabilir. Ancak mantığın sıfırdan uygulanması zor olabilir. Yazı tipi yedekleriyle ilgili bu gönderide açıklandığı gibi hatalar yapılabilir. Neyse ki uygulama geliştirirken bunu kolaylaştırmak için halihazırda çeşitli araç seçenekleri mevcuttur.

Next.js ile yazı tipi yedeklerini optimize etme

Next.js, yedek yazı tipi optimizasyonunu etkinleştirmek için yerleşik bir yol sağlar. @next/font bileşenini kullanarak yazı tiplerini yüklediğinizde bu özellik varsayılan olarak etkinleştirilir.

@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.

Kullanıldığında yedek yazı tipi metrikleri otomatik olarak hesaplanır ve CSS dosyasına eklenir.

Örneğin, Roboto yazı tipi kullanıyorsanız yazı tipini genellikle CSS'de şu şekilde 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;
}

Sonrakine/yazı tipine geçmek için:

  1. "next/font" bölümünden "Roboto" işlevini içe aktararak Roboto yazı tipi bildirimini JavaScript'inize taşıyın. İşlevin döndürdüğü değer, bileşen şablonunuzda yararlanabileceğiniz bir sınıf adı olacaktır. Ö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 boole değeri. Varsayılan değer, doğru değeridir. Next.js, yazı tipi türüne bağlı olarak yedek yazı tipinizi otomatik olarak Arial veya Times New Roman olarak ayarlar (sırasıyla serif veya sans-serif).

@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 boole false değeri. Olası değerler: Arial, Times New Roman veya false. Varsayılan değer: Arial. Serif yazı tipi kullanmak istiyorsanız bu değeri Times New Roman olarak ayarlayın.

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 başka bir yaklaşım da optimizeFonts işaretini kullanmaktır. Next.js'de optimizeFonts özelliği varsayılan olarak etkindir. Bu özellik, HTML yanıtında Google Yazı Tipi CSS'sini satır içi yapar. Ayrıca, aşağıdaki snippet'te gösterildiği gibi next.config.js'nizde experimental.adjustFontFallbacksWithSizeAdjust işaretini ayarlayarak yazı tipi yedeklerini ayarlama özelliğini etkinleştirebilirsiniz:

// In next.config.js
module.exports = {
 experimental: {
   adjustFontFallbacksWithSizeAdjust: true,
 },
}

Not: Yeni kullanıma sunulan app dir ile bu özelliğin desteklenmesi için bir plan yoktur. Uzun vadede, next/font kullanmak ideal olacaktır.

Nuxt ile yazı tipi yedeklerini ayarlama

@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 şekilde 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%;
}

Aşağıdaki örnekte gösterildiği gibi artık CSS'nizde yedek yazı tipi olarak Roboto override kullanabilirsiniz.

: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'i 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 tanımlanmış bir Roboto yazı tipiniz olduğunu düşünün:

@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 Roboto override'i CSS'de yedek yazı tipiniz olarak 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ı kullanabilirsiniz.

Yeni createFontStack API'si

API, createFontStack adlı @capsize/core paketinin bir parçasıdır. Bu paket, yazı tipi yığınınızı belirteceğiniz sırayla (font-family özelliği) bir dizi yazı tipi metriği kabul eder.

Capsize'ı kullanmayla ilgili belgelere buradan ulaşabilirsiniz.

Örnek

Şu örneği ele alalım: İstenen web yazı tipi Lobster'dır. Bu yazı tipinde Helvetica Neue, ardından GPC'ye geri dönülür. CSS'de, font-family: Lobster, 'Helvetica Neue', Arial.

  1. Temel paketten createFontStack'ı 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'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 ailesi CSS mülkündeki sıralamayı kullanarak, metrikleri bir dizi olarak ileterek yazı tipi yığınınızı oluşturun. javascript const { fontFamily, fontFaces } = createFontStack([ lobster, helveticaNeue, arial, ]);

Bu komut aşağıdakini 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 kod, bunu bir CSS stil sayfasına veya <style> bloğuna nasıl uygulayacağınızı gösterir.

<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%;
}

Geçersiz kılma değerlerini hesaplamak ve bunları 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));

Teşekkür

Alexander Andrews'un Unsplash'teki hero resim.