color theoryMay 3, 202612 min read

رنگ OKLCH در CSS مدرن: چرا برنده است و چطور آن را عرضه کنیم

راهنمای عملی رنگ OKLCH در CSS. چرا hex در مقیاس بزرگ از کار افتاد، چگونه OKLCH رانش روشنایی را درست می‌کند، مسیر مهاجرت چهارمرحله‌ای، و رمپ پالت یکنواخت ادراکی که هر دیزاین سیستم در ۲۰۲۶ باید عرضه کند.

By Boone
XLinkedIn
oklch color modern css

رنگ OKLCH در CSS مدرن: چرا برنده است و چطور آن را عرضه کنیم

OKLCH اولین فضای رنگی‌ای است که CSS عرضه کرده و طراحان واقعاً می‌توانند درباره‌اش استدلال کنند. تیم‌هایی که هنوز پالت را با hex می‌سازند، بی‌سروصدا در هر بحث درباره کنتراست و دارک مود می‌بازند، بحث‌هایی که حتی نمی‌دانستند در آن‌اند.

Hex هرگز فضای رنگی نبود، فقط یک سریال‌سازی بود

Hex مخفف‌نویسی برای sRGB است. #4A90E2 مشخصات یک رنگ نیست، سه مقدار کانال قرمز، سبز و آبی است که در شش کاراکتر فشرده شده. sRGB برای مانیتورهای CRT اوایل دهه ۱۹۹۰ طراحی شد، نه برای ادراک بصری انسان.

نتیجه این است که دو مقدار hex می‌توانند در یک جایگاه عددی «روشنایی» پالت شما بنشینند و برای چشم کاملاً متفاوت به نظر برسند. Blue-500 در بیشتر دیزاین سیستم‌ها تیره‌تر از yellow-500 دیده می‌شود، حتی وقتی هر دو جایگاه نسبی یکسانی در رمپ دارند. این مشکل سلیقه نیست. مشکل ریاضی است که در خود دستگاه مختصات پخته شده.

«Hex هرگز فضای رنگی نبود، فقط یک سریال‌سازی بود، و ما از آن زمان تا امروز درباره روشنایی دعوا کرده‌ایم.»

HSL وانمود کرد درستش می‌کند و نکرد

HSL آمد و به طراحان زبان داد: hue، saturation، lightness. حس یک سیستم واقعی را داشت، ولی نبود. کانال lightness در HSL زیر کاپوت هنوز به مقادیر sRGB نگاشت می‌شود، یعنی همان مشکلات ادراکی hex را به ارث می‌برد.

hsl(220, 70%, 50%) و hsl(45, 70%, 50%) اسماً روشنایی یکسانی دارند. کنار هم بگذاریدشان. زرد به‌وضوح روشن‌تر دیده می‌شود. HSL فقط واژه‌های بهتری برای همان ریاضی خراب به شما داد.

OKLCH از نظر ادراکی یکنواخت است

OKLCH بر پایه فضای رنگی OKLab ساخته شده که Björn Ottosson در ۲۰۲۰ مشخصاً برای رفع ناهمگونی ادراکی فضاهای قبلی توسعه داد. حرف L در OKLCH یعنی روشنایی ادراکی، کالیبره‌شده با پاسخ واقعی سیستم بینایی انسان به نور.

مقادیر L برابر در OKLCH یعنی روشنایی ادراکی برابر. نه تقریباً برابر. نه «معمولاً برابر اگر chroma مشابه باشد». برابر. این ویژگی‌ای است که هیچ فضای رنگی قبلی CSS نتوانست ارائه کند، و نگاه شما به تولید پالت را کاملاً عوض می‌کند.

سه دلیل برنده بودن OKLCH

روشنایی یکنواخت ادراکی، درون‌یابی hue قابل‌پیش‌بینی، و پشتیبانی از wide-gamut. هر کدام یک باگ مشخص در پالت فعلی شما را درست می‌کند و با هم گردش‌کاری رنگی می‌سازند که بین تم‌ها، کامپوننت‌ها و انواع نمایشگر مقیاس‌پذیر است.

مفهوم voxel با سه بلوک روی هم که سه برد ساختاری OKLCH نسبت به hex و HSL را نشان می‌دهد: روشنایی ادراکی، درون‌یابی منطقی hue، و دسترسی به wide-gamut
مفهوم voxel با سه بلوک روی هم که سه برد ساختاری OKLCH نسبت به hex و HSL را نشان می‌دهد: روشنایی ادراکی، درون‌یابی منطقی hue، و دسترسی به wide-gamut

