تم‌های رنگی با ویژگی‌های CSS پایه

دیوید ای. هرون
David A. Herron

منتشر شده: ۱۱ دسامبر ۲۰۲۵

خب، شما سایتی دارید که می‌خواهید آن را بسازید یا دوباره طراحی کنید. شاید چند رنگ اصلی در ذهن داشته باشید و به این فکر می‌کنید که چگونه به سرعت یک تم بر اساس آن رنگ‌ها پیاده‌سازی کنید.

شما به رنگ اصلی خود نیاز خواهید داشت، اما همچنین به رنگ‌هایی برای عملیات، حالت‌های شناور، خطاها و رنگ‌هایی برای سایر نیازهای رابط کاربری نیز نیاز خواهید داشت. پس در مورد گزینه‌های حالت روشن و تاریک چه؟ ناگهان به رنگ‌های زیادی نیاز خواهید داشت و این می‌تواند طاقت‌فرسا به نظر برسد.

خبر خوب این است که وقتی صحبت از ساخت یک پالت رنگی متناسب با توکن‌های رنگی که سایت شما را تعریف می‌کنند و تغییر بین حالت‌های رنگی می‌شود، ویژگی‌های Baseline می‌توانند بخش زیادی از کار را برای شما انجام دهند. می‌توانید برخی از این تکنیک‌ها را در نسخه نمایشی ویژه، یک لیست پخش با تم رنگی در سایت خیالی Baseline Radio، بررسی کنید.

یک پایه با رنگ‌های نسبی بسازید

اگر ایده‌ای برای رنگ اصلی قالب خود دارید، با کمی تئوری رنگ پایه و سینتکس رنگ نسبی CSS، می‌توانید به سرعت شروع به تولید پالت رنگی برای استفاده در قالب خود کنید.

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

html {
  --base-color: oklch(43.7% 0.075 224);
}

ویژگی سفارشی --base-color با استفاده از تابع رنگ oklch() ساخته می‌شود. OkLCh شکل استوانه‌ای فضای رنگ Oklab است و مقادیری را برای سه کانال تعریف می‌کند: L (روشنایی)، C (رنگ)، H (رنگمایه)، به علاوه یک کانال آلفای اختیاری برای کنترل شفافیت.

OkLCh فرمت خوبی برای این نوع دستکاری رنگ است، زیرا برای ایجاد یکنواختی ادراکی طراحی شده است. به عنوان مثال، اگر فقط رنگ یک رنگ را تنظیم کنید، رنگ حاصل باید روشنایی و کرومای ادراکی مشابهی با رنگ اصلی داشته باشد. این امر به ویژه در جلوگیری از مشکلات کنتراست غیرمنتظره مفید است.

با حفظ همان روشنایی و کرومای از --base-color خود، می‌توانید رنگ را در هر دو جهت ۱۲۰ درجه تنظیم کنید تا یک پالت سه‌گانه داشته باشید.

html {
  /* ... */
  --triadic-color-primary: oklch(from var(--base-color) l c calc(h + 120));
  --triadic-color-secondary: oklch(from var(--base-color) l c calc(h - 120));
}

همانطور که در اینجا نشان داده شده است، سینتکس رنگ نسبی از یک تابع رنگ استفاده می‌کند که به یک رنگ مبدا (در این مثال --base-color ) با کلمه کلیدی from اشاره می‌کند و کانال‌های مربوط به فضای رنگ را بر اساس رنگ خروجی انتخاب شده تنظیم می‌کند، که در این مورد OkLCh نیز خواهد بود.

خروجی حاصل، یک صورتی تیره برای --accent-color و یک سایه طلایی برای استفاده برای --highlight-color به شما می‌دهد، که هر دو دارای همان روشنایی و کرومای --base-color اصلی هستند.

html {
  /* ... */
  --accent-color: var(--triadic-color-primary);
  --highlight-color: var(--triadic-color-secondary);
}

  html {
    /* Input color in the rgb color space*/
    --base-color: teal;

     /* Output color in oklch. Computes to oklch(0.543123 0.0927099 314.769) */
     --triadic-color-primary: oklch(from var(--base-color) l c calc(h + 120));
  }

