بنية اللون النسبية لـ CSS

إنشاء ألوان جديدة بناءً على قنوات وقيم لون آخر.

Adam Argyle
Adam Argyle

يُعد Chrome 119 ميزة ألوان فعالة جدًا من المستوى 5 من لون CSS. ينشئ بناء جملة الألوان النسبي مسارًا سلسًا لمعالجة الألوان داخل CSS، مما يوفر طرقًا للمؤلفين والمصممين من أجل:

قبل بناء جملة اللون النسبي، لتعديل تعتيم اللون، تحتاج إلى إنشاء خصائص مخصصة لقنوات اللون، عادة HSL، وتجميعها في لون نهائي ولون صيغة نهائي. هذا يعني إدارة الكثير من القطع الملونة، والتي يمكن أن تصبح مرهقة بسرعة.

:root {
  --brand-hue: 300deg;
  --brand-saturation: 75%;
  --brand-lightness: 50%;

  --brand-hsl:
    var(--brand-hue)
    var(--brand-saturation)
    var(--brand-lightness);

  --brand-color: hsl(var(--brand-hsl));

  /* all this work just so I can set the opacity to 50% in a variant */
  --brand-color-variant: hsl(var(--brand-hsl) / 50%);
}

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

:root {
  --brand-color: hsl(300deg 75% 50%);
  --brand-color-variant: hsl(from var(--brand-color) h s l / 50%);
}

ستساعدك هذه المشاركة في التعرّف على البنية وتوضيح كيفية معالجة الألوان الشائعة.

وإذا كنت تفضل الفيديو، فإن جميع المقالات التالية تقريبًا تتناولها في تحدي واجهة المستخدم الرسومية هذا.

نظرة عامة على البنية

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

يُظهر
رسم تخطيطي لبناء جملة أحمر أخضر أزرق(من اللون الأخضر r g b / alpha) مع سهم يتحرّك أعلى اللون الأخضر وينحني إلى بداية الدالة rgb،
ينقسم هذا السهم إلى 4 أسهم تشير بعد ذلك إلى المتغير ذي الصلة. الأسهم الأربعة هي الأحمر والأخضر والأزرق وألفا. قيمة 0، باللون الأحمر والأزرق هي 128، وألفا 100٪.

يوضّح المخطّط السابق اللون الأصلي green الذي يتم تحويله إلى مساحة اللون للون الجديد، ثم يتم تحويله إلى أرقام فردية يتم تمثيلها كمتغيرات r وg وb وalpha، وسيتم استخدامها بعد ذلك مباشرةً كقيم لون rgb() جديدة.

رغم أن هذه الصورة تعرض التقسيم والعملية والمتغيرات، إلا أنها لا تغير اللون أيضًا. تتم إعادة المتغيرات إلى اللون دون تغيير، مما يؤدي إلى استمرار اللون الأخضر.

الكلمة الرئيسية from

الجزء الأول من بناء الجملة المطلوب للتعلم هو إضافة الجزء from <color> لتحديد اللون. يذهب مباشرة قبل تحديد القيم. إليك مثال على الرمز البرمجي حيث أنّ كل ما تمت إضافته هو from green قبل تحديد قيم rgb() مباشرةً.

.syntax-introduction_same-colors {
  color: green;
  color: rgb(0 128 0);
  color: rgb(from green r g b);    /* result = rgb(0 128 0) */
}

عندما تكون الكلمة الرئيسية from هذه هي المَعلمة الأولى في الترميز الوظيفي، تحوّل تعريف اللون إلى لون نسبي. بعد الكلمة الرئيسية from، تتوقّع CSS لونًا، وهو لون يشكِّل مصدر إلهام باللون التالي.

تحويل الألوان

وبعبارات أبسط، فهي تحول اللون الأخضر إلى قنوات r g وb لاستخدامها بلون جديد.

rgb(from green r g b)           /* r=0 g=128 b=0 */
rgb(from rgb(0 128 0) r g b);   /* r=0 g=128 b=0 */

الألوان من المواقع المخصّصة

