نظرة عامة أساسية حول كيفية إنشاء نظام ألوان ديناميكي وقابل للضبط
في هذه المشاركة، أريد أن أشارك أفكارًا حول طرق إدارة أنظمة ألوان متعدّدة في CSS. تجربة العرض التوضيحي
إذا كنت تفضّل مشاهدة فيديو، إليك نسخة من هذا المنشور على YouTube:
نظرة عامة
سننشئ نظام ألوان يسهل الوصول إليه باستخدام خصائص مخصّصة وcalc()، وذلك لإنشاء صفحة ويب تتكيّف مع إعدادات المستخدمين المفضّلة مع الحفاظ على تجربة تأليف بسيطة. نبدأ بلون أساسي للعلامة التجارية وننشئ نظامًا من الألوان المتغيرة: لونان للنص و4 ألوان للسطح وظل مطابق.
يبدأ هذا الدليل بتحديد جميع الألوان لكل نظام ألوان مسبقًا. ولا يتم استخدامها لتغيير الصفحة إلا في النهاية.
العلامة التجارية
في كثير من الأحيان، يتم تحديد لون العلامة التجارية مسبقًا ويتم تقديمه بتنسيق
hex أو
rgb. تتضمّن لعبة التحدي هذه التي تستخدم واجهة مستخدم رسومية لونًا أساسيًا للعلامة التجارية، وهو #0af. أولاً، بالنسبة إلى نظام الألوان هذا، يجب تحويل قيمة الرمز السداسي العشري إلى hsl.
* {
--brand: #0af;
--brand: hsl(200 100% 50%);
}
من أجل إتاحة مفهوم تعتيم لون العلامة التجارية أو تفتيحه، بنسبة %20 مثلاً، يجب استخراج القنوات الثلاث لقيمة لون hsl إلى خصائص مخصّصة خاصة بها، على النحو التالي:
* {
--brand-hue: 200;
--brand-saturation: 100%;
--brand-lightness: 50%;
}
يمكن أن تنفّذ CSS عمليات حسابية على خصائص الألوان هذه، مثل calc(var(--brand-lightness) -
20%) لخفض قيمة السطوع بنسبة %20. هذا أمر أساسي لإنشاء نظام ألوان، إذ يمكن أن يحافظ CSS على جميع الألوان في مجموعة الألوان نفسها من خلال تعديل مقادير التشبع والسطوع في نظام hsl.
مظهر فاتح
سيتم وضع علامة على كل خيار منتج بلون مع نظام الألوان المطابق، وفي هذه الحالة، سيتم إلحاق -light بكل خيار.