دلیل اول: رانش روشنایی مرده است

در سیستم‌های hex و HSL، رانش روشنایی مالیات نامرئی هر پالت است. blue-50 و amber-50 را با چشم روی چیزی که درست به نظر می‌رسد تنظیم می‌کنید، روی صفحه‌های مختلف از هم فاصله می‌گیرند، در دارک مود با هم می‌جنگند، و ریاضی کنتراست هیچ‌وقت کاملاً سر جایش نمی‌ماند.

در OKLCH، blue-50 و amber-50 عدد روشنایی یکسانی دارند و آن عدد همان روشنایی ادراکی را نشان می‌دهد. Tailwind v4 دقیقاً به همین دلیل کل پالتش را به OKLCH منتقل کرد. اگر از مقیاس‌های رنگ Radix UI استفاده می‌کنید، حتی اگر هرگز کلمه OKLCH را در مستندات ندیده باشید، از یکنواختی ادراکی بهره می‌برید.

دلیل دوم: درون‌یابی hue عاقلانه است

گرادیان‌های CSS با درون‌یابی sRGB از داخل مکعب رنگی RGB عبور می‌کنند، نه از فضای ادراکی. گرادیان آبی به زرد در sRGB از میانه‌ای خاکستریِ گل‌آلود می‌گذرد، چون قطر RGB نزدیک محور بی‌رنگ را قطع می‌کند. این هنر نیست. تصادف هندسی است.

درون‌یابی گرادیان در OKLCH زاویه hue را روی حلقه ادراکی طی می‌کند. آبی به زرد در OKLCH از فیروزه‌ای و سبز می‌گذرد، همان چیزی که چشم انتظارش را دارد. آن گل‌آلودگی خاکستری رفته است. این برای گرادیان‌های UI، انتقال‌های رنگی انیمیشنی و هر ابزار تولید پالت که گام‌های میانی می‌سازد اهمیت دارد.

دلیل سوم: P3 و Rec2020 در دسترس‌اند

Hex نمی‌تواند رنگ‌های خارج از sRGB را توصیف کند. هر آیفون از ۲۰۱۶ به بعد، هر لپ‌تاپ مدرن با پنل wide-gamut و بیشتر مانیتورهای جدید می‌توانند رنگ‌هایی نمایش دهند که در گامات P3 وجود دارند ولی آدرس hex ندارند. شما رنگ‌های اشباع و زنده را روی میز جا گذاشته‌اید چون دستگاه مختصاتتان نمی‌توانست اسمشان را ببرد.

OKLCH می‌تواند رنگ‌های P3 و Rec2020 را بومی توصیف کند. oklch(0.60 0.28 260) آبی زنده‌ای است که در P3 هست ولی خارج از گامات sRGB است. مرورگرهای مدرن با آن کنار می‌آیند و راهنمای رنگ Display P3 اپل سال‌هاست به همین سمت اشاره می‌کند. دیزاین سیستمی که حالا به OKLCH می‌رود، همان سیستمی است که وقتی P3 انتظار پیش‌فرض شود آماده است.

مهاجرت چهارمرحله‌ای از hex به OKLCH

ممیزی، تبدیل، بازتولید، ممیزی دوباره. مهاجرت برای توکن‌های primitive مکانیکی است و برای توکن‌های semantic قضاوت می‌خواهد. مهاجرت کامل یک دیزاین سیستم متوسط روزها طول می‌کشد، نه هفته‌ها. اگر پیش از شروع توکن‌های جدید را در یک معماری متغیرهای Figma تمیز لنگر بیندازید، بیشترین زمان را صرفه‌جویی می‌کنید.

گام اول: ممیزی پالت موجود

هر توکن رنگی سیستم را خروجی بگیرید. هر مقدار hex را با ابزاری مثل oklch.com یا پلاگین PostCSS OKLCH به OKLCH تبدیل کنید. بر اساس L مرتب کنید و ستون روشنایی را در سراسر hueها ببینید.

باگ‌ها فوراً خودشان را نشان می‌دهند. Blue-300 روی L=0.72 می‌نشیند و yellow-300 روی L=0.87. توکن‌هایی که قرار بود وزن بصری معادل داشته باشند اصلاً نزدیک هم نیستند. این ممیزی همان شواهدی است که توجیه مهاجرت را برای هر کسی که مخالفت کند آسان می‌کند.

گام دوم: تبدیل primitiveها به OKLCH

