Blog / Çalışmalar

Javascript ile karanlık mod yapımı

Bu yazı 2021 yılından. Anlatılan sürümler, fiyatlar ve adresler o günden bu yana değişmiş olabilir.

Karanlık mod, web sitesi tasarımının en önemli yönlerinden biridir. Son birkaç yıldır trend olan bu özellik ziyaretçiler için oldukça kullanışlı. Bu modun tercih edilmesinin en önemli sebeplerinden birisi özellikle karanlık ortamlarda, yüksek parlaklık nedeniyle beyaz ekranların gözleri çok yoruyor olması.

Bugün bu yazıda temel seviye JavaScript kullanarak web sitemiz için karanlık mod diğer adıyla dark mode oluşturacağız. Sistemin işleyişinden bahsetmek gerekirse sitemiz üzerine bir buton ekleyeceğiz, kullanıcı bu buton sayesinde koyu tema ve açık tema arasında geçiş yapabilecek.

Güncelleme (Kasım 2026): Bu yazıyı 2021'de yazmıştım. Eski halinde iki önemli eksik vardı: sayfa yenilenince seçilen tema unutuluyordu ve telefonu ya da bilgisayarı karanlık modda olan ziyaretçiye bile site açık temada açılıyordu. İkisini de ekledim, kodu da baştan düzenledim. İndirme dosyası da güncel.

Yapacağımız karanlık mod şunları yapacak:

  • Ziyaretçi butona bastığında açık ve koyu tema arasında geçiş yapacak.
  • Seçimini hatırlayacak, sayfayı yenilese ya da siteye ertesi gün girse bile aynı temada açılacak.
  • Ziyaretçi henüz bir seçim yapmadıysa cihazının ayarına bakacak. Telefonu karanlık moddaysa site de karanlık açılacak.

Birinci aşama

Öncelikle index.html adında bir dosya oluşturalım ve ihtiyacımız olan temel HTML kodlarını içerisine yazalım. HTML dosyasını oldukça sade tuttuk, çok az öğe barındırıyor. Geçiş butonunu koymak için ortala adında bir div oluşturduk ve butona gecis değerini atadık. Bütün işlemler bittiğinde değişimi görebilmeniz için rastgele bir lorem ipsum metni oluşturup HTML içerisine ekledim.

HTML
<!DOCTYPE html>
<html lang="tr">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Karanlık Mod</title>
    <script>
        // Sayfa ekrana çizilmeden önce hangi temada açılacağına karar veriyoruz
        const kayitliTema = localStorage.getItem('tema');
        const sistemKaranlik = window.matchMedia('(prefers-color-scheme: dark)').matches;
        if (kayitliTema === 'koyu' || (kayitliTema === null && sistemKaranlik)) {
            document.documentElement.classList.add('karanlik-mod');
        }
    </script>
    <link href="https://fonts.googleapis.com/css2?family=Work+Sans&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="stil.css">
</head>
<body>
    <div class="ortala">
        <input type="checkbox" id="gecis" aria-label="Karanlık mod">
    </div>
    <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec placerat odio id mi egestas, et blandit lacus egestas. Fusce viverra massa non metus placerat, id varius risus congue. Duis consequat, mauris et venenatis porta, ipsum lectus luctus neque, nec blandit mauris orci quis nunc. Praesent felis ex, bibendum ac turpis ac, dapibus hendrerit nunc. Proin pellentesque tempus blandit. Maecenas id vulputate libero, vel placerat purus. Proin bibendum erat id felis commodo, id consequat sem porttitor. Fusce vitae molestie purus. Curabitur nibh dolor, sagittis at massa non, suscipit semper augue.
    </p>
    <script src="script.js"></script>
</body>
</html>

Head etiketleri arasında küçük bir script var, onu üçüncü aşamada anlatacağım. Butona verdiğimiz aria-label değeri de ekran okuyucu kullanan ziyaretçilere bu butonun ne işe yaradığını söylüyor, görünüşte hiçbir şey değiştirmiyor.

İkinci aşama

Şimdi ise stil dosyamızı oluşturalım. Yukarıda yer alan HTML kodlarında stil dosyamızı stil.css olarak çektiğimiz için aynı isimde bir CSS dosyası oluşturacağız. Aşağıda yer alan kodlar ile stil dosyamızı dolduralım.

CSS
:root{
    --arkaplan: #ffffff;
    --yazi: #15181f;
    --buton: #101217;
    color-scheme: light;
}
.karanlik-mod{
    --arkaplan: #15181f;
    --yazi: #e5e5e5;
    --buton: #ffffff;
    color-scheme: dark;
}
*,
*:before,
*:after{
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}
body{
    padding: 40px;
    background-color: var(--arkaplan);
    color: var(--yazi);
    transition: background-color 0.3s, color 0.3s;
}
.ortala{
    width: 100%;
    height: 60px;
    position: relative;
    margin-bottom: 40px;
}
#gecis{
    -webkit-appearance: none;
    appearance: none;
    height: 40px;
    width: 75px;
    background-color: var(--buton);
    position: absolute;
    right: 0;
    border-radius: 20px;
    outline: none;
    cursor: pointer;
}
#gecis:focus-visible{
    outline: 3px solid #4a90e2;
    outline-offset: 3px;
}
#gecis:after{
    content: "";
    position: absolute;
    height: 30px;
    width: 30px;
    background-color: #ffffff;
    top: 5px;
    left: 7px;
    border-radius: 50%;
}
.karanlik-mod #gecis:after{
    background-color: transparent;
    box-shadow: 10px 10px #101217;
    top: -4px;
    left: 30px;
}
p{
    font-family: "Work Sans", sans-serif;
    line-height: 30px;
    text-align: justify;
}

