تحسين الخطوط

next/font سيقوم تلقائيًا بتحسين خطوطك (بما في ذلك الخطوط المخصصة) وإزالة طلبات الشبكة الخارجية لتحسين الخصوصية والأداء.

🎥 شاهد: تعلم المزيد عن استخدام next/fontYouTube (6 دقائق).

يتضمن next/font استضافة ذاتية تلقائية مدمجة لأي ملف خط. هذا يعني أنه يمكنك تحميل خطوط الويب بشكل مثالي دون أي تغيير في التخطيط، بفضل خاصية CSS size-adjust المستخدمة.

كما يسمح لك نظام الخطوط الجديد هذا باستخدام جميع خطوط جوجل بسهولة مع مراعاة الأداء والخصوصية. يتم تنزيل ملفات CSS والخطوط في وقت البناء واستضافتها ذاتيًا مع بقية مواردك الثابتة. لا يتم إرسال أي طلبات إلى جوجل من المتصفح.

خطوط جوجل

استضف أي خط من خطوط جوجل ذاتيًا تلقائيًا. يتم تضمين الخطوط في النشر وتقديمها من نفس النطاق كنشرك. لا يتم إرسال أي طلبات إلى جوجل من المتصفح.

ابدأ باستيراد الخط الذي ترغب في استخدامه من next/font/google كدالة. نوصي باستخدام الخطوط المتغيرة للحصول على أفضل أداء ومرونة.

import { Inter } from 'next/font/google'

// إذا كنت تحمل خطًا متغيرًا، لا تحتاج إلى تحديد وزن الخط
const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  )
}
import { Inter } from 'next/font/google'

// إذا كنت تحمل خطًا متغيرًا، لا تحتاج إلى تحديد وزن الخط
const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  )
}

إذا لم تتمكن من استخدام خط متغير، ستحتاج إلى تحديد وزن:

import { Roboto } from 'next/font/google'

const roboto = Roboto({
  weight: '400',
  subsets: ['latin'],
  display: 'swap',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={roboto.className}>
      <body>{children}</body>
    </html>
  )
}
import { Roboto } from 'next/font/google'

const roboto = Roboto({
  weight: '400',
  subsets: ['latin'],
  display: 'swap',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={roboto.className}>
      <body>{children}</body>
    </html>
  )
}

يمكنك تحديد أوزان و/أو أنماط متعددة باستخدام مصفوفة:

app/layout.js
const roboto = Roboto({
  weight: ['400', '700'],
  style: ['normal', 'italic'],
  subsets: ['latin'],
  display: 'swap',
})

معلومة مفيدة: استخدم شرطة سفلية (_) لأسماء الخطوط التي تحتوي على كلمات متعددة. مثلاً Roboto Mono يجب استيرادها كـ Roboto_Mono.

تحديد مجموعة فرعية

يتم تقسيم خطوط جوجل تلقائيًا. هذا يقلل حجم ملف الخط ويحسن الأداء. ستحتاج إلى تعريف أي من هذه المجموعات الفرعية تريد تحميلها مسبقًا. إذا فشلت في تحديد أي مجموعات فرعية بينما preload مضبوط على true، سيؤدي ذلك إلى تحذير.

يمكن القيام بذلك عن طريق إضافته إلى استدعاء الدالة:

const inter = Inter({ subsets: ['latin'] })
const inter = Inter({ subsets: ['latin'] })

راجع مرجع واجهة برمجة تطبيقات الخط لمزيد من المعلومات.

استخدام خطوط متعددة

يمكنك استيراد واستخدام خطوط متعددة في تطبيقك. هناك نهجان يمكنك اتباعهما.

النهج الأول هو إنشاء دالة مساعدة تصدر خطًا، تستورده، وتطبق className الخاص به حيثما يحتاج. هذا يضمن تحميل الخط مسبقًا فقط عند عرضه:

import { Inter, Roboto_Mono } from 'next/font/google'

export const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

export const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  display: 'swap',
})
import { Inter, Roboto_Mono } from 'next/font/google'

export const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

export const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  display: 'swap',
})
import { inter } from './fonts'

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" className={inter.className}>
      <body>
        <div>{children}</div>
      </body>
    </html>
  )
}
import { inter } from './fonts'

export default function Layout({ children }) {
  return (
    <html lang="en" className={inter.className}>
      <body>
        <div>{children}</div>
      </body>
    </html>
  )
}
import { roboto_mono } from './fonts'

export default function Page() {
  return (
    <>
      <h1 className={roboto_mono.className}>صفحتي</h1>
    </>
  )
}
import { roboto_mono } from './fonts'

export default function Page() {
  return (
    <>
      <h1 className={roboto_mono.className}>صفحتي</h1>
    </>
  )
}

في المثال أعلاه، سيتم تطبيق Inter عالميًا، ويمكن استيراد Roboto Mono وتطبيقه حسب الحاجة.

بدلاً من ذلك، يمكنك إنشاء متغير CSS واستخدامه مع حل CSS المفضل لديك:

import { Inter, Roboto_Mono } from 'next/font/google'
import styles from './global.css'

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
  display: 'swap',
})

const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  variable: '--font-roboto-mono',
  display: 'swap',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={`${inter.variable} ${roboto_mono.variable}`}>
      <body>
        <h1>تطبيقي</h1>
        <div>{children}</div>
      </body>
    </html>
  )
}
import { Inter, Roboto_Mono } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
  display: 'swap',
})

const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  variable: '--font-roboto-mono',
  display: 'swap',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={`${inter.variable} ${roboto_mono.variable}`}>
      <body>
        <h1>تطبيقي</h1>
        <div>{children}</div>
      </body>
    </html>
  )
}
app/global.css
html {
  font-family: var(--font-inter);
}

h1 {
  font-family: var(--font-roboto-mono);
}

في المثال أعلاه، سيتم تطبيق Inter عالميًا، وسيتم تنسيق أي علامات <h1> باستخدام Roboto Mono.

توصية: استخدم خطوط متعددة بحذر لأن كل خط جديد هو مورد إضافي يجب على العميل تنزيله.

الخطوط المحلية

استورد next/font/local وحدد src لملف الخط المحلي الخاص بك. نوصي باستخدام الخطوط المتغيرة للحصول على أفضل أداء ومرونة.

import localFont from 'next/font/local'

// يمكن وضع ملفات الخطوط داخل `app`
const myFont = localFont({
  src: './my-font.woff2',
  display: 'swap',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={myFont.className}>
      <body>{children}</body>
    </html>
  )
}
import localFont from 'next/font/local'

// يمكن وضع ملفات الخطوط داخل `app`
const myFont = localFont({
  src: './my-font.woff2',
  display: 'swap',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={myFont.className}>
      <body>{children}</body>
    </html>
  )
}

إذا كنت تريد استخدام ملفات متعددة لعائلة خط واحدة، يمكن أن يكون src مصفوفة:

const roboto = localFont({
  src: [
    {
      path: './Roboto-Regular.woff2',
      weight: '400',
      style: 'normal',
    },
    {
      path: './Roboto-Italic.woff2',
      weight: '400',
      style: 'italic',
    },
    {
      path: './Roboto-Bold.woff2',
      weight: '700',
      style: 'normal',
    },
    {
      path: './Roboto-BoldItalic.woff2',
      weight: '700',
      style: 'italic',
    },
  ],
})

راجع مرجع واجهة برمجة تطبيقات الخط لمزيد من المعلومات.

مع Tailwind CSS

يمكن استخدام next/font مع Tailwind CSS من خلال متغير CSS.

في المثال أدناه، نستخدم الخط Inter من next/font/google (يمكنك استخدام أي خط من جوجل أو الخطوط المحلية). قم بتحميل خطك باستخدام خيار variable لتعريف اسم متغير CSS الخاص بك وتعيينه إلى inter. ثم استخدم inter.variable لإضافة متغير CSS إلى مستند HTML الخاص بك.

import { Inter, Roboto_Mono } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-inter',
})

const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-roboto-mono',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={`${inter.variable} ${roboto_mono.variable}`}>
      <body>{children}</body>
    </html>
  )
}
import { Inter, Roboto_Mono } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-inter',
})

const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-roboto-mono',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={`${inter.variable} ${roboto_mono.variable}`}>
      <body>{children}</body>
    </html>
  )
}

أخيرًا، أضف متغير CSS إلى إعدادات Tailwind CSS:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
    './app/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {
      fontFamily: {
        sans: ['var(--font-inter)'],
        mono: ['var(--font-roboto-mono)'],
      },
    },
  },
  plugins: [],
}

يمكنك الآن استخدام فئات الأداة font-sans و font-mono لتطبيق الخط على عناصرك.

التحميل المسبق

عند استدعاء دالة خط في صفحة من موقعك، لا يكون الخط متاحًا عالميًا ولا يتم تحميله مسبقًا على جميع المسارات. بدلاً من ذلك، يتم تحميل الخط مسبقًا فقط على المسارات ذات الصلة بناءً على نوع الملف الذي يتم استخدامه فيه:

  • إذا كانت صفحة فريدة، يتم تحميلها مسبقًا على المسار الفريد لتلك الصفحة.
  • إذا كانت تخطيط، يتم تحميلها مسبقًا على جميع المسارات المضمنة في التخطيط.
  • إذا كانت تخطيط الجذر، يتم تحميلها مسبقًا على جميع المسارات.

إعادة استخدام الخطوط

في كل مرة تستدعي فيها دالة localFont أو خط جوجل، يتم استضافة هذا الخط كنسخة واحدة في تطبيقك. لذلك، إذا قمت بتحميل نفس دالة الخط في ملفات متعددة، يتم استضافة عدة نسخ من نفس الخط. في هذه الحالة، يوصى بما يلي:

  • استدعاء دالة محمل الخط في ملف مشترك واحد
  • تصديره كمتغير ثابت
  • استيراد المتغير في كل ملف ترغب في استخدام هذا الخط فيه