العلامة التجارية
بدءًا بلون العلامة التجارية، تتم إعادة إنشائه من خلال تضمين الخصائص المخصّصة --brand-hue و--brand-saturation و--brand-lightness داخل أقواس الدالة hsl ()، بدون إجراء أي عمليات حسابية:
* {
--brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}
ألوان النص
بعد ذلك، يجب أن تتضمّن أساسيات نظام الألوان ألوان النصوص. في المظهر الفاتح، يجب أن يكون النص داكنًا جدًا. لاحظ كيف أنّ درجة سطوع الألوان التالية منخفضة، أي أقل بكثير من %50.
* {
--text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
--text2-light: hsl(var(--brand-hue) 30% 30%);
}
--text1-light، بما أنّ درجة الإضاءة تكون منخفضة جدًا عند% 10، يتم الحفاظ على التشبع العالي بنسبة %100، وبالتالي يمكن أن يظهر لون العلامة التجارية بشكل خفيف في اللون الكحلي الداكن جدًا.
--text2-light، هذا اللون ليس داكنًا تمامًا مثل اللون الأول، وهذا أمر جيد لأنّه لون ثانوي، كما أنّه أقل تشبّعًا بكثير.
ألوان السطح
ألوان السطح هي الخلفيات والحدود والأسطح الزخرفية الأخرى التي يظهر النص عليها أو بداخلها. في المظهر الفاتح، تكون هذه الألوان فاتحة، على عكس ألوان النص التي تكون داكنة. لإنشاء ألوان فاتحة باستخدام hsl، سنستخدم قيمًا أعلى للنسبة المئوية في قيمة السطوع الثالثة. سنقلّل أيضًا من درجة التشبع، كي لا تبدو درجات الرمادي الفاتحة ملوّنة جدًا.
* {
--surface1-light: hsl(var(--brand-hue) 25% 90%);
--surface2-light: hsl(var(--brand-hue) 20% 99%);
--surface3-light: hsl(var(--brand-hue) 20% 92%);
--surface4-light: hsl(var(--brand-hue) 20% 85%);
}
تم إنشاء 4 ألوان للأسطح لأنّ الألوان الزخرفية تميل إلى الحاجة إلى المزيد من الأشكال المختلفة، وذلك للحالات التفاعلية مثل :focus أو :hover أو لإنشاء مظهر الطبقات الورقية. في هذه السيناريوهات، من الجيد الانتقال
من --surface2-light عند التمرير إلى --surface3-light، ما يؤدي إلى زيادة التباين عند التمرير (من 99% سطوع إلى 92% سطوع، ما يجعلها أغمق).
الظلال
تُعد الظلال ضمن نظام الألوان ميزة إضافية، ولكنّها تضفي طابعًا واقعيًا على التأثير وتساعده في التميّز عن الظلال غير الواقعية المستندة إلى اللون الأسود. لتحقيق ذلك، سيتم استخدام السمة المخصّصة "تدرّج اللون" في لون الظل، وسيكون اللون مشبعًا قليلاً بالتدرّج اللوني ولكن سيظل داكنًا جدًا. ويتم ذلك بشكل أساسي من خلال إنشاء ظل داكن جدًا يميل إلى اللون الأزرق.
* {
--surface-shadow-light: var(--brand-hue) 10% 20%;
--shadow-strength-light: .02;
}
لم يتم تضمين --surface-shadow-light في دالة hsl. ويرجع ذلك إلى أنّه سيتم دمج القيمة --shadow-strength لإنشاء بعض التعتيم، ويحتاج CSS إلى الأجزاء من أجل إجراء العمليات الحسابية. انتقِل إلى قسم الظل الدائري لمعرفة المزيد.
الألوان الفاتحة معًا
لا داعي للبحث عن طريقة إنشاء أي من الألوان الفاتحة، فهي كلها في مكان واحد في CSS.
* {
--brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
--text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
--text2-light: hsl(var(--brand-hue) 30% 30%);
--surface1-light: hsl(var(--brand-hue) 25% 90%);
--surface2-light: hsl(var(--brand-hue) 20% 99%);
--surface3-light: hsl(var(--brand-hue) 20% 92%);
--surface4-light: hsl(var(--brand-hue) 20% 85%);
--surface-shadow-light: var(--brand-hue) 10% calc(var(--brand-lightness) / 5);
--shadow-strength-light: .02;
}
مظهر داكن
لا تبدأ معظم العلامات التجارية بمظهر داكن، بل يكون المظهر الداكن أحد أشكال المظهر الأساسي، ويكون عادةً أفتح. في المقابل، يختار المستخدمون غالبًا مظهرًا داكنًا في سياقات مختلفة، مثل الليل. وقد دفعتني هذه العوامل إلى مراعاة أمرين عند تصميم المظاهر الداكنة:
- لن يظهر للمستخدمين عادةً أي ضوء أثناء استخدام هذا المظهر، لذا ننصحك باختباره في الظلام.
- يجب أن تكون الألوان غير مشبّعة كي لا تهتز على الشاشة بسبب شدتها المفرطة.