Eski yazıdan farklı olarak renkleri en başta değişken olarak tanımladık. :root kısmında açık temanın renkleri, .karanlik-mod kısmında koyu temanın renkleri var. Sayfadaki her yer rengini bu değişkenlerden alıyor (var(--arkaplan) gibi). Böylece karanlık mod açıldığında tek tek her öğeye ayrı kod yazmamıza gerek kalmıyor, değişkenlerin değeri değişince bütün sayfa kendiliğinden koyulaşıyor. Sitenize yeni bir öğe eklediğinizde ona da renk olarak bu değişkenleri vermeniz yeterli.

Bu stil dosyasında koyu renk tonunu #15181f olarak ayarladım. Karanlık modunuz için siyah ve gri tonları arasında istediğiniz bir renk tonu belirleyebilirsiniz. Tam siyah (#000000) yerine biraz açık bir ton seçmenizi tavsiye ederim, tam siyah üzerinde beyaz yazı uzun süre okurken gözü daha çok yoruyor.

Birkaç küçük detay daha ekledim:

  • color-scheme satırı tarayıcıya hangi temada olduğumuzu söylüyor. Bu sayede kaydırma çubuğu, form alanları gibi tarayıcının kendi çizdiği öğeler de koyu temaya uyuyor.
  • transition satırı temalar arasında geçerken renklerin bir anda değil yumuşak bir şekilde değişmesini sağlıyor.
  • #gecis:focus-visible kısmı, klavyeyle gezen biri Tab tuşuyla butona geldiğinde etrafında mavi bir çerçeve gösteriyor. Eski kodda bu yoktu, klavye kullanan biri butonun nerede olduğunu göremiyordu.
  • Eski kodda HTML'de Work Sans fontunu çağırıp CSS'te Open Sans kullanmışım. İkisini de Work Sans olarak düzelttim.

Üçüncü ve son aşama

Şimdi son ve en önemli aşamaya geldik. Hazırlamış olduğumuz temalar arasında geçiş yapmamızı sağlayacak kısmı JavaScript ile yazacağız. index.html dosyasında JavaScript dosyamızı script.js olarak çağırdığımız için aynı isimde bir JS dosyası oluşturalım ve içeriğini aşağıdaki şekilde yapalım.

JavaScript
const gecis = document.getElementById('gecis');
const sayfa = document.documentElement;

// Sayfa karanlık modda açıldıysa buton da o konumda başlasın
gecis.checked = sayfa.classList.contains('karanlik-mod');

gecis.addEventListener('change', function () {
    sayfa.classList.toggle('karanlik-mod', gecis.checked);
    localStorage.setItem('tema', gecis.checked ? 'koyu' : 'acik');
});

Kodda yaptığımız şey şu: gecis butonunun durumu değiştiğinde, yani ziyaretçi butona tıkladığında ya da klavyeden boşluk tuşuyla seçtiğinde, sayfaya karanlik-mod sınıfını ekliyoruz ya da kaldırıyoruz. Aynı anda ziyaretçinin seçimini tarayıcının hafızasına (localStorage) koyu ya da acik olarak kaydediyoruz. localStorage'a kaydedilen bilgi tarayıcı kapatılsa bile silinmiyor.

Kaydettiğimiz bu bilgiyi okuyan kısım ise index.html'in head kısmına koyduğumuz script:

HTML
    <script>
        // Sayfa ekrana çizilmeden önce hangi temada açılacağına karar veriyoruz
        const kayitliTema = localStorage.getItem('tema');
        const sistemKaranlik = window.matchMedia('(prefers-color-scheme: dark)').matches;
        if (kayitliTema === 'koyu' || (kayitliTema === null && sistemKaranlik)) {
            document.documentElement.classList.add('karanlik-mod');
        }
    </script>

Bu script sayfa açılırken çalışıyor ve şuna bakıyor: ziyaretçi daha önce koyu temayı seçtiyse ya da hiç seçim yapmamış ama cihazı karanlık moddaysa (prefers-color-scheme: dark), sayfaya karanlık mod sınıfını ekliyor. Cihazın karanlık modda olup olmadığını tarayıcı bize bu şekilde söyleyebiliyor.

Peki bu kodu neden script.js içine değil de head kısmına yazdık? Çünkü script.js sayfanın en sonunda yükleniyor. Temayı orada uygulasaydık sayfa önce bir anlığına beyaz açılıp sonra koyulaşırdı. Karanlık modu seçen biri için her sayfa geçişinde ekranın beyaz yanıp sönmesi hiç hoş değil. Head kısmındaki script sayfa daha ekrana çizilmeden çalıştığı için bu yanıp sönme olmuyor. Aynı sebepten sınıfı eski yazıdaki gibi body'ye değil, sayfanın en üst etiketi olan html'e (document.documentElement) ekliyoruz, çünkü head çalışırken body daha oluşmamış oluyor.

Koyu temamız yani karanlık modumuz artık hazır. Çalışma mantığını kavradıysak bunu web sitelerinize kendi yöntemlerinizle uygun şekilde ekleyebilirsiniz. Kodun sağlamış olduğu işlevselliği özelleştirmek tamamen size kalmış. İsterseniz belirlediğiniz tek bir div içeriğini de koyulaştırabilirsiniz ya da bütün web sayfasını koyu temaya da bürüyebilirsiniz.

Eğer karanlık mod yapımında lazım olan dosyaları tek tek oluşturmakla uğraşmak istemiyorsanız doğrudan hazır halini buraya tıklayarak indirebilirsiniz.

Bu yazıyı paylaşXFacebook