Dark Mode Neden Dusundugumuzden Daha Onemli

2025 basinda JekCMS kullanıcılarindan dark mode talepleri gelmeye basladiginda, durst olayim, bunu guzel bir ekstra özellik olarak goruyordum. Sonra rakamlara baktim. 40'tan fazla JekCMS kurulumundaki analitik verilerimiz, aksam 8 ile sabah 6 arasindaki ziyaretcilerin %62'sinin isletim sistemi seviyesinde dark mode kullandigini gosterdi. Bu nisj bir tercih degil — aksam trafiginin cogunlugu.

Daha derin sorun su ki, gece 11'de parlak beyaz bir sayfa sadece kotu gorunmuyor — fiziksel olarak rahatsiz ediyor. OLED ekranlar bunu daha da kotulestirir cunku her beyaz piksel küçük bir isik kaynagi. Dark mode, tam parlaklikta OLED'lerde guc tuketimini %60'a kadar azaltiyor ve bu mobil cihazlarda anlamli bir batarya farkina denk geliyor.

Tema sistemimizi düzgün dark mode destegi için yeniden yapılandırmak için uc hafta harcadim ve ogrendigim her seyi paylasiyorum — kazanimlar, hatalar ve kimsenin uyarmadigi uc durumlar dahil.

CSS Custom Properties Stratejisi

Surdurulebilir herhangi bir dark mode sisteminin temeli CSS custom properties (degiskenler). Bunu ayri stil dosyalari veya bireysel elemanlardaki sinif gecersiz kilmalariyla yapmaya kalkarsaniz, bir ay icinde surdurulemez bir karmasayla karsilasirsiniz.

Temel prensip sudur: her rengi :root üzerinde custom property olarak tanimlayin, sonra dark mode aktif oldugunda bu özellikleri gecersiz kilin. Stil dosyanzdaki her eleman özelliklere referans verir, ham renk degerlerine degil.

:root {
  /* Yuzey renkleri */
  --color-bg-primary: #ffffff;
  --color-bg-secondary: #f5f5f5;
  --color-bg-tertiary: #e8e8e8;
  --color-bg-elevated: #ffffff;

  /* Metin renkleri */
  --color-text-primary: #1a1a1a;
  --color-text-secondary: #555555;
  --color-text-tertiary: #888888;
  --color-text-inverse: #ffffff;

  /* Kenarlk renkleri */
  --color-border-default: #d0d0d0;
  --color-border-subtle: #e5e5e5;

  /* Marka renkleri */
  --color-accent: #2563eb;
  --color-accent-hover: #1d4ed8;
  --color-accent-text: #ffffff;

  /* Anlamsal renkler */
  --color-success: #16a34a;
  --color-warning: #ca8a04;
  --color-error: #dc2626;

  /* Golge */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);

  /* Gecisler */
  --transition-colors: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease;
}

Degiskenleri --dark-bg veya --light-text gibi adlandirmadigima dikkat edin. Bu yaygin bir hatadir. Islevlerine gore adlandirin, gorunumlerine gore degil. --color-bg-primary ana arka plandir — beyaz veya koyu gri olmasindan bağımsız.

Dark Mode Gecersiz Kilma

Koyu tema ayni özellikleri gecersiz kilar. CSS sinifi yerine <html> elemaninda [data-theme="dark"] ozelligi kullaniyorum cunku data attribute'leri anlamsal olarak daha dogru — bir stili degil, bir durumu tanimliyorlar.

[data-theme="dark"] {
  --color-bg-primary: #0f0f0f;
  --color-bg-secondary: #1a1a1a;
  --color-bg-tertiary: #262626;
  --color-bg-elevated: #1f1f1f;

  --color-text-primary: #e5e5e5;
  --color-text-secondary: #a3a3a3;
  --color-text-tertiary: #737373;
  --color-text-inverse: #0f0f0f;

  --color-border-default: #333333;
  --color-border-subtle: #262626;

  --color-accent: #60a5fa;
  --color-accent-hover: #93c5fd;
  --color-accent-text: #0f0f0f;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.5);
}