العلامة التجارية
استخدم المظهر الفاتح قيم قنوات ألوان hsl الثلاث الخاصة بالعلامة التجارية بدون تغيير، بينما لم يستخدم المظهر الداكن هذه القيم. يتم خفض التشبع إلى النصف وتقليل درجة السطوع بنسبة 50% تقريبًا.
* {
--brand-dark: hsl(
var(--brand-hue)
calc(var(--brand-saturation) / 2)
calc(var(--brand-lightness) / 1.5)
);
}
ألوان النص
في المظهر الداكن، يجب أن تكون ألوان النص فاتحة. تحتوي الألوان التالية على قيم عالية للسطوع، ما يجعلها أقرب إلى اللون الأبيض.
* {
--text1-dark: hsl(var(--brand-hue) 15% 85%);
--text2-dark: hsl(var(--brand-hue) 5% 65%);
}
ألوان السطح
في المظهر الداكن، يجب أن تكون ألوان السطح داكنة. تتضمّن الألوان التالية درجة سطوع وتشبع منخفضة، حيث يكون السطح الأول هو الأغمق بنسبة %10.
* {
--surface1-dark: hsl(var(--brand-hue) 10% 10%);
--surface2-dark: hsl(var(--brand-hue) 10% 15%);
--surface3-dark: hsl(var(--brand-hue) 5% 20%);
--surface4-dark: hsl(var(--brand-hue) 5% 25%);
}
الظلال
في المظهر الداكن، قد يكون من الصعب جدًا رؤية الظلال. وهذا منطقي لأنّه يصعب
تعتيم شيء مظلم بالفعل. وهنا يأتي دور
--shadow-strength-dark الذي يتيح لنا تعتيم الظلال
من خلال تغيير متغيّر واحد.
* {
--surface-shadow-dark: var(--brand-hue) 50% 3%;
--shadow-strength-dark: .8;
}
انظر أيضًا إلى مقدار التشبع في هذا الظل. هل يمكنك ملاحظة اللون عند النظر إلى الواجهة؟ جرِّب إزالة التشبع من أدوات المطوّرين، أيّهما تفضّل؟
الألوان الداكنة معًا
* {
--brand-dark: hsl(var(--brand-hue) calc(var(--brand-saturation) / 2) calc(var(--brand-lightness) / 1.5));
--text1-dark: hsl(var(--brand-hue) 15% 85%);
--text2-dark: hsl(var(--brand-hue) 5% 65%);
--surface1-dark: hsl(var(--brand-hue) 10% 10%);
--surface2-dark: hsl(var(--brand-hue) 10% 15%);
--surface3-dark: hsl(var(--brand-hue) 5% 20%);
--surface4-dark: hsl(var(--brand-hue) 5% 25%);
--surface-shadow-dark: var(--brand-hue) 50% 3%;
--shadow-strength-dark: .8;
}
المظهر الخافت
يركّز نظام الألوان هذا على تنسيق الإضاءة والتشبّع. يجب أن يكون التشبع كافيًا لكي يظل اللون مرئيًا، ولكن يجب أيضًا أن يحقق نتائج التباين بالكاد، لأنّه من المفترض أن يكون باهتًا ومنخفض التباين على أي حال.

