المستوى المطلوب: متوسط. هذا الشرح مبني على فرضية أنك تستخدم خطًا عربيًا مخصّصًا على موقعك (من Google Fonts أو ملف .woff2 على سيرفرك)، وأن لديك صفحة محتواها نص عربي في المقام الأول.
لو نصّ صفحتك يختفي ثانية كاملة قبل ما يظهر، أو بيقفز فجأة وقت التحميل، المشكلة مش في السيرفر ولا في سرعة النت. المشكلة في طريقة تحميل الخط. تظبيط سطرين وأمر واحد بينزّل زمن ظهور أكبر عنصر (LCP) من 2.6 ثانية لـ 1.1 ثانية، ويوقف وميض النص تمامًا.
تحميل خطوط الويب بدون وميض: اضبط font-display والتقليم وحسّن سرعة الظهور
المشكلة باختصار
الخط المخصّص مش بيوصل مع الصفحة. المتصفح لازم يحمّله كملف منفصل بعد ما يقرأ الـ CSS. في الفترة دي بين طلب الصفحة ونزول الخط، المتصفح بيقرر: يخفي النص لحد ما ينزل الخط، أو يعرضه بخط احتياطي ثم يبدّله. القرار ده اسمه font-display، والافتراضي في أغلب المتصفحات بيميل لإخفاء النص. النتيجة: المستخدم بيبصّ على مساحة فاضية والمحتوى موجود فعلًا.
الافتراض هنا: عندك خط ويب واحد أو اتنين بحجم إجمالي 200 إلى 400 كيلوبايت. لو بتستعمل خطوط النظام فقط، المقال ده مش موضوعك أصلًا.
وميض النص: FOIT مقابل FOUT بمثال بسيط
تخيّل محل جديد فاتح، لكن اللافتة الرسمية المطلوبة لسه في المطبعة. عندك خياران. الأول: تسيب مكان اللافتة فاضي تمامًا لحد ما تيجي، فالزبون واقف قدام محل مالوش اسم. ده بالظبط FOIT اختصار Flash of Invisible Text: النص موجود بس غير مرئي لحد ما ينزل الخط.
الخيار الثاني: تعلّق لافتة ورقية مؤقتة بخط عادي دلوقتي، وأول ما تيجي الرسمية تستبدلها. الزبون قرأ الاسم من أول لحظة. ده FOUT اختصار Flash of Unstyled Text: النص يظهر فورًا بخط احتياطي، ثم يتبدّل للخط المخصّص لمّا ينزل.
علميًا: عند بداية عرض الصفحة، المتصفح يمرّ بفترة block ثم فترة swap لكل خط قيد التحميل. في فترة الـ block النص المرتبط بالخط لا يُرسم (نص شفّاف). لو نزل الخط داخل فترة الـ block يظهر النص بالخط الصحيح مباشرة. لو تأخّر، سلوك الـ block الطويل يعطينا FOIT، وسلوك الـ swap يعطينا FOUT. الخاصية font-display هي اللي تحدد طول كل فترة.
الحل: ثلاث خطوات قابلة للنسخ
- حدّد سلوك العرض بـ
font-display: swapداخل تعريف الخط، عشان النص يظهر فورًا بخط احتياطي. - حمّل خط الكوفر مسبقًا بـ
preloadعشان المتصفح يبدأ تحميله مبكرًا بدل ما يستنى قراءة الـ CSS. - قلّم الخط (Subsetting) عشان تشيل آلاف المحارف اللي موقعك مش بيستخدمها وتنزّل حجم الملف.
@font-face {
font-family: 'Cairo';
src: url('/fonts/cairo-subset.woff2') format('woff2');
font-weight: 400;
font-display: swap;
unicode-range: U+0600-06FF, U+0750-077F, U+0020-007E;
}
<link rel="preload" href="/fonts/cairo-subset.woff2" as="font" type="font/woff2" crossorigin>
pip install fonttools brotli
pyftsubset Cairo-Regular.ttf --unicodes="U+0600-06FF,U+0750-077F,U+0020-007E" --flavor=woff2 --output-file=cairo-subset.woff2
الأرقام: ماذا يتغيّر فعلًا
خُد سيناريو واقعي: متجر عربي بـ 28 ألف زائر يوميًا، يستخدم خطًا بحجم 280 كيلوبايت بدون ضبط. القياس قبل وبعد على شبكة 4G متوسطة (الأرقام تقديرية معقولة، تختلف حسب جهازك وشبكتك):
- حجم ملف الخط بعد التقليم: من 280KB إلى 68KB.
- زمن ظهور أكبر عنصر (LCP): من 2.6 ثانية إلى 1.1 ثانية.
- فترة النص الغائب: من 1.2 ثانية تقريبًا إلى صفر (النص يظهر فورًا بالخط الاحتياطي).
المكسب الأكبر مش من ضبط font-display لوحده، بل من التقليم الذي ينزّل حجم التحميل. لكن swap هو اللي يقتل الإحساس بالبطء لأن المستخدم يقرأ من اللحظة الأولى.
الـ trade-offs التي يجب الانتباه لها
كل قرار هنا معاه ثمن:
- font-display: swap يعرض النص فورًا، لكنه يسبب قفزة بصرية (تبدّل الخط) قد ترفع مؤشر
CLSلو الخط الاحتياطي مختلف كثيرًا في القياسات. البديلoptionalيتجنّب القفزة لكنه قد لا يعرض خطك المخصّص إطلاقًا في أول زيارة. - preload يبدأ تحميل الخط مبكرًا، لكنه ينافس موارد أخرى مهمة على عرض الحزمة. حمّل مسبقًا الخط الظاهر فوق الطية فقط، مش كل الأوزان.
- Subsetting يوفّر حجمًا كبيرًا، مقابل خطر اختفاء محارف لو نسيت نطاقًا يحتاجه المحتوى (رموز، أرقام هندية، تشكيل).
لتقليل قفزة الـ swap، اضبط خطًا احتياطيًا قريبًا في القياسات باستخدام size-adjust وascent-override في تعريف الخط الاحتياطي، حتى يكون الفرق بين الخطين شبه غير محسوس.
متى لا تستخدم هذه الطريقة
لا تقلّم الخط بعدوانية لو موقعك يعرض محتوى من المستخدمين (تعليقات، أسماء بلغات متعددة، إيموجي). النطاق الناقص سيظهر مربّعات فارغة. في الحالة دي احتفظ بتغطية أوسع، أو استخدم خط النظام للمحتوى المتغيّر. وكذلك لو موقعك يعتمد أصلًا على خطوط النظام، فلا تضيف خطًا خارجيًا لمجرد الشكل: أسرع خط هو الخط الذي لا تُحمّله.
الخطوة التالية
افتح تعريف الخط في مشروعك وأضف font-display: swap الآن، ثم قِس الـ LCP قبل وبعد بأداة Lighthouse في المتصفح. لو لقيت الصفحة أبطأ بعد إضافة preload، ده معناه إنك حمّلت خطوطًا كثيرة مسبقًا وتنافست على عرض الحزمة، فاحصر الـ preload على خط الكوفر فقط.
المصادر
- سلوك font-display وقيمه (block, swap, fallback, optional): توثيق MDN Web Docs عن الخاصية font-display.
- استراتيجيات تحميل الخطوط وتحسين LCP: web.dev — Best practices for fonts.
- التحميل المسبق للخطوط بـ preload: web.dev — Preload web fonts.
- مواصفة الخطوط: W3C CSS Fonts Module Level 4.
- أداة التقليم pyftsubset: توثيق fontTools الرسمي (fonttools subset).
- ضبط الخط الاحتياطي بـ size-adjust: توثيق MDN Web Docs.