Burada dikkat edilmesi gereken birkac sey var. Koyu arka plan #0f0f0f, saf #000000 degil. Saf siyah metinle cok fazla kontrast oluşturur ve goz yorgunluguna neden olur. OLED ekranlarda saf siyah ayrica kaydırrma sirasinda bir "bulaniclik" etkisi oluşturur cunku pikseller tamamen kapanir ve tekrar acilmada hafif gecikme yasarlar. #0f0f0f veya #121212 gibi cok koyu bir gri her iki sorunu da onler.

Vurgu rengi #2563eb'den (blue-700) #60a5fa'ya (blue-400) kayar. Daha koyu maviler, koyu arka planlara karsi yeterli kontrasta sahip degildir. Vurgu renklerinizi renk olceginde 2-3 adim daha acik olmasi gerekir.

prefers-color-scheme Media Query

Herhangi bir degistirme arayuzu oluşturmadan once, kullanıcınin isletim sistemi tercihine saygi gostermelisiniz. prefers-color-scheme media query'si birinin isletim sistemi seviyesinde dark mode'u etkinlestirip etkinlestirmedigini tespit etmenizi sağlar.

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --color-bg-primary: #0f0f0f;
    --color-bg-secondary: #1a1a1a;
    /* ... tum koyu gecersiz kilmalar ... */
  }
}

Su selektor — :root:not([data-theme="light"]) — anahtardir. Anlami sudur: isletim sistemi tercih ettiginde dark mode'u uygula, ANCAK kullanıcı bu sitede acikca acik modu secmisse uygulama. Bu uc durumlu bir sistem oluşturur: otomatik (isletim sistemini takip et), zorlanmis acik ve zorlanmis koyu.

Tema Degistiriciyi Oluşturma

Degistirici uc sey yapmalidir: gorusel temayi aninda degistir, tercihi localStorage'a kaydet ve sayfa oluşturulmadan once kaydedilen tercihi yukle — boylece yanlis tema parlmasi (FOWT) onlenir.

class ThemeSwitcher {
  constructor() {
    this.STORAGE_KEY = 'jekcms-theme';
    this.theme = this.getSavedTheme();
    this.applyTheme(this.theme);
    this.bindToggle();
  }

  getSavedTheme() {
    const saved = localStorage.getItem(this.STORAGE_KEY);
    if (saved === 'light' || saved === 'dark') return saved;
    return 'auto';
  }

  getEffectiveTheme() {
    if (this.theme !== 'auto') return this.theme;
    return window.matchMedia('(prefers-color-scheme: dark)').matches
      ? 'dark' : 'light';
  }

  applyTheme(theme) {
    this.theme = theme;
    const effective = this.getEffectiveTheme();
    document.documentElement.setAttribute('data-theme', effective);
    localStorage.setItem(this.STORAGE_KEY, theme);
    this.updateToggleIcon(effective);
  }

  cycle() {
    const order = ['auto', 'light', 'dark'];
    const current = order.indexOf(this.theme);
    const next = order[(current + 1) % order.length];
    this.applyTheme(next);
  }

  bindToggle() {
    const btn = document.querySelector('[data-theme-toggle]');
    if (!btn) return;
    btn.addEventListener('click', () => this.cycle());

    window.matchMedia('(prefers-color-scheme: dark)')
      .addEventListener('change', () => {
        if (this.theme === 'auto') this.applyTheme('auto');
      });
  }

  updateToggleIcon(effective) {
    const btn = document.querySelector('[data-theme-toggle]');
    if (!btn) return;
    const icons = { auto: '◔', light: '☀', dark: '☾' };
    btn.textContent = icons[this.theme];
    btn.setAttribute('aria-label', 'Tema: ' + this.theme);
  }
}

document.addEventListener('DOMContentLoaded', () => new ThemeSwitcher());