العلامة التجارية
* {
--brand-dim: hsl(
var(--brand-hue)
calc(var(--brand-saturation) / 1.25)
calc(var(--brand-lightness) / 1.25)
);
}
ألوان النص
* {
--text1-dim: hsl(var(--brand-hue) 15% 75%);
--text2-dim: hsl(var(--brand-hue) 10% 61%);
}
ألوان السطح
* {
--surface1-dim: hsl(var(--brand-hue) 10% 20%);
--surface2-dim: hsl(var(--brand-hue) 10% 25%);
--surface3-dim: hsl(var(--brand-hue) 5% 30%);
--surface4-dim: hsl(var(--brand-hue) 5% 35%);
}
الظلال
* {
--surface-shadow-dim: var(--brand-hue) 30% 13%;
--shadow-strength-dim: .2;
}
تعتيم الألوان كلها معًا
* {
--brand-dim: hsl(var(--brand-hue) calc(var(--brand-saturation) / 1.25) calc(var(--brand-lightness) / 1.25));
--text1-dim: hsl(var(--brand-hue) 15% 75%);
--text2-dim: hsl(var(--brand-hue) 10% 61%);
--surface1-dim: hsl(var(--brand-hue) 10% 20%);
--surface2-dim: hsl(var(--brand-hue) 10% 25%);
--surface3-dim: hsl(var(--brand-hue) 5% 30%);
--surface4-dim: hsl(var(--brand-hue) 5% 35%);
--surface-shadow-dim: var(--brand-hue) 30% 13%;
--shadow-strength-dim: .2;
}
ألوان يسهل الوصول إليها
لاحظ أنّ أدنى درجة سطوع في مجموعة ألوان النص الداكنة هي% 65، وأعلى درجة سطوع في المساحات الداكنة هي %25. هذا يعني أنّ هناك فرقًا بنسبة% 40 في درجة السطوع بينهما. في المظهر الفاتح، تبلغ مساحة التباعد بين العناصر 55%. يمكن أن يساعد الحفاظ على اختلافات السطوع بين ألوان النص وألوان الخلفية عند مستوى يتراوح بين 40 و50% في الحفاظ على نسب تباين الألوان عالية، كما يمكن أن يكون ذلك عاملاً دقيقًا يمكن تعديله في حال كانت النتائج ضعيفة.
أسمّي هذه العملية "الضغط المتكرر حتى النجاح"، وهي تتضمّن الضغط بشكل متكرر على قيمة السطوع إلى أن تشير إحدى الأدوات إلى أنّني اجتزت الاختبار.
تحصل كل سمة تم إنشاؤها في هذا التحدي على نتائج جيدة في اختبار التباين. يتميّز نظام الألوان الداكنة بأقل تباين بينها، ولكنّه لا يزال يستوفي الحد الأدنى من المتطلبات. لمساعدة الآخرين في الفريق على استخدام ألوان متناقضة بشكل جيد، من المستحسن إنشاء اسم فئة يجمع بين لون السطح ولون النص الذي يمكن الوصول إليه.
.surface1 {
background-color: var(--surface1);
color: var(--text2);
}
.surface2 {
background-color: var(--surface2);
color: var(--text2);
}
.surface3 {
background-color: var(--surface3);
color: var(--text1);
}
.surface4 {
background-color: var(--surface4);
color: var(--text1);
}
Rad Shadow
تستخدم المظاهر فئة أداة مساعدة تُسمى .rad-shadow. تم إنشاء هذا الظل
باستخدام أداة الظل الناعم، وأنا أقدّر ذلك كثيرًا. أخذت المقتطف الذي تم إنشاؤه وعدّلته باستخدام الألوان الخاصة بي وحسابات الشفافية. كان الهدف من ذلك هو إنشاء ظل يمكنني تعديله
ضمن كل نظام ألوان.

