بناء نظام ألوان

نظرة عامة أساسية حول كيفية إنشاء نظام ألوان ديناميكي وقابل للتهيئة

في هذه المشاركة، أرغب في مشاركة الأفكار حول طرق إدارة أنظمة الألوان المتعددة في 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 إلى الأجزاء من أجل إجراء العمليات الحسابية. انتقل إلى قسم Rad shadow لمعرفة المزيد.

الألوان الفاتحة معًا

لا داعي للبحث عن طريقة صناعة أي من ألوان الإضاءة، فكل هذه الألوان متوفرة في مكان واحد على 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;
}
لقطة شاشة للألوان الفاتحة معًا
Sandbox على CodePen

مظهر داكن

لا تبدأ معظم العلامات التجارية بمظهر داكن، بل هو شكل مختلف من المظهر الأساسي، وعادة ما يكون أفتح. من ناحية أخرى، غالبًا ما يختار المستخدمون مظهرًا داكنًا لسياقات مختلفة، مثل الليل. دفعتني هذه العوامل إلى وضع شيئين في الاعتبار مع الموضوعات المظلمة:

  1. سيكون المستخدمون بشكل عام في الظلام أثناء استخدام هذا المظهر، لذا أجرِ الاختبار في الظلام.
  2. يجب أن يتم إلغاء تشبع الألوان بحيث لا تهتز على الشاشة لأنها مبالغة في شدة.

معاينة للنتيجة النهائية للمظهر الداكن

علامة تجارية

استخدم المظهر الفاتح قيم قنوات الألوان الثلاث 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;
}

انظر أيضًا إلى مقدار التشبع في هذا الظل. هل يمكنك ملاحظة اللون عند النظر إلى الواجهة؟ حاول إزالة التشبع من أدوات devtools، أيهما تفضل؟!

الألوان الداكنة معًا

* {
  --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;
}
لقطة شاشة للألوان الداكنة معًا
Sandbox على CodePen

تعتيم المظهر

يدور نظام الألوان هذا حول تنسيق الإضاءة والتشبع. يجب أن يكون هناك تشبع كافٍ لإظهار تدرج اللون، ولكن بالكاد يجب أن يجتاز درجات التباين لأنه يُفترض أن يكون معتمًا ومنخفضًا على أي حال.

معاينة النتائج النهائية من المظهر الخافت

علامة تجارية

* {
  --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;
}
لقطة شاشة للألوان الداكنة معًا
Sandbox على CodePen

ألوان يسهل الوصول إليها

لاحظ كيف يبلغ أدنى إضاءة في مجموعة ألوان النص الداكن 65% وأعلى درجة إضاءة في الأسطح الداكنة تبلغ 25%. هذا يعني 40٪ من مساحة التنفّس بينهما. في المظهر الفاتح، هناك غرفة تنفس بنسبة 55٪ في المظهر الفاتح. يمكن أن يساعد الحفاظ على اختلافات الإضاءة بين ألوان النص والسطح بحوالي 40-50٪ في الحفاظ على ارتفاع نسب تباين الألوان، بينما يكون أيضًا رافعًا بسيطًا لتعديله في حالة انخفاض الدرجات.

أسميه "bump bump till ya Pass"، وهي تفاعل مع قيمة الإضاءة حتى تدل الأداة على أنني أمرر.

يتم الضغط على Shift + السهم المتّجه للأسفل لخفض الإضاءة وزيادة التباين إلى أن يتم التمرير سريعًا

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

.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);
}
لقطة شاشة للسطح الخافت وأزواج النصوص
لقطة شاشة للسطح الخافت وعمليات إقران النصوص مع VisBug

ظل رادار

تستخدم المظاهر فئة أدوات تُسمى .rad-shadow. تم إنشاء هذا الظل باستخدام أداة Smooth 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: عرض توضيحي.