مقیاس primitive را بردارید، یعنی همان رمپ شماره‌دار خام و نه توکن‌های semantic، و به OKLCH تبدیل کنید. مقادیر روشنایی را در هر یازده گام به پله‌های ثابت گرد کنید: 0.97، 0.93، 0.86، 0.75، 0.65، 0.54، 0.45، 0.37، 0.27، 0.19، 0.13.

سعی نکنید مقادیر hex اصلی را دقیقاً حفظ کنید. هدف رفع ناهماهنگی است. blue-500 و red-500 تبدیل‌شده پیکسل به پیکسل با مقادیر قدیمی یکی نخواهند بود، و دقیقاً همین هدف است. سیستم بهتر می‌شود، نه فقط متفاوت.

گام سوم: بازتولید رمپ‌ها

با پله‌های روشنایی تمیز و یکدست، بازتولید رمپ‌ها در hueهای مختلف یک عملیات جدولی می‌شود. ستون L را تنظیم کنید، chroma هر hue را انتخاب کنید (آبی‌ها معمولاً پیش از clip شدن chroma بیشتری از قهوه‌ای‌ها و زردها دارند)، ستون H را تنظیم کنید و تولید کنید.

نتیجه این است که blue-500 و red-500 برای اولین بار در سیستم شما وزن بصری یکسانی دارند. تصمیم‌های پالت رنگ برند که قبلاً قضاوت‌های دلبخواهی بودند، به انتخاب‌های اصولی با یک مختصات مشخص تبدیل می‌شوند.

گام چهارم: ممیزی دوباره دسترس‌پذیری

پالت جدید، دور جدید بررسی کنتراست. OKLCH پیش‌بینی کنتراست را آسان‌تر می‌کند چون روشنایی حالا همان چیزی را که می‌گوید معنا می‌دهد. جفت کردن دو توکن با مقادیر L معلوم، پیش از باز کردن ابزار بررسی هم تخمین خوبی از نسبت کنتراستشان می‌دهد.

بررسی کنتراست WCAG و APCA را روی همه جفت‌های توکن semantic اجرا کنید. جفت‌هایی را که دیگر الزامات را برآورده نمی‌کنند علامت بزنید و chroma یا روشنایی توکن مشکل‌دار را تنظیم کنید. یک بررسی درست کنتراست رنگ دسترس‌پذیر روی پالت OKLCH معمولاً شگفتی کمتری از بررسی معادل روی پالت hex نشان می‌دهد، چون پله‌های روشنایی قبلاً غلط بودند و حالا نیستند.


یک سیستم رنگ می‌خواهید که بین مودها، hueها و نمایشگرهای مدرن بدون رانش روشنایی دوام بیاورد؟ Brainy سیستم‌های پالت بومی OKLCH طراحی می‌کند که به شکل متغیرهای Figma، CSS custom properties و توکن‌های Tailwind تحویل می‌شوند و بررسی کنتراستشان از قبل انجام شده.


چهار تله OKLCH

Clamp کردن خارج از گامات، chroma clipping، مدیریت alpha و خلأهای ابزاری. هر کدام تیم‌های تازه‌وارد به OKLCH را گاز می‌گیرد و هر کدام راه‌حل مشخصی دارد که وقتی بدانید دنبال چه می‌گردید چند دقیقه طول می‌کشد.

تلهچه اتفاقی می‌افتدراه‌حل
Clamp شدن خارج از گاماتمقادیر با chroma بالا از sRGB بیرون می‌افتند و مرورگر آن‌ها را clamp می‌کند، گاهی با جابه‌جایی hueرنگ‌های فقط P3 را پشت @media (color-gamut: p3) قرار دهید
Chroma clippingClamp کردن hue را هم کمی عوض می‌کند، نه فقط saturation راchroma امن sRGB را برای سازگاری گسترده زیر حدود ۰٫۲۰ نگه دارید
مدیریت alphaoklch(0.55 0.20 260 / 0.5) در fillهای ثابت کار می‌کند؛ برخی مسیرهای درون‌یابی در مرورگرهای قدیمی‌تر خراب می‌شوندalpha را در گرادیان‌ها و transitionها تست کنید، نه فقط در رنگ‌های ثابت
خلأهای ابزاریانتخابگر رنگ بومی Figma مستقیماً OKLCH را نشان نمی‌دهداز Tokens Studio استفاده کنید یا توکن‌ها را در CSS تعریف کنید و از پنل کد Figma ارجاع دهید