لتحقيق ذلك، أنشأتُ متغيرَين لكل نظام ألوان يمكن تعديله، وهما لون الظل وقوة الظل. يُستخدم اللون لضبط تشبُّع اللون ودرجة الداكن، بينما تُستخدم القوة لتسهيل زيادة كثافة الظل عند استخدام نظام ألوان داكنة. كانت النتيجة النهائية على النحو التالي.
:root {
--surface-shadow-light: var(--brand-hue) 10% 20%;
--shadow-strength-light: .02;
}
.rad-shadow {
box-shadow:
0 2.8px 2.2px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
0 6.7px 5.3px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .01)),
0 12.5px 10px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
0 22.3px 17.9px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
0 41.8px 33.4px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
0 100px 80px hsl(var(--surface-shadow) / var(--shadow-strength))
;
}
إذا أردت استخدام المزيد من الظلال في نظام الألوان، سأجعل زوايا الظلال ثابتة أيضًا في رمز التصميم، لأنّ اتجاه الضوء يجب أن يكون هو نفسه بين جميع الظلال في التصميم.
استخدام أنظمة الألوان
بعد الانتهاء من تحديد الألوان مسبقًا، حان الوقت لتحويلها إلى خصائص مستقلة عن المخطط. أقصد أنّه نادرًا ما يحتاج مطوّر CSS إلى الوصول إلى قيمة نظام ألوان معيّن ضمن مشروع نظام الألوان هذا. أريد أن أسهّل عليك البقاء ضمن الموضوع.
لتحقيق ذلك، يجب استخدام نظام الألوان حصريًا من خلال الخصائص المخصّصة العامة التي سنحدّدها بعد قليل. بهذه الطريقة، لن يحتاج المستخدمون إلى القلق بشأن نظام الألوان المضبوط حاليًا، بل عليهم استخدام ألوان المساحة والنص. بدلاً من
color: var(--text1-light) استخدِم color: var(--text1). يتم تنفيذ جميع عمليات التكيّف والتغيير
في الألوان على مستوى أعلى بكثير في CSS.
عند التمعّن في المظهر الفاتح، نجد أنّ الأنماط الرابطة في كتلة الرمز البرمجي التالية
تربط خاصية مخصّصة عامة باللون الخاص بالمظهر الفاتح. ستستخدم الآن جميع
استخدامات var(--brand) لون العلامة التجارية الفاتح.
المظهر الفاتح (تلقائي)
:root {
color-scheme: light;
--brand: var(--brand-light);
--text1: var(--text1-light);
--text2: var(--text2-light);
--surface1: var(--surface1-light);
--surface2: var(--surface2-light);
--surface3: var(--surface3-light);
--surface4: var(--surface4-light);
--surface-shadow: var(--surface-shadow-light);
--shadow-strength: var(--shadow-strength-light);
}
يستخدم الموقع الإلكتروني الآن المظهر الفاتح. هذه لحظة نجاح ممتعة للغاية. لنستعرض المزيد من هذه اللحظات أثناء استخدام ألواننا المحدّدة مسبقًا في سياقات أخرى لنظام الألوان.
المظهر الداكن (تلقائي)
@media (prefers-color-scheme: dark) {
:root {
color-scheme: dark;
--brand: var(--brand-dark);
--text1: var(--text1-dark);
--text2: var(--text2-dark);
--surface1: var(--surface1-dark);
--surface2: var(--surface2-dark);
--surface3: var(--surface3-dark);
--surface4: var(--surface4-dark);
--surface-shadow: var(--surface-shadow-dark);
--shadow-strength: var(--shadow-strength-dark);
}
}
مظهر فاتح
[color-scheme="light"] {
color-scheme: light;
--brand: var(--brand-light);
--text1: var(--text1-light);
--text2: var(--text2-light);
--surface1: var(--surface1-light);
--surface2: var(--surface2-light);
--surface3: var(--surface3-light);
--surface4: var(--surface4-light);
--surface-shadow: var(--surface-shadow-light);
--shadow-strength: var(--shadow-strength-light);
}
مظهر داكن
[color-scheme="dark"] {
color-scheme: dark;
--brand: var(--brand-dark);
--text1: var(--text1-dark);
--text2: var(--text2-dark);
--surface1: var(--surface1-dark);
--surface2: var(--surface2-dark);
--surface3: var(--surface3-dark);
--surface4: var(--surface4-dark);
--surface-shadow: var(--surface-shadow-dark);
--shadow-strength: var(--shadow-strength-dark);
}
المظهر الخافت
[color-scheme="dim"] {
color-scheme: dark;
--brand: var(--brand-dim);
--text1: var(--text1-dim);
--text2: var(--text2-dim);
--surface1: var(--surface1-dim);
--surface2: var(--surface2-dim);
--surface3: var(--surface3-dim);
--surface4: var(--surface4-dim);
--surface-shadow: var(--surface-shadow-dim);
--shadow-strength: var(--shadow-strength-dim);
}
في هذه المرحلة، يمكن للمؤلفين استخدام العناصر العامة لنظام الألوان المقدَّم حسب الحاجة، ولن يحتاجوا إلى القلق بشأن المظاهر مرة أخرى.
الخاتمة
بعد أن عرفت كيف فعلت ذلك، كيف كنت ستتصرف؟ 🙂
لنستكشف الطرق المختلفة لإنشاء المحتوى على الويب. يمكنك إنشاء عرض توضيحي على Codepen أو استضافة عرضك التوضيحي الخاص، ثم إرسال تغريدة إليّ تتضمّن العرض، وسأضيفه إلى قسم "ريمكسات من المنتدى" أدناه.
المصدر
ريمكسات من إنشاء المنتدى
- أضاف @chris-kruining شريط تمرير لتعديل درجة اللون،
وألوان الحالة وأوضاع التباين لـ no-preference وmore وless:
عرض توضيحي.