یک رنگ مکمل، ۱۸۰ درجه به زاویه رنگ اضافه می‌کند.

html {
  /* ... */
  --complement-color: oklch(from var(--base-color) l c calc(h + 180));
  --border-highlight: var(--complement-color);
}

برای حالت شناور در رابط کاربری خود، ممکن است بخواهید نسخه روشن‌تری از یک رنگ خاص را نمایش دهید. این به معنای افزایش مقدار کانال روشنایی است. برای حالت فعال، ممکن است بخواهید با تنظیم کانال آلفا شفافیت را افزایش دهید، یا با کاهش مقدار کانال روشنایی، آن را تیره‌تر کنید.

html {
  /* Darken the --base-color by 15% */
  --base-color-darkened: oklch(from var(--base-color) calc(l * 0.85) c h);
  /* Assign this color a meaningful variable name */
  --action-color: var(--base-color-darkened);
  /* Lighten the --action-color by 15% */
  --action-color-light: oklch(from var(--action-color) calc(l * 1.15) c h);
  /* Darken the --action-color by 10% */
  --action-color-dark: oklch(from var(--action-color) calc(l * 0.9) c h);
}

در اینجا، ما --action-color از --base-color استخراج می‌کنیم و از آن برای دکمه‌ها و لینک‌ها استفاده می‌کنیم. --action-color دو نوع دارد - روشن‌تر و تیره‌تر - که حتی اگر --action-color نسبت به رنگ دیگری متفاوت از --base-color تغییر کند، همچنان اعمال می‌شود.

شما می‌توانید کانال‌ها را با استفاده از یک تابع ریاضی مانند calc() تنظیم کنید یا کانال را به طور کامل با یک مقدار جدید جایگزین کنید. کانال‌های تغییر نیافته با حروف مربوط به خود نمایش داده می‌شوند (برای مثال، l برای مقدار روشنایی بدون تغییر).

رنگ‌ها را با color-mix() ترکیب کنید

برای سایر انواع رنگ، می‌توانید رویکرد مشابهی را در پیش بگیرید و کانال‌های دیگر ویژگی سفارشی --base-color را تنظیم کنید. یا color-mix() برای افزودن نشانه‌هایی از رنگ پایه به سایر جنبه‌های طراحی خود استفاده کنید.

پارامتر --border-color ترکیبی از رنگ پایه و رنگ grey است که در فضای رنگی oklab درون‌یابی شده است. وقتی به عنوان یک روش درون‌یابی رنگ استفاده شود، نتایج ادراکی یکنواختی ارائه می‌دهد.

html {
  --base-mix-grey-50: color-mix(in oklab, var(--base-color), grey);
  --border-color: var(--base-mix-grey-50);
}

به طور پیش‌فرض، این مقدار ۵۰٪ از هر رنگ خواهد بود، اما می‌توانید با تنظیم درصد وزنی هر رنگ، آن را بیشتر یا کمتر برجسته کنید.

html {
  --background-mix-base-80: color-mix(in oklab,
    var(--background-color) 80%,
    var(--base-color));
  --surface-light: var(--background-mix-base-80);
}

یک جایگزین برای اضافه کردن رنگ بیشتر به یک عنصر، تنظیم کانال رنگی آن با استفاده از سینتکس رنگ نسبی است. حاشیه ورودی‌های متنی در فرم تماس، وقتی در حالت فوکوس هستند، کمی رنگارنگ‌تر است.

[data-input*="text"] {
  --focus-ring: transparent;
  /* ... */
  &:focus {
    --focus-ring: oklch(from var(--border-color) l calc(c + 0.1) h);
  }
}

حالت‌های روشن و تاریک را انتخاب کنید

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

پشتیبانی سیگنال از تم‌های روشن و تیره با ویژگی color-scheme

شما می‌توانید با استفاده از ویژگی color-scheme فوراً به مرورگر بگویید که سایت شما می‌تواند در حالت‌های "روشن"، "تیره" یا هر دو مشاهده شود. این ویژگی به مرورگر می‌گوید که یک عنصر می‌تواند به راحتی در کدام طرح‌های رنگی رندر شود.

 html {
   color-scheme: light dark;
}

