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

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

Adam Argyle
Adam Argyle

يعد Chrome 119 ميزة ألوان قوية جدًا من مستوى ألوان CSS 5. تُنشئ بنية الألوان النسبية مسارًا سلسًا للتعامل مع الألوان ضمن 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. سيُجري المتصفّح عملية تحويل لهذا اللون الأصلي ويقسّمه إلى أجزاء ويقدّمها بدوره كمتغيّرات لاستخدامها في تعريف اللون الجديد.

يظهر رسم بياني لبنية rgb(from green 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%);
}

قلب لون

قلب الألوان هي وظيفة تعديل ألوان شائعة يمكن العثور عليها في مكتبات الألوان. تتمثل إحدى طرق تحقيق ذلك في تحويل لون إلى RGB ثم طرح قيمة كل قناة من 1.

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

إضافة لون مكمّل

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

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

تباين لون

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

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

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

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

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

استخدام لون أغمق مع لون أفتح

وتوضح الفئة .well-contrasting-lighter-color L* مع دلتا تبلغ 60% أيضًا. بما أنّ اللون الأصلي هو لون فاتح (قيمة عالية للسطوع)، تتم إزالة 0.60 من قناة السطوع.

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

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

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

افتح مثال رمز المصدر لهذه اللوحات وحاول تغيير --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))
  );
}