Developers love a quick win. When the ticket says "add dark mode," the path of least resistance looks obvious: write light.css, write dark.css, and toggle between them. It feels clean. It ships fast. For a tiny side project with three components, it might even hold up. But once your application grows past a handful of modules, that second file stops being an asset and becomes a liability you maintain in duplicate.

The Two-File Trap

The logic seems sound at first glance. Separation of concerns, right? Light things over here, dark things over there. You open two buffers in your editor. You copy the card styles from the light file into the dark file, swap #ffffff for #1a1a1a, and call it a day.

The problem is not the first week. The problem is month six, when a designer asks for a slightly different border radius on the primary button, or when the product team wants a new warning state on the checkout form. You update the light stylesheet. You eyeball the dark stylesheet. Maybe you remember to copy the change over. Maybe you do not. That gap is where quality dies. You are no longer maintaining one interface. You are maintaining two parallel interfaces that happen to share the same HTML skeleton.

Theme Drift Is Inevitable

This gap has a name that frontend teams are starting to recognize: theme drift. It happens when your two stylesheets evolve at different speeds. A padding adjustment here. A shadow tweak there. The dark file becomes the neglected sibling. Or worse, it becomes a source of fear. Developers start avoiding changes because touching one theme means hunting through another file to duplicate the work.

The cognitive overhead compounds fast. You wanted to write CSS once. Instead you wrote it twice, and now you are paying interest on that debt every time the design system shifts. Icons misalign in dark mode because someone updated a flex gap in the light file and forgot to mirror it. Focus rings disappear because a new accessibility rule only made it into one sheet. The UI does not just look wrong. It starts to feel broken.

Use Semantic Tokens

The fix is not a better diff tool or stricter code review. The fix is a different way of thinking about color. Stop organizing your styles by literal appearance and start organizing them by purpose. This is where semantic tokens come in.

Instead of assigning a card a white background, assign it a surface background. Instead of choosing between black and off-white for text, choose a text color. The component does not know or care whether the user prefers light or dark. It simply asks for the token that matches its job.

Think about a standard button. In a two-file world, .btn lives in the light stylesheet with a white background and a dark border. Its twin lives in the dark stylesheet with a near-black background and a lighter border. That is twice the code for one button. With tokens, .btn has one declaration: the background is var(--color-surface-secondary) and the border is var(--color-border-default). The values themselves live at the root. When the site is in light mode, --color-surface-secondary resolves to something like #f8f9fa. In dark mode, the same token resolves to #2d2d2d. The button component never changes. Only the data underneath it does.

This distinction between structure and data is subtle but powerful. Your card component defines layout, spacing, typography, and elevation once. Your theme layer defines the palette. That separation is exactly what CSS custom properties were built for.

How the Architecture Changes

This approach fundamentally restructures how you write styles.

The old way usually looks like this:

  • A light card stylesheet defining padding, radius, background, text color, and shadow.
  • A dark card stylesheet redefining most of the same properties just to flip colors.
  • A logic layer deciding which stylesheet to load or which class to toggle on the body.

The new way looks like this:

  • One card stylesheet defining layout and assigning semantic tokens.
  • One theme file defining what those tokens mean in a light context.
  • One theme file, or simply a block in the same file, defining what those tokens mean in a dark context.
  • A single attribute swap that changes the value layer without touching the component layer.

Kurulumu sabit tutarsınız. Sadece veriyi değiştirirsiniz. Tasarımcı üçüncü bir tema, belki yüksek kontrastlı bir mod veya gece mavisi bir varyant eklemek istediğinde, kartı yeniden yazmazsınız. Token haritasına bir atama daha eklersiniz. Bileşen basit ve mutlu kalır. Hala bir yüzey rengi ister. Tema ona hangi yüzey rengini kullanacağını söyler.

Veri Özniteliği ile Geçiş

Uygulama basit ve okunabilir kalabilir. HTML etiketinize data-theme="dark" gibi bir veri özniteliği uygulayın ve token tanımlarınızın bunun altında kapsamlanmasına (scope) izin verin.

Sayfa JavaScript çalışmadan önce doğru şekilde işlensin diye varsayılanlarınızı açık deneyim için :root üzerinde ayarlayın. Ardından [data-theme="dark"] altında token değerlerini geçersiz kılın. Küçük bir script bir geçiş (toggle) tıklamasını izler, özniteliği günceller ve sayfadaki her bileşen anında yanıt verir. Tekil öğeler üzerinde sınıf karmaşası yaşanmaz. İşleme (render) sırasında tamamen ayrı bir stil dosyası içe aktarmanız gerekmez. Tarayıcı değişkenleri zaten bellekte tutar; sadece yeni değerlerle yeniden boyama (repaint) yapar.

Bu, kodunuzu çok pratik bir anlamda temiz tutar. .card ifadesinin her örneğini bulmak için iki dizin arasında grep yapmak zorunda kalmazsınız. Aynı düğüm (node) üzerine yığılmış rakip tema sınıfları arasındaki belirleyicilik (specificity) savaşları hakkında endişelenmenize gerek kalmaz. HTML'iniz okunabilir kalır. CSS'iniz merkezi ve aranabilir kalır.

Mesele Versiyonlar Değil, Değerlerdir

Karanlık mod değerlerle ilgilidir. Kullanıcı arayüzünüzün (UI) ikinci bir versiyonu değildir. Kartınızın köşeleri geceleyin daha yuvarlak hale gelmez. Izgaranız (grid) farklı bir şekle bürünmez. Tipografi ölçeğinizin (type scale) yeni bir ritme ihtiyacı yoktur. Sadece renkler değişir ve bazen gölgeler biraz daha derin nefes alır. Karanlık modu tam bir yeniden kaplama (reskin) olarak ele almak, bakım kabusları yaratan bir aşırı mühendisliktir (over-engineering).

Bunu doğru yapan ekipler, tasarım sistemlerini bir veritabanı gibi ele alır. Bileşenler özellikleri isimlerine göre sorgular. Temalar kayıtları (records) sağlar. Aydınlıktan karanlığa geçmek bir sorgu parametresi değişikliğidir, bir şema yeniden yazımı değildir.

Bu zihniyet sizi tema sapmasından (theme drift) kurtarır. Tek bir kart. Tek bir buton. Boşluklandırma ve boyutlandırma için tek bir doğruluk kaynağı (source of truth). Renk paleti tek bir yerde yaşar, mantıksal olarak eşlenmiştir ve kullanıcının tercih ettiği her türlü ortama hazırdır.

Asıl Çıkarılması Gereken Ders

Eğer aydınlık ve karanlık için iki ayrı CSS dosyası tutuyorsanız, tema oluşturmuyorsunuz demektir; kopyalıyorsunuzdur. Semantik tokenlara geçin, onları kök düzeyinde bir veri özniteliği ile kapsamlayın ve bileşenlerinizin görünümü doğrudan kodlamak (hardcoding) yerine roller talep etmesine izin verin. İlk refaktör çaba gerektirir ancak alternatifi, paralel stil dosyaları arasında bitmek bilmeyen bir köstebek vurma (whack-a-mole) oyunudur. Aynı kartı iki kez yazmak için hayat çok kısa.