Uc durumlu dongü (otomatik, acik, koyu) ikili bir degistirmeden daha iyidir cunku kullanıcılarin isletim sistemlerinin ne oldugunu hatirlamaya çalışmadan "isletim sistemimi takip et" secenegine geri donmelerini sağlar.

Yanlis Tema Parlamasini Onleme

En büyük dark mode kullanıcı deneyimi sorunu, JavaScript çalışmasinda once görünen beyaz parlamadir. Birisi koyu modu tercih ediyorsa ve sayfaniz gecis yapmadan once 200ms beyaz yukleniyorsa, bu parlama rahatsiz edici — özellikle gece.

Cozum, herhangi bir stil dosyasi yuklenmeden once <head> icerisinde küçük bir satir ici betik:

<script>
(function() {
  var saved = localStorage.getItem('jekcms-theme');
  var theme = saved || 'auto';
  var effective = theme;
  if (theme === 'auto') {
    effective = window.matchMedia('(prefers-color-scheme: dark)').matches
      ? 'dark' : 'light';
  }
  document.documentElement.setAttribute('data-theme', effective);
})();
</script>

Bu, tarayıcı herhangi bir sey cizmeden once senkron olarak çalışır, bu nedenle dogru tema ilk kareden itibaren uygulanir.

Gecis Animasyonlari

Ani bir renk degisimi bozuk görünür. Yumusak bir gecis kasitli hissettirir:

*,
*::before,
*::after {
  transition: var(--transition-colors);
}

Bu basit yaklasimdir ve cogu site için iyi çalışır. 0.2s süresi hizli hissettirmek için yeterince kisa ama görünür olmak için yeterince uzundur. Ancak bu joker karakter gecisinin bir maliyeti var: sayfadaki her elemana uygulanir.

Dark Mode'da Görsel Yönetimi

Görseller, dark mode'un kimsenin ilk seferinde dogru yapamadigi kismidir. Birkac görsel kategorisi vardir ve her biri farkli muamele gerektirir.

Fotograflar

Normal fotograflar degistirilmemeli. Fotograflara herhangi bir filtre veya opaklk degisikligi uygulamayin. Bir gun batimi fotografi her iki modda da ayni gorunmeli. Yapabileceginiz tek sey, görsel kenarlarinin koyu arka plandan ayirt edilebilmesi için hafif bir kenarlk veya golge eklemektir.

Diyagramlar ve Ekran Goruntuleri

Beyaz arka planli diyagramlar ve ekran görüntuleri dark mode'da parlayan dikdortgenler gibi görünür. En iyi cozum <picture> elemani kullanarak ayri versiyonlar saglamaktir. Ayri versiyonlar mevcut degilse, bir CSS filtresi renkleri ters cevirmeden parlakli azaltabilir:

[data-theme="dark"] .diagram img {
  filter: brightness(0.85) contrast(1.1);
}

Logolar ve Ikonlar

currentColor kullanan SVG ikonlar otomatik olarak uyum sağlar. Seffaf arka planli raster logolar için koyu arka planlar için acik bir versiyon gerekebilir.

Soz Dizimi Vurgulama Temalari

Siteniz kod bloklari iceriyorsa — ve herhangi bir CMS blogu icerecektir — eslesyen soz dizimi vurgulama temalarina ihtiyaciniz var. JekCMS, One Dark/One Light eslesmesine dayanan özel bir sema kullanir.

:root {
  --code-bg: #f6f8fa;
  --code-text: #24292e;
  --code-keyword: #d73a49;
  --code-string: #032f62;
  --code-comment: #6a737d;
  --code-function: #6f42c1;
}

[data-theme="dark"] {
  --code-bg: #161b22;
  --code-text: #c9d1d9;
  --code-keyword: #ff7b72;
  --code-string: #a5d6ff;
  --code-comment: #8b949e;
  --code-function: #d2a8ff;
}

Form Elemani Stillendirmesi