قراءة rgb from green واضحة جدًا وسهلة الفهم. هذا هو السبب في أنّ السمات المخصّصة وبناء بنية اللون النسبي تجعل هذه التطابق رائعًا، لأنه بإمكانك التخلص من اللغز من لون from. ولا تحتاج أيضًا بشكل عام إلى معرفة تنسيق اللون للون الخاصية المخصّصة، حيث إنك تنشئ لونًا جديدًا بالتنسيق الذي تختاره.

rgb(from rgb(255 105 180) r g b) /* ????? */
rgb(from var(--hotpink) r g b)   /* clear */

العمل في مساحة اللون المفضلة لديك

يمكنك اختيار مساحة اللون مع اختيارك لتدوين اللون الوظيفي.

rgb(from hsl(120 100% 25%) r g b)     /*  r=0   g=128  b=0    */
hsl(from hsl(120 100% 25%) h s l)     /*  h=120 s=100% l=25%  */
hwb(from hsl(120 100% 25%) h w b)     /*  h=120 w=0%   b=50%  */
lch(from hsl(120 100% 25%) l c h)     /*  l=46  c=68   h=134  */

وتتضمّن بنية اللون النسبية خطوة التحويل هذه، ويتم تحويل اللون بعد from إلى مساحة اللون كما هو محدّد في بداية اللون النسبي. لا يلزم أن يتطابق المدخلات والمخرجات، وهو ما يتيح قدرًا كبيرًا من الحرية.

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

مزج المتغيّرات ومطابقتها وحذفها وتكرارها

هناك شيء غريب ولكنه مثير حول بناء الجملة هذا، وهو أنه ليس من الضروري ترتيب المتغيرات ويمكن تكرارها.

rgb(from green g g g)    /* rgb(128 128 128) */
rgb(from green b r g)    /* rgb(0 0 128) */
rgb(from green 0 0 g)    /* rgb(0 0 128) */

التعتيم كمتغير

ويوفر بناء الجملة أيضًا معدل الشفافية كمتغير يسمى alpha. إنّه اختياري ويتبع / في تدوين اللون الوظيفي.