مشکل گامات بیشتر از همه گاز می‌گیرد. وقتی oklch(0.60 0.32 260) می‌نویسید، آن مقدار chroma خارج از sRGB است. مرورگرهای دسکتاپ آن را با clamp کردن به نزدیک‌ترین رنگ sRGB حل می‌کنند، که می‌تواند hue ظاهری را جابه‌جا کند. راه‌حل یا ماندن در chroma امن sRGB برای توکن‌های پایه است، یا قرار دادن مقادیر wide-gamut پشت media query و نگه داشتن یک declaration جایگزین بالای آن.

رمپ پالت کارآمد OKLCH

یک رمپ عملی ۱۱ گامی با پله‌های روشنایی ثابت، با آبی در hue برابر ۲۶۰ به‌عنوان مرجع. پله‌های روشنایی در هر hue سیستم شما یکسان است. فقط chroma و hue برای هر خانواده رنگی تغییر می‌کند.

css
:root { --blue-50: oklch(0.97 0.02 260); --blue-100: oklch(0.93 0.05 260); --blue-200: oklch(0.86 0.09 260); --blue-300: oklch(0.75 0.14 260); --blue-400: oklch(0.65 0.18 260); --blue-500: oklch(0.54 0.22 260); --blue-600: oklch(0.45 0.20 260); --blue-700: oklch(0.37 0.17 260); --blue-800: oklch(0.27 0.13 260); --blue-900: oklch(0.19 0.09 260); --blue-950: oklch(0.13 0.06 260); }

برای ساخت قرمز (hue برابر ۲۵)، کهربایی (hue برابر ۷۵) یا سبز (hue برابر ۱۴۵)، ستون L را در هر یازده گام یکسان نگه دارید. C را بر اساس ظرفیت طبیعی chroma آن hue تنظیم کنید: زردها و سبزها پیش از clip شدن از sRGB chroma کمتری از آبی‌ها دارند. H را روی hue هدف بگذارید. کل سیستم پالت همین است.

سیستم رنگ دارک مود که روی این رمپ ساخته می‌شود از توکن‌های semantic استفاده می‌کند که بر اساس پله L و hue بین primitiveها جابه‌جا می‌شوند، نه با override دستی مقادیر hex یکی‌یکی.

مفهوم voxel از یک رمپ رنگ ۱۱ گامی با روشنایی ادراکی یکنواخت در همه گام‌ها، که نشان می‌دهد OKLCH چگونه وزن بصری را از ۵۰ تا ۹۵۰ ثابت نگه می‌دارد
مفهوم voxel از یک رمپ رنگ ۱۱ گامی با روشنایی ادراکی یکنواخت در همه گام‌ها، که نشان می‌دهد OKLCH چگونه وزن بصری را از ۵۰ تا ۹۵۰ ثابت نگه می‌دارد

پشتیبانی مرورگرها و پنجره امن مهاجرت

OKLCH در هر مرورگر اصلی منتشرشده از ۲۰۲۳ به بعد پشتیبانی می‌شود. Chrome 111، Safari 15.4، Firefox 113 و Edge 111 همگی پشتیبانی کامل OKLCH دارند. پوشش جهانی تا اواسط ۲۰۲۵ بالای ۹۳٪ است. پنجره مهاجرت باز است.

مرورگرپشتیبانی OKLCHاز نسخه
Chromeکامل111 (مارس 2023)
Safariکامل15.4 (مارس 2022)
Firefoxکامل113 (مه 2023)
Edgeکامل111 (مارس 2023)
Samsung Internetکامل21 (2023)

جایگزین برای هر مرورگری که OKLCH را پشتیبانی نمی‌کند یک خط است. اول جایگزین hex را اعلام کنید، بعد مقدار OKLCH را. مرورگرهایی که OKLCH را نمی‌فهمند آن را نادیده می‌گیرند و از hex استفاده می‌کنند. مرورگرهایی که می‌فهمند از مقدار بهتر استفاده می‌کنند.

css
color: #4a7de8; /* sRGB fallback */ color: oklch(0.54 0.22 260); /* OKLCH for modern browsers */

Tailwind v4 پالتش را به‌صورت بومی در OKLCH تولید می‌کند. Linear، توکن‌های طراحی Sail از Stripe و راهنمای رنگ توسعه‌دهندگان Apple همگی به سمت سیستم‌های یکنواخت ادراکی رفته‌اند. صنعت به نتیجه رسیده. سؤال این است که تیم شما کی می‌پیوندد.

سوالات متداول

یادگیری OKLCH سخت است؟