Form elemanlari dark mode'un en sinir bozucu kismdir cunku tarayıcılar kendi stillerini uygular. Input'lar, textarea'lar ve select'ler acik koyu mod stillerine ihtiyac duyar aksi halde beyaz kalirlar.

input,
textarea,
select {
  background-color: var(--color-bg-elevated);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border-default);
}

/* Dark mode'da otomatik doldurma arka planini düzelt */
[data-theme="dark"] input:-webkit-autofill {
  -webkit-text-fill-color: var(--color-text-primary);
  -webkit-box-shadow: 0 0 0px 1000px var(--color-bg-elevated) inset;
  transition: background-color 5000s ease-in-out 0s;
}

Su otomatik doldurma hilesi cirkin ama gerekli. Chrome'un otomatik doldurmasi, normal CSS ile gecersiz kilamayacaginiz opak sari bir arka plan uygular. Box-shadow hilesi onu tema renginizle orter.

Tarayicilar Arasi Test

Dark mode davranisi tarayıcılar arasinda beklediginizden daha fazla farklilik gosterir:

  • Chrome/Edge (Chromium): prefers-color-scheme isletim sistemi ayarini takip eder. Otomatik doldurma arka planlari box-shadow hilesine ihtiyac duyar.
  • Firefox: Dark mode'u desteklemeyen sayfalarda koyu renkleri zorlayabilen kendi gecersiz kilmasi vardir. Sizin acik dark mode uygulamaniz Firefox'un kendisini uygulamasini onler.
  • Safari: macOS ve iOS'ta prefers-color-scheme'e saygi gosterir. color-scheme CSS ozelligi burada özellikle onemlidir.
:root {
  color-scheme: light;
}

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

color-scheme ozelligi tarayıcıya sayfanizin hangi renk semalarini destekledigini soyler. Safari'de bu, sayfa yükleme sirasinda varsayilan arka plan rengini degistirir, kaydırrma cubugu gorunumunu ayarlar ve yerel form kontrol renklerini degistirir.

Performans Etkisi

Dark mode'u test kurulumlarimiza dagittiktan sonra olctuklerimiz:

  • CSS dosya boyutu artisi: Tum koyu mod gecersiz kilmalari için 1.8 KB (gzip'li)
  • JavaScript: Tema degistirici için 680 bayt minify edilmis
  • Ilk boyama etkisi: Tespit edilemez (satir ici head betigi 1ms'den az ekler)
  • Degistirmede yeniden akim: Tek stil yeniden hesaplamasi, düzeni kaydırrma yok

CSS custom properties yaklasimi, tarayıcınin tema degistiginde yalnizca özellik degerlerini yeniden hesaplamasi gerektigini ifade eder — selektor eslesmelerini yeniden degerlendirmesi veya ozgullugu yeniden hesaplamasi gerekmez. Bu nedenle custom properties, onlarca selektoru degistiren sinif tabanli yaklasimlara gore temalama için temelden daha hizlidir.

Erisilebilirlik Hususlari

Dark mode sadece görsel bir tercih degildir — isik hassasiyeti, migren ve belirli gorme bozukluklari olan kisiler için bir erişilebilirlik ozelligidir. Koyu temanizin WCAG AA kontrast oranlarini korudugundan emin olun (normal metin için 4.5:1, büyük metin için 3:1). Yukarida listeledigim renk degerleri AA uyumlulugunu karsilar.

Geliştirme sirasinda bir kontrast denetleyici kullanin. WebAIM kontrast denetleyicisini bir sekmede acik tutuyorum ve her iki temada da her metin/arka plan kombinasyonunu test ediyorum. 10 dakika suruyor ve erişilebilirlik basarisizliklarini onluyor.

Tema degistirici klavyeyle erişilebilir olmali (<button> elemani kullandigimiz için oyle) ve durumunu aria-label araciligiyla ekran okuyuculara duyurmali. Tema degistiginde etiket mevcut modu yansitacak sekilde güncellenir.