rgb(from #00800080 r g b / alpha)             /* alpha=50% */
rgb(from rgba(0,128,0,.5) r g b / alpha)      /* alpha=50% */
rgb(from rgb(0 128 0 / 50%) r g b / alpha)    /* alpha=50% */

استخدم calc() أو دوال CSS أخرى على المتغيرات

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

green                              /*  h=120 s=100% l=25%  */
hsl(from green calc(h * 2) s l)    /*  h=240 s=100% l=25%  */

الجوّ البحري الآن وقد تمت مضاعفة درجة اللون، مع تدرج لونها 120 وتحويلها إلى 240، ما أدى إلى تغيير اللون تمامًا. أدّى ذلك إلى تدوير تدرج اللون على عجلة الألوان، وهي خدعة متقنة تم تنفيذها بشكل بسيط للغاية باستخدام مساحات ألوان أسطوانية مثل HSL وHWB وLCH وOKLCH.

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

التحقّق من توافق المتصفّح

@supports (color: rgb(from white r g b)) {
  /* safe to use relative color syntax */
}

حالات الاستخدام والعروض التوضيحية

تحتوي الأمثلة وحالات الاستخدام التالية على العديد من التراكيب البديلة لتحقيق نتائج مماثلة أو واحدة. تأتي الاختلافات من مساحات الألوان والقنوات التي تقدمها.

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

ويمكن العثور على كل العروض التوضيحية في مجموعة Codepen هذه.

تفتيح لون

توفّر مساحات الألوان OKLCH أو OKLAB أو XYZ أو sRGB النتائج الأكثر توقّعًا عند تفتيح الألوان.

تخفيف التغيير بمقدار كمية

في المثال التالي، سيأخذ .lighten-by-25 اللون blue ويحوّله إلى OKLCH، ثم تضيء إعدادات اللون الأزرق بزيادة قناة l (الإضاءة) من خلال ضرب القيمة الحالية في 1.25. يؤدي ذلك إلى دفع الإضاءة الزرقاء نحو اللون الأبيض بنسبة 25٪.

.lighten-by-25 {
  background: oklch(from blue calc(l * 1.25) c h);
}

التخفيف إلى قيمة معينة

لا يستخدم المثال التالي .lighten-to-75 القناة l لتحسين blue، بل يتم استبدال القيمة بالكامل بـ 75%.

.lighten-to-75 {
  background: oklch(from blue 75% c h);
}

تعتيم لون

مساحات اللون نفسها فعالة في تفتيح اللون، رائعة أيضًا لتعتيم اللون.

زيادة درجة التعتيم إلى حد ما

في المثال التالي، يأخذ .darken-by-25 اللون الأزرق ويحوّله إلى OKLCH، ثم يجعله غامقًا من خلال تقليل قناة l (الإضاءة) بنسبة 25% من خلال ضرب القيمة في .75. يؤدي هذا إلى دفع اللون الأزرق باتجاه الأسود بنسبة 25٪.

.darken-by-25 {
  background: oklch(from blue calc(l * .75) c h);
}

التعتيم إلى قيمة محددة

لا يستخدم المثال التالي .darken-to-25 قناة l لزيادة تعتيم blue، بل يتم استبدال القيمة بالكامل بـ 25%.

.darken-to-25 {
  background: oklch(from blue 25% c h);
}

تشبع لون

التشبع بمقدار كمية

في المثال التالي، يستخدم .saturate-by-50 العنصر s من hsl() لزيادة حيوية orchid باستخدام 50% نسبيًا.

.saturate-by-50 {
  background: hsl(from orchid h calc(s * 1.5) l);
}

التشبع إلى مقدار محدد

لا يستخدم المثال التالي .saturate-to-100 القناة s من hsl()، بل يتم تحديد قيمة التشبع المطلوبة بدلاً من ذلك. في هذا المثال، يتم رفع التشبع إلى 100%.

.saturate-to-100 {
  background: hsl(from orchid h 100% l);
}

إلغاء تشبُّع اللون

إلغاء التشبع بمقدار مبلغ

في المثال التالي، يستخدم .desaturate-by-half العنصر s من hsl() لخفض تشبُّع indigo بمقدار النصف.

.desaturate-by-half {
  background: hsl(from indigo h calc(s / 2) l);
}

إلغاء التشبُّع إلى قيمة محدَّدة

بدلاً من إلغاء التشبع بمقدار كمية، يمكنك إلغاء التشبع إلى قيمة محددة مطلوبة. في المثال التالي، يتم إنشاء لون جديد من النوع .desaturate-to-25 استنادًا إلى indigo، لكن يتم ضبط التشبع على 25%.

.desaturate-to-25 {
  background: hsl(from indigo h 25% l);
}

تعزيز اللون اللوني

يشبه هذا التأثير تشبع اللون ولكنه يختلف بطريقتين. أولاً، هذا التغيير هو chroma وليس saturation، وذلك لأنّ مساحات الألوان التي يمكن أن تزيد إلى نطاق ديناميكي عالي لا تستخدم التشبع. مساحات الألوان التي تتضمّن chroma قادرة على استخدام النطاق الديناميكي العالي، ما يسمح للمؤلفين بتعزيز حيوية الألوان أكثر من التشبع.

.increase-chroma {
  background: oklch(from orange l calc(c + .1) h);
}

ضبط مستوى تعتيم اللون

يعد إجراء متغير شبه شفاف للون أحد أكثر تعديلات اللون شيوعًا التي تم إجراؤها في أنظمة التصميم. شاهد المثال في مقدمة هذه المقالة إذا فاتك هذا، فإنها تحدد مساحة المشكلة بشكل جيد حقًا.

ضبط التعتيم بمقدار مبلغ

.decrease-opacity-by-25 {
  background: rgb(from lime r g b / calc(alpha / 2));
}

ضبط التعتيم على قيمة محدّدة

.decrease-opacity-to-25 {
  background: rgb(from lime r g b / 25%);
}

قلب اللون

ميزة "قلب الألوان" هي دالة شائعة لضبط الألوان في مكتبات الألوان. تتمثل إحدى طرق تحقيق ذلك في تحويل لون إلى نموذج أحمر أخضر أزرق ثم طرح قيمة كل قناة من 1.

.invert-each-rgb-channel {
  background: rgb(from yellow calc(255 - r) calc(255 - g) calc(255 - b));
}
.

استكمال اللون

إذا لم يكن هدفك قلب اللون بل مكملته، فمن المحتمل أن يكون تدوير تدرج اللون هو ما تبحث عنه. اختر مساحة لون تعرض تدرج اللون كزاوية، ثم استخدِم calc() لتدوير تدرج اللون بمقدار المقدار الذي تريده. يتم العثور على تكامل للون من خلال التدوير بمقدار نصف دورة، وفي هذه الحالة يمكنك جمع أو طرح قيمة من قناة h بمقدار 180 للحصول على النتيجة.

.complementary-color {
  background: hsl(from blue calc(h + 180) s l);
}

تباين اللون

كطريقة لتحقيق نسب تباين الألوان التي يمكن الوصول إليها، ضع في الاعتبار L&ميدast; (Lstar). من خلال هذا الإجراء، يتم استخدام قناة الإضاءة نفسها (L) (تقريبًا) من LCH وOKLCH في calc(). اعتمادًا على ما إذا كنت تستهدف التباين المنخفض أو المتوسط أو العالي، تكون قيمة دلتا الدلتا حوالي 40 أو 50 أو 60 تقريبًا.

تعمل هذه التقنية بشكل جيد عبر أي تدرج لوني في LCH أو OKLCH.

تباين مع لون أغمق

توضح الفئة .well-contrasting-darker-color L* بدلتا 60. بما أن اللون الأصلي هو لون داكن (إضاءة منخفضة القيمة)، تتم إضافة %60 (.6) إلى قناة الإضاءة. تُستخدم هذه التقنية للعثور على تدرُّج لون النص الداكن المتباين جيدًا ونفس اللون على خلفية فاتحة.

.well-contrasting-darker-color {
  background: darkred;
  color: oklch(from darkred calc(l + .60) c h);
}

التباين مع لون أفتح

توضح الفئة .well-contrasting-lighter-color أيضًا L* بدلتا بنسبة 60%. نظرًا لأن اللون الأصلي هو لون فاتح (إضاءة عالية القيمة)، يتم خفض 60. من قناة الإضاءة.

.well-contrasting-lighter-color {
  background: lightpink;
  color: oklch(from lightpink calc(l - .60) c h);
}

ألواح الألوان

بناء جملة الألوان النسبي جيد جدًا في إنشاء لوحات الألوان. إنها مفيدة وقوية بشكل خاص بسبب عدد مساحات الألوان المتاحة. تستخدم جميع الأمثلة التالية OKLCH نظرًا لأن قناة الإضاءة موثوقة ويمكن تدوير قناة hue بدون أي آثار جانبية. يوضح المثال الأخير مزيجًا من تعديلات الإضاءة ودوران تدرج اللون للحصول على نتيجة أكثر إثارة للاهتمام!

افتح نموذج رمز المصدر لهذه اللوحات وحاوِل تغيير --base-color للاطّلاع على مدى ديناميكية هذه اللوحات. إنه أمر ممتع!

إذا أعجبك الفيديو، سأقدّم معلومات مفصّلة حول إنشاء لوحات ألوان في CSS باستخدام OKLCH على YouTube.

لوحات ألوان أحادية اللون

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

:root {
  --base-color: deeppink;

  --color-0: oklch(from var(--base-color) calc(l + .20) c h); /* lightest */
  --color-1: oklch(from var(--base-color) calc(l + .10) c h);
  --color-2: var(--base-color);
  --color-3: oklch(from var(--base-color) calc(l - .10) c h);
  --color-4: oklch(from var(--base-color) calc(l - .20) c h); /* darkest */
}
جرب مجموعة من لوحات الألوان المصنوعة من بنية ألوان نسبية وOKLCH

Open Props، وهي مكتبة تضمّ متغيرات CSS المجانية، وتوفّر لوحات ألوان تم تصميمها باستخدام هذه الاستراتيجية وتسهّل استخدامها من خلال عملية الاستيراد. إنها أيضًا مبنية على لون يمكنك تخصيصه، ما عليك سوى إعطائه لونًا وإضفاء لوحة ألوان!

لوحات ألوان تناظرية

بما أنّ عملية تدوير تدرُّج الألوان سهلة للغاية باستخدام OKLCH وHSL، سيكون من السهل إنشاء لوحة ألوان مماثلة. يمكنك تدوير تدرج اللون إلى مقدار ما تريد من النتائج وتغيير اللون الأساسي، ومشاهدة لوحات جديدة يتم إنشاؤها بواسطة المتصفح.

:root {
  --base-color: blue;

  --primary:   var(--base-color);
  --secondary: oklch(from var(--base-color) l c calc(h - 45));
  --tertiary:  oklch(from var(--base-color) l c calc(h + 45));
}

لوحات ألوان ثلاثية

على غرار الألوان التكميلية، لوحات الألوان الثالوثية معارضة في الوقت ذاته لدورات تدرجات لونية متناغمة وفقًا للون الأساسي. عندما يكون اللون التكميلي على الجانب الآخر من اللون، مثل خط مستقيم مرسوم من خلال منتصف عجلة الألوان، فإن الألواح المثلثية تشبه مثلث الخطوط، وتوجد لونين يتم تدويرهما بالتساوي من اللون الأساسي. ويمكنك تحقيق ذلك من خلال تدوير تدرُّج اللون 120deg.

يعد ذلك تبسيطًا بسيطًا لنظرية الألوان، ولكنه يكفي لبدء لوحات ألوان أكثر تعقيدًا إذا كنت مهتمًا.

:root {
  --base-color: yellow;
  --triad-1: oklch(from var(--base-color) l c calc(h - 120));
  --triad-2: oklch(from var(--base-color) l c calc(h + 120));
}

لوحات ألوان رباعية

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

يعد ذلك تبسيطًا بسيطًا لنظرية الألوان، ولكنه يكفي لبدءك في لوحات الألوان الرباعية الأكثر تعقيدًا إذا كنت مهتمًا.

:root {
  --base-color: lime;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) l c calc(h + 90));
  --color-3: oklch(from var(--base-color) l c calc(h + 180));
  --color-4: oklch(from var(--base-color) l c calc(h + 270));
}

