تم‌بندی پویا بدون CSS-in-JS

من زمانی طرفدار پر و پا قرص styled-components بودم. انعطاف‌پذیری‌اش را دوست داشتم. اما بعد به بن‌بست خوردم.

یک پروژه نیاز داشت که حجم runtime خود را کاهش دهد. تصمیم گرفتم CSS Modules و CSS بومی (native CSS) را امتحان کنم. نتیجه من را غافلگیر کرد. من styled-components، Emotion و goober را از پروژه‌هایم حذف کردم. هیچ‌کدام از چیزهایی را که واقعاً به آن‌ها نیاز داشتم، از دست ندادم.

بزرگترین دستاورد فقط عملکرد (performance) نبود؛ بلکه حذف وابستگی به استایل‌دهی بود. در یک پروژه، runtime مربوط به CSS-in-JS حدود ۳۰٪ از باندل کلاینت را اشغال کرده بود.

CSS خالص تکامل یافته است. دیگر برای این کارها نیازی به کتابخانه‌های سنگین JS ندارید:

• Nesting: از CSS nesting بومی استفاده کنید. • Color shifts: از color-mix() استفاده کنید. • Specificity control: از @layer استفاده کنید. • Responsive components: از container queries استفاده کنید.

در اینجا نحوه ساخت یک تم تنها با استفاده از یک فایل و custom properties آورده شده است.

۱. توکن‌ها را در یک فایل CSS تعریف کنید.

:root {
  --color-bg: #ffffff;
  --color-text: #1a1a1a;
  --color-accent: #3c7dc4;
}

[data-theme="dark"] {
  --color-bg: #14161a;
  --color-text: #f5f5f0;
  --color-accent: #6aa6e8;
}

۲. از آن متغیرها در کامپوننت‌های خود استفاده کنید.

.button {
  background: var(--color-accent);
  color: var(--color-bg);
}

۳. با تغییر یک ویژگی (attribute) واحد، تم را عوض کنید.

function setTheme(theme) {
  document.documentElement.dataset.theme = theme;
  localStorage.setItem("theme", theme);
}

کامپوننت‌ها نیازی به ThemeProvider ندارند. آن‌ها نیازی به رندر مجدد (re-render) ندارند. مرورگر به‌روزرسانی را از طریق cascade مدیریت می‌کند. این کار باعث می‌شود بیشتر اپلیکیشن شما در قالب Server Components باقی بماند.

برای جلوگیری از «فلاش» (flash) شدن تم اشتباه هنگام بارگذاری صفحه، از یک اسکریپت کوچک inline در بخش head فایل HTML خود استفاده کنید:

<script>
  const t = localStorage.getItem("theme") || 
  (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
  document.documentElement.dataset.theme = t;
</script>

استفاده از JS برای تولید استایل‌ها در زمان اجرا (runtime) را متوقف کنید. برای توکن‌های خود از متغیرهای CSS بومی استفاده کنید. این کار منجر به کد کمتر و زمان بارگذاری سریع‌تر می‌شود.

منبع: https://dev.to/kirill_c_7b35589230/dynamic-theming-without-css-in-js-d7e