الخصائص المخصصة (المتغيرات) في CSS
مقدمة إلى الخصائص المخصصة في CSS
الخصائص المخصصة في CSS، المعروفة عادة بمتغيرات CSS، هي واحدة من أقوى الميزات التي أُدخلت في CSS الحديث. تتيح لك تعريف قيم قابلة لإعادة الاستخدام يمكن الإشارة إليها في جميع أنحاء أوراق الأنماط الخاصة بك، مما يجعل الكود أكثر قابلية للصيانة والمرونة والديناميكية. على عكس متغيرات المعالجات المسبقة من أدوات مثل Sass أو Less، فإن الخصائص المخصصة في CSS حية في المتصفح -- فهي تشارك في التتالي ويمكن أن تُورث للعناصر الفرعية ويمكن حتى التحكم بها بواسطة JavaScript أثناء التشغيل.
قبل وجود الخصائص المخصصة، كان المطورون يعتمدون على متغيرات المعالجات المسبقة أو البحث والاستبدال اليدوي للقيم عبر أوراق أنماط كبيرة. إذا أردت تغيير لون علامتك التجارية الأساسي، فربما كنت تحتاج إلى تحديث عشرات الإعلانات المتناثرة عبر ملفات متعددة. تحل الخصائص المخصصة في CSS هذه المشكلة على مستوى اللغة، مما يمنحك آلية أصلية لإنشاء مصدر واحد للحقيقة للقيم المتكررة.
إعلان الخصائص المخصصة
يتم إعلان الخاصية المخصصة باستخدام اسم يبدأ بشرطتين (--). هذا البادئة المزدوجة هي ما يميز الخصائص المخصصة عن خصائص CSS العادية. يمكن أن يحتوي الاسم على أحرف وأرقام وشرطات وشرطات سفلية، وهو حساس لحالة الأحرف -- مما يعني أن --my-Color و--my-color هما خاصيتان مختلفتان تماما.
مثال: إعلان الخصائص المخصصة
:root {
--color-primary: #3498db;
--color-secondary: #2ecc71;
--color-danger: #e74c3c;
--font-family-base: 'Segoe UI', Tahoma, Geneva, sans-serif;
--font-size-base: 16px;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 32px;
--border-radius: 4px;
--shadow-card: 0 2px 8px rgba(0, 0, 0, 0.1);
}
في المثال أعلاه، يُستخدم محدد الفئة الزائفة :root كنطاق الإعلان. يطابق محدد :root العنصر الجذري للمستند، وهو عنصر <html> في HTML. نظرا لأن الخصائص المخصصة تُورث، فإن إعلانها على :root يجعلها متاحة لكل عنصر في المستند. هذا هو النهج التقليدي للمتغيرات العامة.
--Color-Primary و--color-primary تُعامل كخصائص مختلفة تماما. التزم باتفاقية تسمية متسقة -- الأحرف الصغيرة مع الشرطات هي المعيار الأكثر شيوعا.استخدام دالة var()
لاستخدام خاصية مخصصة، تُشير إليها بدالة var(). تأخذ دالة var() اسم الخاصية المخصصة كوسيطها الأول وتُعيد القيمة المُعينة لتلك الخاصية. إذا لم تكن الخاصية معرفة أو كانت غير صالحة، فسيستخدم المتصفح إما القيمة الموروثة أو القيمة الأولية للخاصية.
مثال: استخدام var() لتطبيق الخصائص المخصصة
body {
font-family: var(--font-family-base);
font-size: var(--font-size-base);
color: var(--color-text);
background-color: var(--color-background);
}
.btn-primary {
background-color: var(--color-primary);
color: #ffffff;
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--border-radius);
border: none;
cursor: pointer;
}
.btn-danger {
background-color: var(--color-danger);
color: #ffffff;
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--border-radius);
border: none;
cursor: pointer;
}
.card {
padding: var(--spacing-lg);
border-radius: var(--border-radius);
box-shadow: var(--shadow-card);
}
لاحظ كيف يتشارك كل من .btn-primary و.btn-danger نفس الحشوة ونصف قطر الحدود والبنية -- الاختلاف الوحيد هو لون الخلفية. باستخدام المتغيرات للقيم المشتركة، أي تغييرات مستقبلية على التباعد أو نصف قطر الحدود تحتاج فقط أن تحدث في مكان واحد.
القيم الاحتياطية في var()
تقبل دالة var() وسيطا ثانيا اختياريا -- قيمة احتياطية. تُستخدم هذه القيمة الاحتياطية إذا لم تكن الخاصية المخصصة معرفة أو تم إزالتها أو تحتوي على قيمة غير صالحة. القيم الاحتياطية مفيدة بشكل خاص عند بناء مكونات قابلة لإعادة الاستخدام قد تُستخدم في سياقات مختلفة حيث قد لا تكون بعض المتغيرات معرفة.
مثال: القيم الاحتياطية
/* قيمة احتياطية واحدة */
.header {
background-color: var(--header-bg, #333333);
color: var(--header-text, #ffffff);
padding: var(--header-padding, 20px);
}
/* var() متداخلة كقيمة احتياطية -- متغير يرجع إلى متغير آخر */
.sidebar {
width: var(--sidebar-width, var(--default-sidebar-width, 250px));
}
/* قيم متعددة في قيمة احتياطية واحدة */
.content {
font-family: var(--font-stack, 'Helvetica Neue', Arial, sans-serif);
}
/* قيمة احتياطية مع calc() */
.container {
max-width: var(--container-width, calc(100% - 40px));
}
var() يُعامل كقيمة احتياطية. لذا var(--font, Helvetica, Arial, sans-serif) لها قيمة احتياطية هي Helvetica, Arial, sans-serif -- الفواصل هي جزء من القيمة الاحتياطية وليست وسائط إضافية.النطاق: المتغيرات العامة مقابل المحلية
أحد أقوى جوانب الخصائص المخصصة في CSS هو سلوك النطاق الخاص بها. المتغيرات المعرفة على :root عامة ومتاحة في كل مكان. ومع ذلك، يمكنك أيضا تعريف المتغيرات على أي عنصر، وستكون تلك المتغيرات متاحة فقط لذلك العنصر وأحفاده. هذا النطاق المحلي يُمكّن من تخصيص المكونات على مستوى المكون والتغليف.
مثال: النطاق العام والمحلي
/* متغيرات عامة متاحة في كل مكان */
:root {
--color-primary: #3498db;
--color-text: #333333;
--spacing-unit: 8px;
}
/* متغيرات محلية خاصة بمكون التنبيه */
.alert {
--alert-padding: 16px;
--alert-border-width: 4px;
padding: var(--alert-padding);
border-left: var(--alert-border-width) solid var(--alert-border-color, #ccc);
background-color: var(--alert-bg, #f5f5f5);
color: var(--alert-text, var(--color-text));
}
/* تجاوز المتغيرات المحلية لأنواع تنبيه محددة */
.alert-success {
--alert-border-color: #2ecc71;
--alert-bg: #eafaf1;
--alert-text: #1e8449;
}
.alert-error {
--alert-border-color: #e74c3c;
--alert-bg: #fdedec;
--alert-text: #c0392b;
}
.alert-warning {
--alert-border-color: #f39c12;
--alert-bg: #fef9e7;
--alert-text: #9a7d0a;
}
في هذا المثال، تُعرف فئة .alert متغيراتها المحلية الخاصة بقيم احتياطية. فئات المتغيرات (.alert-success و.alert-error و.alert-warning) تحتاج فقط إلى تجاوز قيم المتغيرات -- خصائص CSS الفعلية في فئة .alert الأساسية تبقى دون تغيير. هذا النمط نظيف للغاية وقابل للتوسع.
التتالي والوراثة للمتغيرات
تتبع الخصائص المخصصة في CSS نفس قواعد التتالي والوراثة مثل أي خاصية CSS أخرى. المتغير المعرف على عنصر أب يُورث لجميع أبنائه. إذا أعاد عنصر فرعي تعريف نفس المتغير، فإن القيمة الجديدة تسري على ذلك الفرع وأحفاده، دون التأثير على الأب أو الأشقاء.
مثال: سلوك الوراثة والتجاوز
:root {
--text-color: #333333;
--bg-color: #ffffff;
}
body {
color: var(--text-color);
background-color: var(--bg-color);
}
/* الشريط الجانبي يعيد تعريف المتغيرات لنفسه ولأبنائه */
.sidebar {
--text-color: #ffffff;
--bg-color: #2c3e50;
color: var(--text-color);
background-color: var(--bg-color);
}
/* العناصر داخل .sidebar ترث القيم المُتجاوزة */
.sidebar a {
color: var(--text-color); /* ستكون #ffffff وليس #333333 */
}
/* العناصر خارج .sidebar لا تزال تستخدم قيم الجذر */
.main-content a {
color: var(--text-color); /* ستكون #333333 */
}
اتفاقيات التسمية
التسمية المتسقة ضرورية لقابلية الصيانة، خاصة في المشاريع الكبيرة التي تحتوي على العديد من المتغيرات. الاتفاقية الأكثر شيوعا تستخدم كلمات صغيرة مفصولة بشرطات، مع بادئة فئة تجمع المتغيرات ذات الصلة معا. إليك بعض أنماط التسمية المعتمدة على نطاق واسع:
- رموز الألوان:
--color-primaryو--color-secondaryو--color-successو--color-dangerو--color-textو--color-bg - رموز التباعد:
--spacing-xsو--spacing-smو--spacing-mdو--spacing-lgو--spacing-xl - رموز الطباعة:
--font-family-baseو--font-family-headingو--font-size-smو--font-size-baseو--font-size-lg - نطاق المكونات:
--card-paddingو--card-bgو--btn-heightو--nav-width - معدلات الحالة:
--color-primary-hoverو--color-primary-activeو--btn-disabled-opacity
بعض الفرق تستخدم بادئة مساحة اسم مثل --app- أو --ds- (نظام التصميم) لتجنب التعارضات مع المكتبات الخارجية. على سبيل المثال: --ds-color-primary و--ds-spacing-md.
التخصيص بالمتغيرات: مخططات الألوان
أحد أكثر حالات الاستخدام شيوعا للخصائص المخصصة في CSS هو التخصيص. من خلال تعريف لوحة الألوان بأكملها كمتغيرات، يمكنك التبديل بين السمات ببساطة عن طريق إعادة تعريف تلك المتغيرات تحت محدد أو فئة مختلفة. هذه هي الطريقة التي تعمل بها معظم تطبيقات الوضع الداكن الحديثة.
مثال: السمة الفاتحة والداكنة باستخدام متغيرات CSS
/* السمة الفاتحة (الافتراضية) */
:root {
--color-bg: #ffffff;
--color-surface: #f8f9fa;
--color-text: #212529;
--color-text-secondary: #6c757d;
--color-primary: #0d6efd;
--color-primary-hover: #0b5ed7;
--color-border: #dee2e6;
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
}
/* السمة الداكنة */
[data-theme="dark"] {
--color-bg: #1a1a2e;
--color-surface: #16213e;
--color-text: #e0e0e0;
--color-text-secondary: #a0a0a0;
--color-primary: #4dabf7;
--color-primary-hover: #74c0fc;
--color-border: #2d2d44;
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
}
/* المكونات تتكيف تلقائيا مع السمة النشطة */
body {
background-color: var(--color-bg);
color: var(--color-text);
}
.card {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
box-shadow: var(--shadow-sm);
border-radius: 8px;
padding: 24px;
}
.card:hover {
box-shadow: var(--shadow-md);
}
a {
color: var(--color-primary);
}
a:hover {
color: var(--color-primary-hover);
}
مع هذا الإعداد، التبديل بين الوضع الفاتح والداكن يتطلب فقط إضافة أو إزالة سمة data-theme="dark" على العنصر الجذري. كل مكون يستخدم المتغيرات سيُحدث مظهره تلقائيا -- لا حاجة لقواعد CSS إضافية لكل مكون.
تجاوز المتغيرات في استعلامات الوسائط
يمكن إعادة تعريف الخصائص المخصصة في CSS داخل استعلامات الوسائط، مما يتيح لك تعديل رموز التصميم بناء على حجم الشاشة أو تفضيلات المستخدم أو ميزات الوسائط الأخرى. هذا قوي بشكل خاص للطباعة المتجاوبة وتعديلات التباعد واحترام تفضيل السمة على مستوى النظام لدى المستخدم.
مثال: متغيرات متجاوبة مع استعلامات الوسائط
:root {
--font-size-base: 14px;
--font-size-h1: 28px;
--spacing-section: 40px;
--container-padding: 16px;
--grid-columns: 1;
}
/* الأجهزة اللوحية وما فوق */
@media (min-width: 768px) {
:root {
--font-size-base: 16px;
--font-size-h1: 36px;
--spacing-section: 60px;
--container-padding: 24px;
--grid-columns: 2;
}
}
/* سطح المكتب وما فوق */
@media (min-width: 1200px) {
:root {
--font-size-base: 18px;
--font-size-h1: 48px;
--spacing-section: 80px;
--container-padding: 32px;
--grid-columns: 3;
}
}
/* احترام تفضيل الوضع الداكن للمستخدم */
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #1a1a2e;
--color-text: #e0e0e0;
--color-surface: #16213e;
}
}
/* احترام تفضيل تقليل الحركة للمستخدم */
@media (prefers-reduced-motion: reduce) {
:root {
--transition-duration: 0s;
--animation-duration: 0s;
}
}
/* استخدام المتغيرات المتجاوبة */
body {
font-size: var(--font-size-base);
}
h1 {
font-size: var(--font-size-h1);
}
section {
padding: var(--spacing-section) 0;
}
.grid {
display: grid;
grid-template-columns: repeat(var(--grid-columns), 1fr);
gap: var(--container-padding);
}
تجاوز المتغيرات في سياقات المكونات
الخصائص المخصصة مفيدة بشكل خاص عندما تريد أن تبدو نسخ مختلفة من نفس المكون مختلفة حسب مكان ظهورها. بدلا من إنشاء فئات معدلة تُكرر مجموعة القواعد بأكملها، يمكنك ببساطة تجاوز المتغيرات ذات الصلة في كل سياق.
مثال: تجاوزات سياقية للمكونات
/* زر أساسي يستخدم المتغيرات */
.btn {
--btn-bg: var(--color-primary);
--btn-text: #ffffff;
--btn-padding-x: 16px;
--btn-padding-y: 8px;
--btn-font-size: 14px;
background-color: var(--btn-bg);
color: var(--btn-text);
padding: var(--btn-padding-y) var(--btn-padding-x);
font-size: var(--btn-font-size);
border: none;
border-radius: var(--border-radius);
cursor: pointer;
}
/* في قسم البطل، الأزرار أكبر */
.hero .btn {
--btn-padding-x: 32px;
--btn-padding-y: 16px;
--btn-font-size: 18px;
}
/* في الشريط الجانبي، الأزرار أصغر ولها ألوان مختلفة */
.sidebar .btn {
--btn-bg: transparent;
--btn-text: var(--color-primary);
--btn-padding-x: 12px;
--btn-padding-y: 6px;
--btn-font-size: 12px;
}
/* في التذييل، الأزرار تتوافق مع سمة التذييل */
.footer .btn {
--btn-bg: #ffffff;
--btn-text: #333333;
}
هذا النمط يلغي الحاجة لفئات مثل .btn-large و.btn-small أو .btn-sidebar. المكون يتكيف بشكل طبيعي بناء على موقعه في DOM، وهذا أسهل في الصيانة بكثير من إدارة قائمة متنامية من فئات المعدلات.
استخدام المتغيرات مع calc()
تعمل الخصائص المخصصة في CSS بسلاسة مع دالة calc()، مما يمكّن العمليات الحسابية بناء على قيم المتغيرات. هذا مفيد للغاية لإنشاء أنظمة تباعد متناسبة وطباعة مرنة وتخطيطات ديناميكية.
مثال: المتغيرات مع calc()
:root {
--spacing-unit: 8px;
--font-size-base: 16px;
--line-height-ratio: 1.5;
--container-max-width: 1200px;
--sidebar-width: 280px;
}
/* تباعد متناسب باستخدام calc ووحدة أساسية */
.section {
padding: calc(var(--spacing-unit) * 4) calc(var(--spacing-unit) * 2);
margin-bottom: calc(var(--spacing-unit) * 6);
}
/* طباعة مرنة */
h1 {
font-size: calc(var(--font-size-base) * 2.5);
line-height: calc(var(--font-size-base) * 2.5 * var(--line-height-ratio));
}
h2 {
font-size: calc(var(--font-size-base) * 2);
}
h3 {
font-size: calc(var(--font-size-base) * 1.5);
}
/* حسابات تخطيط ديناميكية */
.main-content {
width: calc(100% - var(--sidebar-width) - var(--spacing-unit) * 4);
margin-left: calc(var(--sidebar-width) + var(--spacing-unit) * 2);
}
/* هامش سلبي باستخدام calc */
.full-bleed {
margin-left: calc(-1 * var(--container-padding));
margin-right: calc(-1 * var(--container-padding));
padding-left: var(--container-padding);
padding-right: var(--container-padding);
}
calc() مسافات حول عاملي + و-. كتابة calc(var(--a)-var(--b)) لن تعمل -- يجب كتابة calc(var(--a) - var(--b)). عاملا * و/ لا يتطلبان مسافات، لكن إضافتها تحسن القراءة.التحديثات الديناميكية باستخدام JavaScript
أحد أكبر مزايا الخصائص المخصصة في CSS مقارنة بمتغيرات المعالجات المسبقة هو أنها موجودة في وقت التشغيل ويمكن قراءتها وتعديلها بواسطة JavaScript. هذا يفتح إمكانيات للتخصيص الديناميكي وتفضيلات المستخدم والرسوم المتحركة القائمة على التمرير والتلاعب بالأنماط في الوقت الفعلي دون الحاجة إلى تعديل فئات CSS.
مثال: قراءة وتعيين المتغيرات بواسطة JavaScript
/* CSS */
:root {
--primary-hue: 210;
--primary-saturation: 70%;
--primary-lightness: 50%;
--color-primary: hsl(
var(--primary-hue),
var(--primary-saturation),
var(--primary-lightness)
);
}
/* JavaScript */
// قراءة قيمة خاصية مخصصة
const root = document.documentElement;
const styles = getComputedStyle(root);
const currentHue = styles.getPropertyValue('--primary-hue').trim();
console.log('الدرجة الحالية:', currentHue); // "210"
// تعيين قيمة خاصية مخصصة
root.style.setProperty('--primary-hue', '150');
// تبديل الوضع الداكن
function toggleDarkMode() {
const html = document.documentElement;
const isDark = html.getAttribute('data-theme') === 'dark';
html.setAttribute('data-theme', isDark ? 'light' : 'dark');
}
// منتقي ألوان ديناميكي
const colorPicker = document.getElementById('color-picker');
colorPicker.addEventListener('input', function(e) {
document.documentElement.style.setProperty(
'--color-primary',
e.target.value
);
});
// حجم خط متجاوب بناء على شريط تمرير
const slider = document.getElementById('font-slider');
slider.addEventListener('input', function(e) {
document.documentElement.style.setProperty(
'--font-size-base',
e.target.value + 'px'
);
});
طريقة getComputedStyle() تقرأ القيمة المحسوبة الحالية لخاصية مخصصة، بينما style.setProperty() تعين قيمة جديدة على أنماط العنصر المضمنة. الأنماط المضمنة لها أولوية أعلى من قواعد أوراق الأنماط، لذا ستسري القيمة الجديدة فورا وتنتشر إلى جميع الأحفاد الذين يستخدمون المتغير.
متغيرات CSS مقابل متغيرات المعالجات المسبقة
من المهم فهم الاختلافات بين الخصائص المخصصة في CSS ومتغيرات المعالجات المسبقة (Sass وLess وStylus)، حيث تخدم أغراضا متداخلة ولكن متميزة:
- وقت الحل: تُحل متغيرات المعالجات المسبقة في وقت الترجمة وتُنتج CSS ثابتة. تُحل الخصائص المخصصة في CSS في وقت التشغيل بواسطة المتصفح.
- التتالي والوراثة: الخصائص المخصصة في CSS تشارك في التتالي وتُورث. متغيرات المعالجات المسبقة ليس لها مفهوم لـ DOM أو التتالي.
- الوصول من JavaScript: يمكن قراءة الخصائص المخصصة في CSS وتعديلها بواسطة JavaScript. لا يمكن الوصول إلى متغيرات المعالجات المسبقة في وقت التشغيل.
- استعلامات الوسائط: يمكن إعادة تعريف الخصائص المخصصة في CSS داخل استعلامات الوسائط ويُطبق التغيير ديناميكيا. متغيرات المعالجات المسبقة المستخدمة في استعلامات الوسائط تنتج قيما ثابتة في وقت الترجمة.
- النطاق: الخصائص المخصصة في CSS محددة النطاق للعناصر وأحفادها. متغيرات المعالجات المسبقة محددة النطاق للكتل أو الملفات.
- دعم المتصفح: تتطلب الخصائص المخصصة في CSS متصفحا حديثا (مدعومة في جميع المتصفحات الحالية). متغيرات المعالجات المسبقة ليس لها متطلبات متصفح لأنها تُترجم إلى CSS قياسية.
- القيم الاحتياطية: تدعم الخصائص المخصصة في CSS القيم الاحتياطية مع
var(). تستخدم متغيرات المعالجات المسبقة صيغة معاملات افتراضية خاصة بالمعالج المسبق.
في الممارسة العملية، تستخدم العديد من الفرق كليهما -- متغيرات المعالجات المسبقة للقيم الثابتة في وقت البناء (مثل تعريفات نقاط التوقف المستخدمة في قواعد @media، والتي لا تستطيع الخصائص المخصصة في CSS القيام بها) والخصائص المخصصة في CSS لأي شيء يحتاج أن يكون ديناميكيا في وقت التشغيل (مثل التخصيص وتخصيص المستخدم ومتغيرات المكونات).
بناء نظام رموز التصميم
رموز التصميم هي القيم الأساسية لنظام التصميم -- الألوان والتباعد والطباعة والظلال والمزيد. الخصائص المخصصة في CSS هي طريقة مثالية لتنفيذ رموز التصميم لأنها توفر نظام رموز مركزي وقابل للصيانة وديناميكي مباشرة في CSS الخاص بك.
مثال: نظام رموز تصميم كامل
:root {
/* ===== رموز الألوان ===== */
/* ألوان أولية (قيم خام) */
--color-blue-50: #eff6ff;
--color-blue-100: #dbeafe;
--color-blue-500: #3b82f6;
--color-blue-600: #2563eb;
--color-blue-700: #1d4ed8;
--color-gray-50: #f9fafb;
--color-gray-100: #f3f4f6;
--color-gray-200: #e5e7eb;
--color-gray-500: #6b7280;
--color-gray-700: #374151;
--color-gray-900: #111827;
--color-green-500: #22c55e;
--color-red-500: #ef4444;
--color-yellow-500: #eab308;
/* ألوان دلالية (مراجع قائمة على الدور) */
--color-primary: var(--color-blue-500);
--color-primary-hover: var(--color-blue-600);
--color-primary-active: var(--color-blue-700);
--color-bg: var(--color-gray-50);
--color-surface: #ffffff;
--color-text: var(--color-gray-900);
--color-text-muted: var(--color-gray-500);
--color-border: var(--color-gray-200);
--color-success: var(--color-green-500);
--color-error: var(--color-red-500);
--color-warning: var(--color-yellow-500);
/* ===== رموز التباعد ===== */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
--space-16: 64px;
/* ===== رموز الطباعة ===== */
--font-sans: 'Inter', 'Segoe UI', sans-serif;
--font-mono: 'Fira Code', 'Courier New', monospace;
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 1.875rem;
--text-4xl: 2.25rem;
--line-height-tight: 1.25;
--line-height-normal: 1.5;
--line-height-relaxed: 1.75;
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-bold: 700;
/* ===== رموز الظلال ===== */
--shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
--shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.15);
/* ===== رموز نصف قطر الحدود ===== */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-full: 9999px;
/* ===== رموز الانتقال ===== */
--duration-fast: 150ms;
--duration-normal: 300ms;
--duration-slow: 500ms;
--easing-default: cubic-bezier(0.4, 0, 0.2, 1);
}
لاحظ النهج ذو المستويين: الرموز الأولية تعرف القيم الخام (مثل --color-blue-500)، بينما الرموز الدلالية تشير إلى الرموز الأولية وتعين معنى (مثل --color-primary). هذا الفصل يجعل التخصيص أسهل -- لإنشاء سمة جديدة، تحتاج فقط لتغيير الرموز الدلالية للإشارة إلى رموز أولية مختلفة.
مثال عملي: تبديل السمة الداكنة/الفاتحة
دعنا نبني تبديل سمة داكنة/فاتحة كامل باستخدام كل ما تعلمناه. يجمع هذا المثال بين الخصائص المخصصة في CSS مع كمية صغيرة من JavaScript لإنشاء مبدل سمات وظيفي بالكامل.
مثال: تنفيذ كامل لتبديل السمة
/* هيكل HTML */
<button id="theme-toggle" aria-label="تبديل الوضع الداكن">
تبديل السمة
</button>
/* CSS */
:root {
--color-bg: #ffffff;
--color-surface: #f8f9fa;
--color-text: #212529;
--color-text-muted: #6c757d;
--color-primary: #0d6efd;
--color-border: #dee2e6;
--color-code-bg: #f1f3f5;
--shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
--transition: 0.3s ease;
}
[data-theme="dark"] {
--color-bg: #0d1117;
--color-surface: #161b22;
--color-text: #c9d1d9;
--color-text-muted: #8b949e;
--color-primary: #58a6ff;
--color-border: #30363d;
--color-code-bg: #1c2128;
--shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
*, *::before, *::after {
transition: background-color var(--transition),
color var(--transition),
border-color var(--transition),
box-shadow var(--transition);
}
body {
background-color: var(--color-bg);
color: var(--color-text);
font-family: system-ui, sans-serif;
line-height: 1.6;
}
.card {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
padding: 24px;
box-shadow: var(--shadow);
}
code {
background-color: var(--color-code-bg);
padding: 2px 6px;
border-radius: 4px;
font-size: 0.9em;
}
/* JavaScript */
const toggle = document.getElementById('theme-toggle');
const html = document.documentElement;
// التحقق من التفضيل المحفوظ أو تفضيل النظام
const savedTheme = localStorage.getItem('theme');
const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (savedTheme) {
html.setAttribute('data-theme', savedTheme);
} else if (systemDark) {
html.setAttribute('data-theme', 'dark');
}
toggle.addEventListener('click', () => {
const current = html.getAttribute('data-theme');
const next = current === 'dark' ? 'light' : 'dark';
html.setAttribute('data-theme', next);
localStorage.setItem('theme', next);
});
مثال عملي: متغيرات المكونات
تسهل الخصائص المخصصة إنشاء متغيرات المكونات دون تكرار الأنماط. إليك مكون شارة بمتغيرات ألوان متعددة، جميعها مدفوعة بمجموعة واحدة من المتغيرات.
مثال: مكون شارة بمتغيرات مدفوعة بالمتغيرات
.badge {
--badge-bg: var(--color-gray-100);
--badge-text: var(--color-gray-700);
--badge-border: var(--color-gray-200);
display: inline-flex;
align-items: center;
padding: 4px 12px;
font-size: var(--text-sm);
font-weight: var(--font-weight-medium);
background-color: var(--badge-bg);
color: var(--badge-text);
border: 1px solid var(--badge-border);
border-radius: var(--radius-full);
}
.badge-primary {
--badge-bg: var(--color-blue-50);
--badge-text: var(--color-blue-700);
--badge-border: var(--color-blue-100);
}
.badge-success {
--badge-bg: #dcfce7;
--badge-text: #15803d;
--badge-border: #bbf7d0;
}
.badge-danger {
--badge-bg: #fef2f2;
--badge-text: #b91c1c;
--badge-border: #fecaca;
}
/* متغيرات الحجم تستخدم أيضا المتغيرات */
.badge-sm {
--badge-font-size: var(--text-xs);
padding: 2px 8px;
font-size: var(--badge-font-size);
}
.badge-lg {
--badge-font-size: var(--text-base);
padding: 6px 16px;
font-size: var(--badge-font-size);
}
التمرين 1: بناء مخصص للسمة
أنشئ صفحة ويب بلوحة تخصيص السمة تتيح للمستخدمين تعديل التصميم في الوقت الفعلي. ابدأ بتعريف مجموعة من الخصائص المخصصة في CSS على :root للون الأساسي ولون الخلفية ولون النص وحجم الخط ونصف قطر الحدود. ابنِ تخطيط صفحة بسيط مع رأس ومكون بطاقة وزر. ثم أنشئ لوحة تخصيص بالعناصر التالية: مدخل لون للون الأساسي وشريط تمرير نطاق لحجم الخط (12px إلى 24px) وشريط تمرير نطاق لنصف قطر الحدود (0px إلى 20px) وزر تبديل للوضع الداكن/الفاتح. استخدم JavaScript لقراءة قيمة كل مدخل وتحديث الخاصية المخصصة المقابلة في CSS باستخدام document.documentElement.style.setProperty(). أضف زر "إعادة التعيين للافتراضيات" يزيل جميع تجاوزات الأنماط المضمنة. احفظ تفضيلات المستخدم في localStorage واستعدها عند تحميل الصفحة.
التمرين 2: نظام رموز تصميم لمكون بطاقة
أنشئ نظام رموز تصميم كامل واستخدمه لبناء مكون بطاقة بمتغيرات متعددة. عرّف ما لا يقل عن 15 خاصية مخصصة على :root تغطي الألوان (الأساسي والثانوي والخلفية والنص والحدود) والتباعد (صغير ومتوسط وكبير) والطباعة (عائلة الخط والحجم الأساسي وحجم العنوان) والظلال (صغير ومتوسط). ابنِ مكون .card يستخدم متغيرات محلية بقيم احتياطية لخلفيته وحشوته وحدوده وظله ولون نصه. أنشئ ما لا يقل عن أربعة متغيرات للبطاقة: بطاقة افتراضية وبطاقة مميزة بحدود ملونة وبطاقة مرتفعة بظل أكبر وبطاقة مدمجة بحشوة مخفضة. ثم أضف سمة داكنة بإعادة تعريف متغيرات الجذر تحت محدد [data-theme="dark"] مع التأكد من أن جميع متغيرات البطاقة الأربعة تتكيف بشكل صحيح. أخيرا، أضف استعلام وسائط يعدل متغيرات التباعد للشاشات الأصغر من 768px.