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

Janicklas Ralph James'in hikayeleri
Janicklas Ralph James

Yazı tiplerini font-display: change ile yükleyen sitelerde, web yazı tipi yüklendiğinde ve yedek yazı tipiyle değiştirildiğinde genellikle bir düzen kayması (CLS) olur.

Yedek yazı tipinin boyutlarını birincil yazı tipinin boyutuyla 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ı tipi metriklerinin geçersiz kılınmasına yardımcı olabilir. Böylece geliştiriciler, yazı tiplerinin görüntülenme şekli üzerinde daha fazla kontrol sahibi olabilir. Yedek yazı tipleri ve geçersiz kılma özellikleri hakkında daha fazla bilgiyi bu yayında bulabilirsiniz. Bu demoda, söz konusu tekniğin çalışan bir uygulamasını da görebilirsiniz.

Bu makalede, yedek yazı tipi CSS'si oluşturmak ve CLS'yi azaltmak için yazı tipi boyutu ayarlamalarının Next.js ve Nuxt.js çerçevelerinde nasıl uygulandığı açıklanmaktadır. Ayrıca, Fontaine ve Capsize gibi çapraz kesme araçlarını kullanarak nasıl yedek yazı tipleri oluşturacağınızı göstermektedir.

Arka plan

font-display: change, genellikle FOIT'i (görünmez metnin Flash'ı) ö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ı tipi kullanılarak 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 rahatsız edici etkidir. İki yazı tipinin karakter boyutları arasındaki fark, ekran içeriğinin değişmesine neden olur. Bu durum, özellikle çok fazla metin içeren web sitelerinde CLS puanlarının düşük olmasına yol açar.

Aşağıdaki resimlerde sorunun bir örneği gösterilmektedir. İlk resimde, yedek yazı tipinin boyutunu ayarlama girişiminde bulunulmadan font-display: swap kullanılmıştır. İkincisi ise CSS @font-face kuralı kullanılarak boyutu ayarlamanın yükleme deneyimini nasıl iyileştirdiğini gösterir.

Yazı tipi boyutu değiştirilmeden

body {
  font-family: Inter, serif;
}
Yazı tipi ve boyutu aniden değişen ve sarsıcı bir etkiye neden olan metinler.

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");
}
Yumuşak bir şekilde farklı bir yazı tipine geçen metin.

Yedek yazı tipinin boyutunu ayarlamak, yazı tipi yükleme düzen kaymasını önlemek için etkili bir strateji olabilir, ancak yazı tipi yedekleriyle ilgili bu yayında açıklandığı gibi, mantığı sıfırdan uygulamak zor olabilir. Neyse ki uygulama geliştirirken bunu kolaylaştırmak için zaten çeşitli araç seçenekleri mevcuttur.

Next.js ile yedek yazı tipleri nasıl optimize edilir?

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

@next/font bileşeni Next.js sürüm 13'te 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 ve otomatik olarak kendiliğinden 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 bunu genellikle CSS'de 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;
}

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

  1. "next/font" parametresinden "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ı ayarlayan boole değeridir. Varsayılan, doğru değeridir. Next.js, yazı tipi türüne bağlı olarak yedek yazı tipinizi otomatik olarak Arial veya Times New Roman değerine ayarlar (sırasıyla serif ve 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'dir. Varsayılan değer: Arial. Seri yazı tipi kullanmak istiyorsanız bu değeri Times New Roman olarak ayarlamayı düşünün.

Google Fonts için başka bir seçenek

next/font bileşenini kullanmak mümkün değilse bu özelliği Google Fonts ile kullanmaya yönelik bir başka yaklaşım da optimizeFonts işaretini kullanmaktır. Next.js'de, optimizeFonts özelliği varsayılan olarak zaten etkindir. Bu özellik, HTML yanıtında Google Yazı Tipi CSS'sini satır içine alır. Ayrıca aşağıdaki snippet'te gösterildiği gibi, next.config.js dosyanızda experimental.adjustFontFallbacksWithSizeAdjust işaretini ayarlayarak yedek yazı tipi ayarlama özelliğini etkinleştirebilirsiniz:

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

Not: Bu özelliğin, yeni kullanıma sunulan app dizinde desteklenmesine yönelik bir plan bulunmamaktadır. Uzun vadede, next/font kullanmak için idealdir.

Nuxt ile yedek yazı tipini ayarlama

@nuxtjs/fontaine, yedek yazı tipi metrik değerlerini otomatik olarak hesaplayan ve yedek @font-face CSS'si oluşturan Nuxt.js çerçevesi için 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'u kullanıyorsanız veya bir yazı tipi için @font-face beyanınız yoksa bunları ek seçenekler olarak belirtebilirsiniz.

Modül çoğu durumda CSS'nizden @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ımlanırsa metrik bilgilerini aşağıdaki kod snippet'inde gösterildiği gibi aktarabilirsiniz.

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 Roboto override öğesini CSS'de yedek yazı tipi olarak 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'i kullanabilirsiniz. Fontaine, @nuxtjs/fontaine'i 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 tanımlı bir Roboto yazı tipinizin 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 takılması için Vite ve Webpack dönüştürücüleri sağlar ve 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 gibi 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 öğesini 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ı da kullanabilirsiniz.

Yeni createFontStack API

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

Capsize'ı kullanma ile ilgili dokümanlara buradan bakabilirsiniz.

Örnek

Şu örneği ele alalım: İstenen web yazı tipi Lobster'dır ve Helvetica Neue ve ardından Arial'a döner. CSS'de, font-family: Lobster, 'Helvetica Neue', Arial.

  1. Temel paketten createFontStack'i 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şturun ve metrikleri, font-family CSS mülkündeki sıralamayı kullanarak bir dizi olarak iletin. javascript const { fontFamily, fontFaces } = createFontStack([ lobster, helveticaNeue, arial, ]);

Bu, şunu 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 kod, bu özelliğin bir CSS stil sayfasında veya <style> bloğunda nasıl uygulanacağını gösterir.

<style type="text/css">
  .heading {
    font-family: 
  }

  
</style>

Bu, 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 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 lokomotif resmi.