تنظیم color-scheme: light dark روی شبه عنصر :root یا عنصر html :

  • به مرورگر می‌گوید که صفحه شما از حالت روشن یا تاریک پشتیبانی می‌کند.
  • رنگ‌های پیش‌فرض رابط کاربری مرورگر را برای مطابقت با تنظیمات سیستم عامل مربوطه تغییر می‌دهد.

برای اینکه به مرورگرها زودتر اطلاع دهید که صفحه شما از حالت‌های روشن و تاریک پشتیبانی می‌کند، می‌توانید با اضافه کردن یک عنصر <meta> در <head> سند، پشتیبانی از تغییر طرح رنگ را نیز اعلام کنید.

<head>
  <!-- ... -->
   <meta name="color-scheme" content="light dark">
</head>

با استفاده از تابع light-dark() می‌توان انواع «روشن» و «تاریک» را تنظیم کرد.

به عنوان یک نویسنده، ممکن است به تنظیم رنگ‌های صفحه با استفاده از کوئری prefers-color-scheme @media عادت داشته باشید.

@media (prefers-color-scheme: light) {
  html {
    --background-color: oklch(95.5% 0 162);
    --text-color: black;
  }
}

@media (prefers-color-scheme: dark) {
  html {
    --background-color: oklch(22.635% 0.01351 291.83);
    --text-color: white;
  }
}

این برای رنگ‌ها و سبک‌هایی که توسط نویسنده کنترل می‌شوند عالی عمل می‌کند، اما همانطور که در بخش قبلی ذکر شد، برای به‌روزرسانی رنگ‌های رابط کاربری مرورگر، هنوز به color-scheme نیاز دارید.

تغییر رنگ‌های صفحه با استفاده از کوئری prefers-color-scheme همچنین به معنای تکرار کد است، زیرا باید رنگ‌ها را برای هر حالت جداگانه تعریف کنید.

با تنظیم color-scheme روی کل صفحه (یا عناصر خاص)، می‌توانید از تابع light-dark() برای تنظیم رنگ‌ها برای هر حالت در یک خط کد استفاده کنید.

این تابع دو رنگ را می‌پذیرد. رنگ اول زمانی استفاده می‌شود که طرح رنگ روی "روشن" تنظیم شده باشد و رنگ دوم برای زمانی است که طرح رنگ روی "تیره" تنظیم شده باشد.

html {
  color-scheme: light dark;
  /* Color custom property values for both light and dark modes */
  --base-color: light-dark(oklch(43.7% 0.075 224), oklch(89.2% 0.069 224));
  --background-color: light-dark(oklch(95.5% 0 162), oklch(22.635% 0.01351 291.83));
  --accent-color: oklch(from var(--base-color) l c calc(h + 120));
  --active-color: light-dark(var(--action-color-light), var(--action-color-dark));
  /* ... */
}

همانند هر ویژگی سفارشی، تنظیمات light-dark() برای رنگ‌های شما می‌تواند به صورت سراسری یا درون کامپوننت‌های خاص تنظیم شود و سپس در صورت نیاز در جای دیگری استفاده شود.

/* custom property usage */
body {
  background-color: var(--background-color);
  /* ... */
}

:any-link {
  /* ... */
  text-decoration-color: var(--accent-color);
}

با استفاده از تعویض‌کننده‌ی تم داخلی، به کاربران کنترل بدهید

خیلی خوب است که قالبی داشته باشید که با تنظیمات رنگ پیش‌فرض سیستم یا مرورگر کاربر سازگار شود، اما می‌توانید یک قدم فراتر بروید و به بینندگان سایت خود این امکان را بدهید که این تنظیمات رنگ پیش‌فرض را لغو کنند.

اگر یک دکمه‌ی تغییر وضعیت تم ایجاد کنید که ویژگی data-scheme را در عنصر <html> به‌روزرسانی کند، می‌توانید از همان ویژگی برای تغییر color-scheme با CSS استفاده کنید.