دستگاه مختصات با hex یا HSL فرق دارد ولی پیچیده نیست. L روشنایی از ۰ تا ۱ است. C همان chroma است، تقریباً میزان اشباع. H هیو بر حسب درجه است. وقتی درونی کنید که L یعنی روشنایی ادراکی و C یعنی رنگین‌بودن، این سیستم سریع‌تر از HSL شهودی می‌شود.

آیا امروز می‌توانم از OKLCH در Figma استفاده کنم؟

Figma تا ۲۰۲۵ OKLCH را به‌صورت بومی در انتخابگر رنگش نشان نمی‌دهد. گردش‌کار عملی این است که توکن‌ها را در یک فایل توکن با Tokens Studio یا یک فایل CSS variables همگام با متغیرهای Figma به OKLCH تعریف کنید، سپس با خروجی کد Figma مقادیر را راستی‌آزمایی کنید. موتور رندر Figma تبدیل را در داخل انجام می‌دهد.

آیا OKLCH مقادیر hex فعلی من را خراب می‌کند؟

نه. می‌توانید OKLCH را تدریجی و توکن به توکن وارد کنید. مقادیر hex فعلی دقیقاً مثل قبل کار می‌کنند. مهاجرت افزایشی است، نه جایگزینی.

تفاوت LCH و OKLCH چیست؟

LCH بر پایه فضای رنگی CIELAB است که از نظر ادراکی یکنواخت است ولی مشکل خطی‌بودن hue دارد، به‌ویژه در محدوده آبی-بنفش. OKLCH بر پایه OKLab است که این جابه‌جایی‌های hue را اصلاح می‌کند. برای کار طراحی عملی OKLCH انتخاب بهتری است چون درون‌یابی hue آن شگفتی کمتری تولید می‌کند.

چطور hex را به OKLCH تبدیل کنم؟

از oklch.com، پلاگین PostCSS oklch یا playground مشخصات CSS Color 4 استفاده کنید. مقدار hex را بچسبانید، مختصات OKLCH را بخوانید، L و C را تا دو رقم اعشار گرد کنید و H را به نزدیک‌ترین درجه صحیح. این مقدار توکن کاری شماست.

آیا OKLCH بر الزامات دسترس‌پذیری اثر می‌گذارد؟

الزامات کنتراست WCAG بر اساس luminance نسبی sRGB تعریف شده‌اند، نه روشنایی OKLCH. APCA به مدل‌های ادراکی نزدیک‌تر است و طبیعی‌تر به مقادیر L در OKLCH نگاشت می‌شود. در عمل OKLCH پیش‌بینی کنتراست را شهودی‌تر می‌کند چون L روشنایی ادراکی را دنبال می‌کند، ولی هنوز باید جفت توکن‌های semantic را از ابزار بررسی کنتراست رد کنید. فرآیند همان است، فقط از پیش راحت‌تر می‌شود درباره‌اش استدلال کرد.

تغییری که OKLCH واقعاً باز می‌کند

OKLCH یک ترند نیست. اولین باری است که CSS فضای رنگی‌ای عرضه کرده که حول نحوه دیدن رنگ توسط چشم انسان طراحی شده، و ابزارها به اندازه کافی پیش آمده‌اند که مهاجرت امروز برای هر تیمی که چند روز متمرکز وقت بگذارد عملی باشد.

تیم‌هایی که حالا حرکت می‌کنند سه چیز را همزمان می‌گیرند: پالتی که بدون override دستی در دارک مود دوام می‌آورد، رفتار کنتراستی که با دستگاه مختصات جور است، و پایه‌ای که بدون بازنویسی آینده به P3 گسترش می‌یابد. تیم‌هایی که صبر می‌کنند همچنان همان بحث را خواهند داشت که چرا blue-300 سنگین‌تر از orange-300 به نظر می‌رسد، و جواب همچنان همان خواهد بود. دستگاه مختصات هرگز برای آن کار طراحی نشده بود.

اگر می‌خواهید معماری کامل توکن را روی این پالت بسازید، مقاله معماری متغیرهای Figma لایه semantic را پوشش می‌دهد. برای کاربرد این کار در دارک مود، سیستم‌های رنگ دارک مود از همان جایی ادامه می‌دهد که این مقاله تمام می‌شود.

می‌خواهید برایتان ساخته شود؟ Brainy را استخدام کنید.

Want a color system that holds up across modes, hues, and modern displays without lightness drift? Brainy designs OKLCH-native palette systems that ship as Figma variables, CSS custom properties, and Tailwind tokens with the contrast pass already done.

Get Started

More from Brainy Papers

Keep reading