We are still cooking the magic in the way!
خطوط الويب وخطوط Google والخطوط المتغيرة
مقدمة في خطوط الويب
في الأيام الأولى للويب، كان المصممون محدودين بحفنة من الخطوط "الآمنة للويب" -- مثل Arial وGeorgia وTimes New Roman وVerdana التي كانت مثبتة بشكل موثوق على معظم الحواسيب. إذا أردت استخدام أي خط آخر، كان عليك اللجوء إلى صور النص أو حلول Flash أو حيل JavaScript مثل Cufon وsIFR. تغير كل شيء مع تقديم قاعدة @font-face، التي تسمح بتحميل ملفات خطوط مخصصة مباشرة في المتصفح. اليوم، خطوط الويب جزء أساسي من تصميم الويب، وخدمات مثل Google Fonts جعلت من السهل للغاية استخدام آلاف الخطوط عالية الجودة على أي موقع.
في هذا الدرس، سنستكشف كيف تعمل خطوط الويب على مستوى تقني عميق. ستتعلم كيفية استخدام قاعدة @font-face، وفهم تنسيقات خطوط الويب، ودمج Google Fonts بكفاءة، وتحسين أداء تحميل الخطوط، والاستفادة من قوة الخطوط المتغيرة -- أحد أكثر التطورات إثارة في طباعة الويب.
قاعدة @font-face
قاعدة @font-face هي آلية CSS التي تخبر المتصفح بتنزيل واستخدام ملف خط مخصص. تُعلن اسم عائلة خط، وتشير إلى ملف خط واحد أو أكثر، ثم تستخدم ذلك الاسم في تصريحات font-family العادية عبر ورقة الأنماط.
الصيغة الأساسية
إليك أبسط شكل لتصريح @font-face:
مثال: تصريح @font-face أساسي
@font-face {
font-family: 'MyCustomFont';
src: url('fonts/my-custom-font.woff2') format('woff2');
}
/* الآن استخدمه مثل أي خط آخر */
body {
font-family: 'MyCustomFont', Arial, sans-serif;
}
واصفات @font-face
تدعم قاعدة @font-face عدة واصفات تمنحك تحكماً دقيقاً في كيفية تحميل الخط واستخدامه:
- font-family -- الاسم الذي تعينه للخط. يمكن أن يكون أي اسم تختاره؛ لا يجب أن يطابق الاسم الفعلي للخط. تستخدم هذا الاسم في خاصية
font-familyفي أماكن أخرى من CSS. - src -- مصدر ملف الخط. هذا هو أهم واصف. يمكنك تحديد مصادر متعددة كقائمة مفصولة بفواصل، وسيستخدم المتصفح أول مصدر يدعمه. كل مصدر يمكن أن يستخدم
url()للملفات الخارجية أوlocal()للخطوط المثبتة مسبقاً على نظام المستخدم. - font-weight -- يحدد أي سمك يمثله ملف الخط هذا. لا يجعل الخط غامقاً بل يخبر المتصفح أي ملف يستخدم عند طلب سمك معين. مثلاً، إذا كان لديك ملفات منفصلة للعادي والغامق، تنشئ قاعدتي
@font-faceبقيمfont-weightمختلفة لكن بنفس اسمfont-family. - font-style -- يحدد ما إذا كان هذا الملف للنص العادي أو المائل أو المنحرف. مثل font-weight، يربط نمطاً بملف محدد.
- font-display -- يتحكم في سلوك الخط أثناء التحميل (swap، block، fallback، optional، auto). غطينا هذا بالتفصيل في الدرس السابق.
- unicode-range -- يحد من الأحرف التي يغطيها ملف الخط. سيقوم المتصفح بتنزيل الملف فقط إذا احتوت الصفحة على أحرف في النطاق المحدد. هذا قوي للغاية لتحسين الأداء.
مثال: @font-face كامل مع أسماك وأنماط متعددة
/* السمك العادي */
@font-face {
font-family: 'Roboto';
src: local('Roboto'),
url('fonts/roboto-regular.woff2') format('woff2'),
url('fonts/roboto-regular.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
/* السمك الغامق */
@font-face {
font-family: 'Roboto';
src: local('Roboto Bold'),
url('fonts/roboto-bold.woff2') format('woff2'),
url('fonts/roboto-bold.woff') format('woff');
font-weight: 700;
font-style: normal;
font-display: swap;
}
/* النمط المائل */
@font-face {
font-family: 'Roboto';
src: local('Roboto Italic'),
url('fonts/roboto-italic.woff2') format('woff2'),
url('fonts/roboto-italic.woff') format('woff');
font-weight: 400;
font-style: italic;
font-display: swap;
}
/* غامق مائل */
@font-face {
font-family: 'Roboto';
src: local('Roboto Bold Italic'),
url('fonts/roboto-bold-italic.woff2') format('woff2'),
url('fonts/roboto-bold-italic.woff') format('woff');
font-weight: 700;
font-style: italic;
font-display: swap;
}
/* الآن يعرف المتصفح أي ملف يستخدم لكل تركيبة */
body {
font-family: 'Roboto', sans-serif;
font-weight: 400; /* يستخدم roboto-regular.woff2 */
}
strong {
font-weight: 700; /* يستخدم roboto-bold.woff2 */
}
em {
font-style: italic; /* يستخدم roboto-italic.woff2 */
}
@font-face الأربع نفس اسم font-family ("Roboto")، تنشئ عائلة خط واحدة بأوجه متعددة. يختار المتصفح تلقائياً الملف الصحيح بناءً على font-weight وfont-style المستخدمين في CSS. هذا أفضل بكثير من إنشاء أسماء عائلات منفصلة مثل "Roboto-Bold" لأنه يسمح للغامق والمائل بالعمل بشكل طبيعي مع عناصر <strong> و<em> في HTML.دالة local()
تتحقق دالة local() في واصف src مما إذا كان الخط مثبتاً مسبقاً على نظام المستخدم قبل تنزيله. هذا تحسين للأداء -- إذا كان الخط لدى المستخدم بالفعل، لا حاجة لتنزيله مرة أخرى.
مثال: استخدام local() لتحسين الأداء
@font-face {
font-family: 'Open Sans';
src: local('Open Sans'), /* تحقق من الخطوط المثبتة أولاً */
local('OpenSans'), /* تنسيق اسم بديل */
url('fonts/open-sans.woff2') format('woff2'),
url('fonts/open-sans.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
local(). بعض المتصفحات المركزة على الخصوصية وإضافات المتصفح تحظر local() لمنع بصمة الخطوط -- تقنية تكشف فيها المواقع أي خطوط مثبتة على نظامك لإنشاء معرف فريد. إذا كانت الخصوصية مصدر قلق كبير لجمهورك، قد ترغب في تخطي local() وتقديم ملفات الخطوط الخاصة بك دائماً. ومع ذلك، لمعظم المواقع، فائدة الأداء من local() تفوق هذا القلق.تنسيقات خطوط الويب
على مر السنين، تم تطوير عدة تنسيقات ملفات خطوط للويب. فهمها يساعدك في كتابة قواعد @font-face فعالة ودعم أوسع نطاق من المتصفحات:
- WOFF2 (تنسيق خطوط الويب المفتوح 2.0) -- المعيار الحديث. يستخدم WOFF2 ضغط Brotli، مما ينتج ملفات أصغر بنسبة 30-50% من WOFF. مدعوم من جميع المتصفحات الحديثة (Chrome، Firefox، Safari، Edge، Opera) ويجب أن يكون تنسيقك الأساسي. إذا كنت تستطيع تقديم تنسيق واحد فقط، اجعله WOFF2.
- WOFF (تنسيق خطوط الويب المفتوح 1.0) -- سلف WOFF2. يستخدم ضغط zlib. ملفات أكبر قليلاً من WOFF2 لكنها لا تزال أصغر بكثير من تنسيقات الخطوط الخام. له دعم أوسع للمتصفحات القديمة ويعمل كبديل جيد لـ WOFF2.
- TTF/OTF (خط TrueType / خط OpenType) -- تنسيقات خطوط سطح المكتب التي يمكن استخدامها أيضاً على الويب. غير مضغوطة وبالتالي أكبر بكثير من WOFF/WOFF2. استخدمها فقط إذا كنت بحاجة لدعم متصفحات قديمة جداً أو إذا كنت تحولها إلى WOFF2 بنفسك.
- EOT (خط OpenType المضمن) -- تنسيق مملوك لمايكروسوفت كان مدعوماً فقط بواسطة Internet Explorer. بما أن IE توقف، لم يعد EOT ضرورياً لأي مشروع حديث. يمكنك تجاهله بأمان.
- خطوط SVG -- تنسيق قديم حيث كانت الخطوط تُعرّف باستخدام توصيف SVG. كان يُستخدم فقط بواسطة إصدارات قديمة جداً من Safari على iOS. أصبح قديماً تماماً اليوم.
مثال: مكدس تنسيقات الخطوط الحديث
/* النهج الحديث -- WOFF2 فقط (يغطي 97%+ من المتصفحات) */
@font-face {
font-family: 'Inter';
src: url('fonts/inter.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
/* النهج المحافظ -- WOFF2 مع بديل WOFF */
@font-face {
font-family: 'Inter';
src: url('fonts/inter.woff2') format('woff2'),
url('fonts/inter.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
/* صيغة "مضادة للرصاص" القديمة (نادراً ما تكون مطلوبة اليوم) */
@font-face {
font-family: 'Inter';
src: url('fonts/inter.eot'); /* وضع توافق IE9 */
src: url('fonts/inter.eot?#iefix') format('embedded-opentype'),
url('fonts/inter.woff2') format('woff2'),
url('fonts/inter.woff') format('woff'),
url('fonts/inter.ttf') format('truetype');
font-weight: 400;
font-style: normal;
}
woff2_compress (سطر الأوامر)، أو Font Squirrel Webfont Generator، أو Transfonter.org لتحويل التنسيقات الأخرى إلى WOFF2.استخدام Google Fonts
Google Fonts هي مكتبة مجانية ومفتوحة المصدر تضم أكثر من 1500 عائلة خط. وهي أكثر الطرق شيوعاً لإضافة خطوط مخصصة لموقع ويب لأنها لا تتطلب إدارة ملفات الخطوط -- تستضيف Google الملفات وتقدمها من شبكة CDN الخاصة بها. هناك طريقتان أساسيتان لدمج Google Fonts.
الطريقة الأولى: طريقة الرابط (موصى بها)
أضف عنصر <link> في <head> الخاص بـ HTML. هذه هي الطريقة الموصى بها لأنها تسمح للمتصفح ببدء تنزيل الخطوط بالتوازي مع CSS الخاص بك.
مثال: Google Fonts عبر وسم Link
<!-- في <head> الخاص بـ HTML -->
<!-- خط واحد -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Roboto&display=swap">
<!-- أسماك متعددة -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap">
<!-- خطوط متعددة بأسماك محددة -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&family=Open+Sans:ital,wght@0,400;0,700;1,400&display=swap">
<!-- ثم استخدم في CSS -->
<style>
body {
font-family: 'Roboto', sans-serif;
}
</style>
الطريقة الثانية: طريقة @import
أضف تصريح @import في أعلى ملف CSS الخاص بك. هذا أبسط عندما تريد كل شيء في CSS، لكن له عيب في الأداء: يجب على المتصفح أولاً تنزيل ملف CSS الخاص بك، وإيجاد @import، وعندها فقط يبدأ بتنزيل CSS الخطوط -- مما يخلق سلسلة من الطلبات المتتالية.
مثال: Google Fonts عبر @import
/* في أعلى ملف CSS */
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&display=swap');
/* ثم استخدمه بشكل طبيعي */
h1, h2, h3 {
font-family: 'Playfair Display', Georgia, serif;
}
@import تنشئ سلسلة حظر عرض: HTML يحمّل CSS، ثم CSS يطلق طلب شبكة آخر لـ CSS خطوط Google. هذا يضيف تأخيراً متتالياً. طريقة <link> في HTML أسرع لأن المتصفح يكتشف طلب الخط أثناء تحليل HTML، قبل أن يبدأ حتى بتنزيل ورقة الأنماط الرئيسية. لمواقع الإنتاج، فضّل دائماً طريقة الرابط.تحسين Google Fonts مع Preconnect
عند استخدام Google Fonts، يحتاج المتصفح للاتصال بنطاقين مختلفين: fonts.googleapis.com (لـ CSS) وfonts.gstatic.com (لملفات الخطوط الفعلية). يمكنك تسريع تحميل الخطوط بإضافة وسوم <link rel="preconnect"> لإنشاء هذه الاتصالات مبكراً.
مثال: Preconnect لـ Google Fonts
<head>
<!-- اتصال مسبق بخوادم Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- ثم حمّل الخطوط -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap">
</head>
crossorigin على preconnect الخاص بـ gstatic.com مهمة. ملفات الخطوط تُطلب دائماً مع CORS (مشاركة الموارد عبر المصادر)، لذا يجب أن يتطابق preconnect. بدون crossorigin، سينشئ المتصفح اتصالاً بدون CORS لا يمكن إعادة استخدامه لتنزيل الخط، مما يهدر preconnect بالكامل.FOIT وFOUT
تحدث مشكلتان شائعتان عند تحميل خطوط الويب:
- FOIT (وميض النص غير المرئي) -- يخفي المتصفح النص أثناء تحميل خط الويب. يرى المستخدم مساحة فارغة حيث يجب أن يكون النص. هذا هو السلوك الافتراضي في العديد من المتصفحات وينشئ تجربة مستخدم سيئة لأن الصفحة تبدو وكأنها تحمّل ببطء حتى لو كان المحتوى جاهزاً.
- FOUT (وميض النص غير المنسق) -- يعرض المتصفح النص بخط بديل أثناء تحميل خط الويب، ثم يستبدله بخط الويب عند وصوله. يرى المستخدم وميضاً عند تغير مظهر النص. يُعتبر هذا عموماً النهج الأفضل لأن المحتوى على الأقل قابل للقراءة فوراً.
خاصية font-display (التي غطيناها في الدرس السابق) هي الأداة الرئيسية للتحكم في هذا السلوك. استخدام font-display: swap ينشئ FOUT، وهو مفضل لأن المحتوى يكون متاحاً فوراً.
تقليل FOUT بمطابقة الخطوط
لتقليل الإزعاج البصري لـ FOUT، يمكنك اختيار خطوط بديلة بعناية تتطابق بشكل وثيق مع مقاييس (الحجم، السمك، التباعد) خط الويب الخاص بك. واصفات CSS مثل size-adjust وascent-override وdescent-override وline-gap-override في @font-face تتيح لك ضبط الخطوط البديلة بدقة لتقليل انزياحات التخطيط عند تحميل خط الويب.
مثال: تقليل انزياح التخطيط بتعديلات الخط البديل
/* تعريف خط بديل معدّل */
@font-face {
font-family: 'Inter Fallback';
src: local('Arial');
size-adjust: 107%;
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
}
/* تعريف خط الويب الحقيقي */
@font-face {
font-family: 'Inter';
src: url('fonts/inter.woff2') format('woff2');
font-weight: 100 900;
font-display: swap;
}
/* استخدم كليهما في مكدس الخطوط */
body {
font-family: 'Inter', 'Inter Fallback', sans-serif;
}
التحميل المسبق للخطوط
للخطوط الحرجة التي يجب أن تتحمل بأسرع ما يمكن، يمكنك استخدام <link rel="preload"> لإخبار المتصفح ببدء تنزيل ملف الخط فوراً، حتى قبل أن يصادف قاعدة @font-face في CSS. هذا ذو قيمة خاصة عندما تكون ملفات الخطوط مرجعة عميقاً في CSS أو عند استخدام خطوط مستضافة ذاتياً.
مثال: التحميل المسبق لملفات الخطوط
<head>
<!-- حمّل مسبقاً أهم ملفات الخطوط -->
<link rel="preload"
href="/fonts/inter-regular.woff2"
as="font"
type="font/woff2"
crossorigin>
<link rel="preload"
href="/fonts/inter-bold.woff2"
as="font"
type="font/woff2"
crossorigin>
<!-- ورقة الأنماط التي تحتوي على قواعد @font-face -->
<link rel="stylesheet" href="/css/styles.css">
</head>
واصف unicode-range
يحد واصف unicode-range من أحرف يونيكود التي يغطيها ملف الخط. سيقوم المتصفح بتنزيل ملف الخط فقط إذا احتوت الصفحة على حرف واحد على الأقل في النطاق المحدد. هذا قوي بشكل لا يصدق للأداء لأنه يمكنك تقسيم خط كبير إلى مجموعات فرعية أصغر.
مثال: تقسيم نطاق يونيكود
/* أحرف لاتينية فقط */
@font-face {
font-family: 'Noto Sans';
src: url('fonts/noto-sans-latin.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC,
U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074,
U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD;
}
/* أحرف عربية */
@font-face {
font-family: 'Noto Sans';
src: url('fonts/noto-sans-arabic.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
unicode-range: U+0600-06FF, U+200C-200E, U+2010-2011,
U+204F, U+2E41, U+FB50-FDFF, U+FE80-FEFC;
}
/* أحرف سيريلية */
@font-face {
font-family: 'Noto Sans';
src: url('fonts/noto-sans-cyrillic.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* المتصفح يحمّل فقط ملفات المجموعات الفرعية التي يحتاجها! */
body {
font-family: 'Noto Sans', sans-serif;
}
@font-face متعددة، كل منها تغطي نظام كتابة مختلف (لاتيني، لاتيني موسع، سيريلي، يوناني، إلخ). يحمّل المتصفح فقط المجموعات الفرعية التي يحتاجها فعلاً للنص في صفحتك. هذا أحد أسباب أداء Google Fonts الجيد حتى للخطوط التي تحتوي على آلاف الأحرف.تقسيم الخطوط لتحسين الأداء
تقسيم الخطوط يعني إنشاء نسخة أصغر من ملف الخط تحتوي فقط على الأحرف التي تحتاجها فعلاً. ملف خط كامل قد يحتوي على آلاف الأحرف تغطي اللاتينية والسيريلية واليونانية والعربية وCJK والعديد من الأنظمة الأخرى. إذا كان موقعك بالعربية والإنجليزية فقط، فأنت تهدر النطاق الترددي على أحرف لن تستخدمها أبداً.
هناك عدة مناهج للتقسيم:
- تقسيم نطاق يونيكود في CSS -- استخدم واصف
unicode-rangeكما هو موضح أعلاه لتقسيم الخطوط إلى ملفات لكل نظام كتابة. يحمّل المتصفح فقط الملفات التي يحتاجها. - التقسيم الثابت بالأدوات -- استخدم أدوات مثل
pyftsubset(من fonttools) أوglyphhangerأو Font Squirrel Webfont Generator لإنشاء ملفات خطوط تحتوي فقط على الأحرف التي تحتاجها. - التقسيم المبني على المحتوى -- حلل المحتوى النصي الفعلي لموقعك وأنشئ مجموعة فرعية من الخط تتضمن تلك الأحرف المحددة فقط. هذا ينتج أصغر ملفات خطوط ممكنة.
مثال: استخدام pyftsubset لإنشاء مجموعة فرعية
# تثبيت fonttools (بايثون)
pip install fonttools brotli
# إنشاء مجموعة فرعية لاتينية فقط
pyftsubset MyFont.ttf \
--output-file=MyFont-latin.woff2 \
--flavor=woff2 \
--layout-features='*' \
--unicodes=U+0000-00FF
# إنشاء مجموعة فرعية بأحرف محددة فقط
pyftsubset MyFont.ttf \
--output-file=MyFont-minimal.woff2 \
--flavor=woff2 \
--text="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,!?- "
# استخدام glyphhanger لتحليل صفحة وتقسيم الخط
npx glyphhanger https://example.com --subset=MyFont.ttf --formats=woff2
الخطوط المتغيرة
الخطوط المتغيرة هي أحد أهم التطورات في طباعة الويب. عائلة الخط التقليدية تتطلب ملفات منفصلة لكل تركيبة من السمك والنمط -- عادي، غامق، مائل، غامق مائل، خفيف، خفيف مائل، وهكذا. عائلة كاملة قد تتطلب 8 أو 12 أو حتى 18 ملفاً منفصلاً. الخط المتغير يحزم جميع هذه التنوعات -- وقيم لا نهائية بينها -- في ملف واحد.
كيف تعمل الخطوط المتغيرة
تستخدم الخطوط المتغيرة محاور التنوع. كل محور يمثل خاصية يمكن تعديلها بشكل مستمر على مدى نطاق. يحتوي ملف الخط على تصاميم رئيسية عند الأطراف، ويقوم المتصفح بالاستيفاء بينها لإنتاج أي قيمة بينها. مثلاً، بدلاً من امتلاك فقط سمكي 400 و700، قد يقدم الخط المتغير أي سمك من 100 إلى 900 بزيادات صغيرة تصل إلى وحدة واحدة.
المحاور المسجلة
تحدد مواصفة OpenType خمسة محاور مسجلة (قياسية)، كل منها معرّف بوسم من أربعة أحرف صغيرة:
- wght (السمك) -- يتحكم في سمك الخطوط. يتراوح النطاق حسب الخط، عادةً 100-900. يُعين إلى خاصية CSS
font-weight. - wdth (العرض) -- يتحكم في مدى ضيق أو اتساع الأحرف. يُعبر عنه كنسبة مئوية من العادي (100%). يُعين إلى خاصية CSS
font-stretch. - ital (مائل) -- يبدل بين التصميم الروماني (0) والمائل (1). على عكس الميل البسيط، التصاميم المائلة عادةً ما تتميز بأشكال حروف مختلفة. يُعين إلى
font-style: italic. - slnt (الميل) -- يتحكم في زاوية النص، عادةً من 0 (مستقيم) إلى -12 أو -20 درجة. على عكس محور ital، لا يغير الميل أشكال الحروف -- بل يميلها فقط. يُعين إلى
font-style: oblique <angle>. - opsz (الحجم البصري) -- يعدل تصميم الخط لأحجام مختلفة. بالأحجام الصغيرة، تصبح الحروف أوسع قليلاً مع فتحات أكثر انفتاحاً وخطوط رفيعة أسمك للوضوح. بالأحجام الكبيرة، يصبح التصميم أكثر تنقيحاً بتباين أعلى. يُعين إلى خاصية CSS
font-optical-sizing.
استخدام الخطوط المتغيرة مع خصائص CSS القياسية
للمحاور المسجلة، يمكنك استخدام خصائص CSS القياسية بدلاً من font-variation-settings الأدنى مستوى:
مثال: الخطوط المتغيرة مع خصائص CSS القياسية
/* تحميل خط متغير */
@font-face {
font-family: 'Inter';
src: url('fonts/Inter-Variable.woff2') format('woff2-variations');
font-weight: 100 900; /* تصريح نطاق السمك الكامل */
font-style: normal;
font-display: swap;
}
/* استخدم أي سمك في النطاق -- وليس فقط 100، 200، 300، إلخ */
.thin { font-weight: 100; }
.extra-light { font-weight: 200; }
.light { font-weight: 300; }
.regular { font-weight: 400; }
.medium { font-weight: 500; }
.semi-bold { font-weight: 600; }
.bold { font-weight: 700; }
.extra-bold { font-weight: 800; }
.black { font-weight: 900; }
/* يمكنك حتى استخدام قيم بينية! */
.custom-450 { font-weight: 450; }
.custom-550 { font-weight: 550; }
.custom-650 { font-weight: 650; }
/* font-stretch المتغير لمحور العرض */
.condensed { font-stretch: 75%; }
.normal-width { font-stretch: 100%; }
.expanded { font-stretch: 125%; }
/* الحجم البصري (تلقائي افتراضياً) */
body {
font-optical-sizing: auto;
}
خاصية font-variation-settings
تمنحك خاصية font-variation-settings وصولاً مباشراً لجميع محاور الخط المتغير، بما في ذلك المحاور المسجلة والمخصصة. كل محور يُحدد كزوج من سلسلة وسم من أربعة أحرف وقيمة رقمية.
مثال: font-variation-settings
/* تعيين محاور السمك والعرض مباشرة */
.custom-variation {
font-variation-settings: 'wght' 625, 'wdth' 85;
}
/* محور المائل */
.partial-italic {
font-variation-settings: 'ital' 0.5; /* نصف مائل! */
}
/* محور الميل */
.slanted {
font-variation-settings: 'slnt' -8; /* 8 درجات من الميل */
}
/* محور الحجم البصري (تجاوز يدوي) */
.caption-text {
font-size: 12px;
font-variation-settings: 'opsz' 12;
}
.display-text {
font-size: 72px;
font-variation-settings: 'opsz' 72;
}
/* دمج محاور متعددة */
.hero-heading {
font-variation-settings: 'wght' 800, 'wdth' 110, 'opsz' 48;
}
font-weight، font-stretch، font-style، font-optical-sizing) على font-variation-settings كلما أمكن. خاصية font-variation-settings لا ترث قيم المحاور بشكل مستقل -- تعيين أي محور يعيد تعيين جميع المحاور غير المحددة صراحة. بالإضافة إلى ذلك، الرسوم المتحركة والانتقالات تعمل بشكل أفضل مع الخصائص القياسية. احتفظ بـ font-variation-settings للمحاور المخصصة أو للقيم التي لا يمكن التعبير عنها من خلال الخصائص القياسية.المحاور المخصصة
بعد المحاور المسجلة الخمسة، يمكن لمصممي الخطوط إنشاء محاور مخصصة معرّفة بأربعة أحرف كبيرة. هذه فريدة لكل خط وتقدم إمكانيات إبداعية تتجاوز بكثير السمك والعرض:
مثال: محاور خط متغير مخصصة
/* خط Recursive -- لديه محور MONO (مقدار أحادي المسافة)
ومحور CASL (النمط غير الرسمي) */
@font-face {
font-family: 'Recursive';
src: url('fonts/Recursive-Variable.woff2') format('woff2-variations');
font-weight: 300 1000;
font-display: swap;
}
/* التبديل بين متناسب وأحادي المسافة */
.proportional {
font-variation-settings: 'MONO' 0, 'CASL' 0;
}
.monospace {
font-variation-settings: 'MONO' 1, 'CASL' 0;
}
/* استخدام محور النمط غير الرسمي */
.casual {
font-variation-settings: 'MONO' 0, 'CASL' 1;
}
/* دمج للحصول على مظهر أحادي غير رسمي */
.casual-mono {
font-variation-settings: 'MONO' 1, 'CASL' 1;
}
الخطوط المتغيرة: فوائد الأداء
تقدم الخطوط المتغيرة مزايا أداء كبيرة مقارنة بالخطوط الثابتة التقليدية:
- طلبات HTTP أقل -- بدلاً من تنزيل 4-8 ملفات خط منفصلة (عادي، غامق، مائل، غامق مائل، خفيف، متوسط، إلخ)، تقوم بتنزيل ملف أو ملفين فقط من الخطوط المتغيرة.
- حجم ملف إجمالي أصغر -- ملف خط متغير واحد عادة أصغر من الحجم المجمع للخطوط الثابتة المكافئة. مثلاً، خط متغير يغطي أسماك 100-900 قد يكون 150 كيلوبايت، بينما تسعة خطوط ثابتة بـ 25 كيلوبايت لكل منها ستبلغ 225 كيلوبايت.
- مرونة التصميم -- يمكنك استخدام أي سمك أو عرض أو حجم بصري بدون إضافة تنزيلات ملفات إضافية. تحتاج font-weight: 550؟ لا مشكلة -- لا حاجة لملف إضافي.
تحريك الخطوط المتغيرة
أحد أكثر ميزات الخطوط المتغيرة إثارة هو القدرة على التحريك بين قيم المحاور. لأن المتصفح يقوم بالاستيفاء بين التصاميم في الوقت الحقيقي، يمكنك إنشاء انتقالات سلسة بين أسماك أو عروض أو محاور مخصصة مختلفة.
مثال: تحريك خصائص الخط المتغير
/* انتقال سمك سلس عند التمرير */
.animated-weight {
font-weight: 400;
transition: font-weight 0.3s ease;
}
.animated-weight:hover {
font-weight: 700;
}
/* تحريك بإطارات مفتاحية يتنقل عبر الأسماك */
@keyframes breathe {
0%, 100% {
font-variation-settings: 'wght' 300;
}
50% {
font-variation-settings: 'wght' 700;
}
}
.breathing-text {
animation: breathe 3s ease-in-out infinite;
}
/* تحريك محاور متعددة في وقت واحد */
@keyframes morph {
0% {
font-variation-settings: 'wght' 300, 'wdth' 75;
}
50% {
font-variation-settings: 'wght' 800, 'wdth' 125;
}
100% {
font-variation-settings: 'wght' 300, 'wdth' 75;
}
}
.morphing-text {
animation: morph 4s ease-in-out infinite;
}
الاستضافة الذاتية مقابل CDN: اتخاذ القرار الصحيح
لديك خياران رئيسيان لتقديم خطوط الويب: استخدام CDN مثل Google Fonts، أو الاستضافة الذاتية لملفات الخطوط على خادمك الخاص. لكل نهج مقايضات:
- CDN (Google Fonts، Adobe Fonts، إلخ) -- إعداد أسهل، اختيار تنسيق تلقائي، وتقسيم unicode-range. ومع ذلك، يقدم تبعية لطرف ثالث، ويتطلب بحث DNS واتصالات إضافية، ويثير مخاوف GDPR/الخصوصية في بعض المناطق لأن عناوين IP للمستخدمين تُرسل إلى خوادم Google.
- الاستضافة الذاتية -- تحكم كامل في التخزين المؤقت، لا تبعية لطرف ثالث، امتثال أفضل للخصوصية، وتحميل أسرع محتمل (بحث DNS أقل). ومع ذلك، تحتاج لإدارة ملفات الخطوط، والتعامل مع التقسيم بنفسك، وتقديم التنسيقات المناسبة.
لمواقع الإنتاج، خاصة تلك ذات الجمهور الأوروبي الخاضع لـ GDPR، يُوصى بشكل متزايد بالاستضافة الذاتية للخطوط. يمكن استخدام Google Fonts أثناء التطوير للسهولة، لكن يجب تنزيل ملفات الخطوط واستضافتها ذاتياً للإنتاج.
قائمة مراجعة شاملة لتحسين خطوط الويب
إليك قائمة مراجعة شاملة لتحسين خطوط الويب في أي مشروع:
- استخدم تنسيق WOFF2 -- يقدم أفضل ضغط وأوسع دعم للمتصفحات الحديثة.
- قسّم خطوطك -- أزل الأحرف التي لا تحتاجها. استخدم unicode-range أو أدوات مثل pyftsubset.
- حدد عائلات الخطوط -- استخدم 2-3 عائلات خط على الأكثر. كل واحدة تضيف حجماً وتعقيداً.
- حدد الأسماك والأنماط -- حمّل فقط الأسماك والأنماط التي تستخدمها فعلاً. لا تحمّل 8 أسماك إذا كنت تستخدم 3 فقط.
- فكر في الخطوط المتغيرة -- إذا كنت تحتاج 3 أسماك أو أكثر من نفس العائلة، فالخط المتغير غالباً أصغر.
- اضبط font-display: swap -- تأكد أن النص مرئي فوراً أثناء تحميل الخطوط.
- حمّل الخطوط الحرجة مسبقاً -- استخدم
<link rel="preload">لأهم ملف أو ملفين خط. - استخدم preconnect -- إذا كنت تستخدم CDN خطوط، أضف تلميحات preconnect لنطاقي CSS وملفات الخطوط.
- استضف ذاتياً عندما يمكن -- يلغي تبعيات الطرف الثالث وبحث DNS الإضافي.
- طابق مقاييس البديل -- استخدم size-adjust وواصفات التجاوز لتقليل انزياح التخطيط أثناء FOUT.
تمرين 1: استضافة ذاتية لخط Google
اختر أي خط Google بـ 3 أسماك على الأقل (مثلاً، Inter بأسماك 400 و500 و700). حمّل ملفات WOFF2 من Google Fonts (يمكنك استخدام أداة google-webfonts-helper على gwfh.mranftl.com). أنشئ قواعد @font-face لجميع الأسماك الثلاثة، بما في ذلك دالة local()، وتنسيق WOFF2، وfont-display: swap، وunicode-range مناسب للأحرف اللاتينية. ثم طبّق الخط على صفحة HTML نموذجية بعناوين ونص متن ونص غامق. قارن طلبات الشبكة في DevTools المتصفح مع نهج Google Fonts CDN -- كم عدد الطلبات في كل حالة؟ ما فرق حجم الملف الإجمالي؟
تمرين 2: تنفيذ خط متغير مع رسوم متحركة
حمّل خط "Recursive" المتغير (متاح على Google Fonts). أنشئ قاعدة @font-face واحدة تحمّل ملف الخط المتغير بنطاق سمك من 300 إلى 1000. ابنِ صفحة عرض بالميزات التالية: (1) عنوان ينتقل بسلاسة من سمك 300 إلى سمك 900 عند التمرير باستخدام انتقالات CSS. (2) فقرة حيث يمكن التحكم بالسمك بواسطة خاصية CSS مخصصة، مما يوضح كيف يحل ملف واحد محل العديد من الملفات الثابتة. (3) رسم متحرك "التنفس" يستخدم إطارات مفتاحية لتدوير السمك بين 400 و700 على مدى 3 ثوانٍ. (4) إذا كان الخط يدعم محور CASL (غير رسمي)، أضف تبديلاً يتنقل بين الأنماط غير الرسمية والعادية. وثّق الحجم الإجمالي لملف الخط المتغير مقابل ملفات الخطوط الثابتة المكافئة لـ 3-4 أسماك.
تمرين 3: تدقيق أداء تحميل الخطوط
اختر أي موقع حي يستخدم خطوط ويب (يمكنك فحص هذا باستخدام DevTools المتصفح تحت تبويب الشبكة، بالتصفية حسب الخط). للموقع المختار، أجب عن الأسئلة التالية: (1) ما تنسيقات الخطوط المُقدمة؟ هل يستخدمون WOFF2؟ (2) كم عدد ملفات الخطوط المحمّلة؟ هل يمكن لخط متغير تقليل هذا العدد؟ (3) هل يُستخدم font-display؟ بأي قيمة؟ (4) هل الخطوط محمّلة مسبقاً بـ <link rel="preload">؟ (5) هل يُستخدم preconnect لنطاقات الخطوط الخارجية؟ (6) هل يُستخدم unicode-range للتقسيم؟ (7) ما حجم حمولة الخطوط الإجمالي؟ ثم اكتب تقريراً موجزاً يوصي بتحسينات محددة مع تقديرات لتحسين الأداء.