html {
  color-scheme: light dark;

  &[data-scheme="light"] {
    color-scheme: light;
  }

  &[data-scheme="dark"] {
    color-scheme: dark;
  }

  &[data-scheme="green"] {
      --base-color-light: oklch(48.052% 0.11875 151.945);
      --base-color-dark: oklch(92.124% 0.13356 151.558);
      color-scheme: light dark;
   }
}

data-scheme="light" و data-scheme="dark" صفحه را فقط در حالت‌های رنگی مربوط به خودشان نشان می‌دهند. data-scheme="green" می‌توان در هر دو حالت مشاهده کرد و همچنین --base-color به سایه‌ای از سبز تغییر می‌دهد که به شما یک پالت رنگی کاملاً جدید می‌دهد زیرا اکثر رنگ‌های دیگر بر اساس --base-color هستند.

ثبت املاک سفارشی با @property

تاکنون، رنگ‌های موجود در نسخه آزمایشی به عنوان ویژگی‌های سفارشی استاندارد تنظیم شده‌اند. همچنین می‌توانید ویژگی‌ها را با استفاده از قانون @property ثبت کنید تا از مزایای بررسی نوع بهره‌مند شوید.

از آنجایی که از --base-color به عنوان پایه بسیاری از رنگ‌های دیگر در رابط کاربری استفاده می‌شود، خوب است که مطمئن شوید همیشه یک رنگ است و یک مقدار جایگزین دارد.

@property --base-color-light {
  syntax: '<color>';
  inherits: false;
  initial-value: oklch(43.7% 0.075 224);
}

@property --base-color-dark {
  syntax: '<color>';
  inherits: false;
  initial-value: oklch(89.2% 0.069 224);
}

html {
  --base-color: light-dark(var(--base-color-light), var(--base-color-dark));
}

به این ترتیب، اگر مقدار --base-color سهواً به یک مقدار نامعتبر تغییر کند، همیشه با استفاده از قانون @property به initial-value خود برمی‌گردد.

ثبت برخی ویژگی‌ها به این روش، امکان متحرک‌سازی روان رنگ‌ها را در تابع linear-gradient() فراهم می‌کند.

.main-heading {
  background: linear-gradient(in oklch 90deg, var(--text-color) 50%, oklch(from var(--base-color) l c var(--header-hue)));
  background-clip: text;
  color: transparent;
  animation: header-hue-switch 5s ease-in-out infinite alternate;
}

.main-heading دارای یک پس‌زمینه linear-gradient() است که با استفاده از ویژگی background-clip از طریق متن شفاف نمایش داده می‌شود.

بخشی از متن، hue نشان می‌دهد که با استفاده از سینتکس رنگ نسبی، از مقدار کانال 26.67 تا 277 متحرک می‌شود:

@keyframes header-hue-switch {
  from {
    --header-hue: 26.67;
  }

  to {
    --header-hue: 277;
  }
}

با یک ویژگی سفارشی ثبت شده --header-hue ، این انیمیشن می‌تواند به راحتی اجرا شود زیرا مرورگر می‌داند که این ویژگی سفارشی یک عدد است.

@property --header-hue {
  syntax: '<number>';
  inherits: false;
  initial-value: 100;
}

با یک ویژگی سفارشی ثبت نشده، مرورگر نوع داده‌ی --header-hue را نمی‌داند، بنابراین انتقال به یک عدد یک انیمیشن گسسته خواهد بود که بدون درون‌یابی تدریجی بین حالت‌ها پرش می‌کند.

جمع بندی

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

ایجاد پالت رنگ به صورت پویا به این شکل، به شما انعطاف‌پذیری می‌دهد. اگر نیاز به تغییر رنگ پایه برای برندسازی دارید، می‌توانید فقط --base-color را به‌روزرسانی کنید و بقیه تم از آن پیروی خواهد کرد. یا اگر قابلیت‌های پخش موسیقی را اضافه کنید، می‌توانید تصمیم بگیرید که می‌خواهید رنگ پایه را به صورت پویا تغییر دهید تا با آهنگ در حال پخش مطابقت داشته باشد.

اعتبارات

منطق تغییر تم از کامپوننت تغییر تم آدام آرگایل اقتباس شده است.