أحادي اللون مع دوران بسيط لتدرج اللون

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

يقلل المثال التالي الإضاءة بنسبة 10٪ لكل عينة كما يؤدي إلى تدوير تدرج اللون بمقدار 10 درجات. والناتج هو لوحة ألوان من اللون الوردي الساخن إلى اللون النيلي والتي تبدو تمتزج بسلاسة مثل التدرج اللوني.

:root {
  --base-color: deeppink;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) calc(l - .10) c calc(h - 10));
  --color-3: oklch(from var(--base-color) calc(l - .20) c calc(h - 20));
  --color-4: oklch(from var(--base-color) calc(l - .30) c calc(h - 30));
  --color-5: oklch(from var(--base-color) calc(l - .40) c calc(h - 40));
}
.
جرِّب لوحة الصدارة هذه المصممة باستخدام OKLCH وتدوير تدرج اللون

تستخدم واجهة ليدربورد التالية استراتيجية تدوير تدرجات اللون هذه. يتتبّع كل عنصر من عناصر القائمة فهرسه في المستند على شكل متغيّر يسمى --i. ويتم بعد ذلك استخدام هذا الفهرس لضبط درجات اللون والإضاءة وتدرج اللون. تكون التسوية فقط بنسبة 5% أو 5 درجات، وهي أكثر دقة بكثير من المثال أعلاه مع الوردي العميق، ولذلك يتطلّب الأمر بعناية ملاحظة السبب الذي يجعل "ليدربورد" أي تدرج مختلف بهذه الأناقة.

تأكد من تغيير تدرج اللون في شريط التمرير أسفل لوحة الصدارة، وشاهد بنية الألوان النسبية التي تنشئ لحظات لون جميلة.

li {
  --_bg: oklch(
    /* decrease lightness as list grows */
    calc(75% - (var(--i) * 5%))

    /* decrease chroma as list grows */
    calc(.2 - (var(--i) * .01))

    /* lightly rotate the hue as the list grows */
    calc(var(--hue) - (var(--i) + 5))
  );
}