CSS'iniz çalışmıyorsa, nedeni çoğu zaman şu üç gruptan birindedir: tarayıcı bildirimi geçersiz sayıp sessizce attı (yazım hatası, eksik noktalı virgül, yanlış değer türü), bildirim geçerli ama cascade'de başka bir kurala yenildi (özgüllük, kaynak sırası, katman, !important) ya da kural uygulandı ama bir düzen kuralı beklediğiniz sonucu engelliyor (stacking context, margin çökmesi gibi). CSS, JavaScript gibi hata fırlatmaz; MDN'in ifadesiyle tarayıcılar CSS hataları için uyarı göstermez, geçersiz içeriği atar ve sonraki geçerli stilleri ayrıştırmaya devam eder.

Bu yazıda önce tarayıcının hatalı CSS'i nasıl ele aldığını, yani neyin ne kadarının atıldığını, MDN'in hata işleme rehberine dayanarak anlatıyoruz. Ardından en sık karşılaşılan "çalışmıyor" durumlarını belirtiye göre teşhis etmeyi gösteriyoruz. Ayrıntılı konular için seri içindeki ilgili yazılara bağlantı veriyoruz.

Tarayıcı hatalı CSS ile ne yapar?

Tarayıcı hatalı CSS ile ne yapar? Bilinmeyen özellik adı veya geçersiz değer, Eksik noktalı virgül, Seçici listesinde geçersiz bir seçici, At-rule içinde hata

MDN'e göre ayrıştırıcı bir hatayla karşılaştığında, hatayı içeren kısmı yok sayar ve olabildiğince az kodu atarak normal ayrıştırmaya döner. Bu bir eksiklik değil, CSS'in bilinçli bir özelliğidir: eski bir tarayıcı yeni bir özelliği tanımasa bile sayfa bozulmaz. Ne kadar kodun atılacağı ise hatanın türüne bağlıdır:

Hata türüAtılan kısım
Bilinmeyen özellik adı veya geçersiz değerYalnızca o bildirim
Eksik noktalı virgülHatalı bildirim ve ardından gelen bildirim
Seçici listesinde geçersiz bir seçiciBütün kural bloğu
At-rule içinde hataAt-rule ve hatanın türüne göre tek satır ya da bütün kural
Kapanmamış süslü parantezİç içe yazım olarak ne kadar ayrıştırılabildiğine bağlı

Eksik noktalı virgül: iki bildirim birden gider

css
p {
  /* noktalı virgül eksik */
  border-color: red
  background-color: green;
  /* geçerli ama büyük olasılıkla mantık hatası */
  border-width: 100vh;
}
/* sonuç: border-color ve background-color ikisi de atılır;
   border-width: 100vh uygulanır */

Neden iki bildirim birden gidiyor? Ayrıştırıcı bir bildirimi noktalı virgüle ya da kapanış süslü parantezine kadar okur. Noktalı virgül eksik olduğu için border-color değeri red background-color: green olarak okunur; bu geçerli bir <color> değildir ve bildirim atılır. Ayrıştırıcı bir sonraki noktalı virgülden devam ettiği için background-color da kaybolur. Son satırdaki 100vh kenarlık kalınlığı muhtemelen bir hatadır ama sözdizimi geçerlidir; CSS bunu hata saymaz ve uygular. Yani "geçerli" ile "istediğiniz" aynı şey değildir.

Geçersiz seçici bütün bloğu öldürür

Var olmayan bir sınıfı, kimliği ya da öğe adını seçmek mantık hatasıdır ama sözdizimi hatası değildir; kural yalnızca hiçbir şeyle eşleşmez. Buna karşılık bir sözde sınıfın ya da sözde öğenin adındaki yazım hatası geçersiz bir seçici oluşturabilir. Seçici listesindeki tek geçersiz seçici, listenin ve kural bloğunun tamamını geçersiz kılar:

css
h1, h2:hovr, .baslik {
  color: darkblue;
}
/* sonuç: :hovr geçersiz olduğu için h1 ve .baslik de renk almaz */

:is(h1, h2:hovr, .baslik) {
  color: darkblue;
}
/* sonuç: :is() bağışlayıcı liste kabul eder; yalnızca h2:hovr
   yok sayılır, h1 ve .baslik renk alır */

İki istisna vardır. :is() ve :where() bağışlayıcı (forgiving) seçici listesi kabul eder; içlerindeki geçersiz seçici yalnızca hiçbir şeyle eşleşmez. İkinci istisna tarihsel bir nedenden gelir: -webkit- önekiyle başlayan ve parantezle bitmeyen sözde öğeler, tarayıcı onları tanımasa bile geçerli sayılır ve listeyi bozmaz. ::-webkit-hayali-fonksiyon() gibi parantezli bir önekli sözde öğe ise bütün listeyi geçersiz kılar. Bu sözde sınıfların kullanım desenleri için :has(), :is(), :where(), :not() yazısına bakabilirsiniz.

At-rule hataları

At-rule'larda neyin atılacağı kuralın kendi dilbilgisine bağlıdır. MDN'den birkaç önemli örnek:

  • @import yeri: @import, @charset, @layer ve diğer @import ifadeleri dışındaki herhangi bir CSS'ten sonra gelirse yok sayılır. İçe aktardığınız dosyanın hiç yüklenmiyormuş gibi görünmesinin sık nedenidir.
  • @font-face zorunlu tanımlayıcıları: font-family ve src zorunludur; biri eksik ya da geçersizse bütün @font-face kuralı geçersiz olur. Diğer geçersiz tanımlayıcılar ise yalnızca kendileri atılır.
  • @keyframes: Anahtar kare içindeki !important bildirimler ve canlandırılamayan özellikler yok sayılır ama aynı karedeki diğer stilleri etkilemez. 0%'dan küçük, 100%'den büyük ya da % işareti unutulmuş bir anahtar kare seçicisi yalnızca o karenin bloğunu atar. İki anahtar kare bloğu arasına stil yazmak ise bütün @keyframes kuralını geçersiz kılar.
  • @layer kapanış parantezi: Unutulmuş bir kapanış parantezi sözdizimi hatası değil, mantık hatasıdır; sonraki bütün stiller o katmanın içinde sayılır ve hiçbir şey atılmaz.

Yazı tipi tanımlarının ayrıntısı için @font-face ve yazı tipi özellikleri, animasyon kuralları için animation ve @keyframes, katmanlar için @layer yazılarına bakabilirsiniz.

Kapanmamış yapılar ve yorumlar

Stil dosyası bir kural, bildirim, fonksiyon, metin ya da yorum açıkken biterse ayrıştırıcı açık kalan her şeyi otomatik olarak kapatır. Son noktalı virgülden sonraki içerik eksik de olsa geçerliyse normal biçimde ayrıştırılır. MDN yine de bu bağışlayıcılığa güvenmemenizi, her bloğu açıkça kapatmanızı önerir.

Kapanmamış yorum ise daha sinsi bir sorundur. /* ile başlayıp kapanmayan bir yorum, sonraki bir yorumun kapanış işaretine (*/) ya da stil dosyasının sonuna kadar her şeyi yorumun parçası yapar. CSS geçersiz olmaz, ama açılış işaretinden sonraki kodun tamamı yok sayılır. Dosyanın yarısından sonrası birden çalışmayı bıraktıysa ilk bakacağınız yer burasıdır. Yorum sözdizimi için CSS sözdizimi yazısına bakabilirsiniz.

Yanlış tür ve var() tuzağı

Her bildirim, ayrıştırıldıktan sonra o özelliğin dilbilgisine göre denetlenir. background-color: 45deg yazarsanız değer bir açıdır, renk değildir; bildirim geçersizdir ve atılır, özellik daha önceki geçerli değerinde kalır. Özel özelliklerde ise durum farklıdır ve çok sık karıştırılır:

css
.kart {
  background-color: lightyellow;
  background-color: var(--theme-color);
}

:root {
  --theme-color: 45deg;
}
/* sonuç: zemin lightyellow kalmaz, transparent olur */

Adım adım: --theme-color: 45deg bildirimi geçerlidir, çünkü özel özellikler hemen her değeri kabul eder. var(--theme-color) içeren bildirim de ayrıştırma sırasında geçerli görünür; tarayıcı değişkenin hangi değeri taşıyacağını henüz bilmez. Değer hesaplanırken 45deg yerine konduğunda dilbilgisi bozulur. MDN'e göre bu durumda bildirim atılmaz; özellik kalıtılan bir özellikse üst öğeden kalıtılan değeri, değilse başlangıç değerini alır. background-color kalıtılmadığı için başlangıç değeri transparent kullanılır ve önceki satırdaki lightyellow yedeği işe yaramaz.

Bu tuzaktan kaçınmanın yolu değişkeni @property ile türlendirmek ya da var() ile yedek değer vermektir. Ayrıntılar @property ve CSS değişkenleri yazılarında.

Yedekleri doğru sırayla yazın

Geçersiz bildirimlerin atılması, eski ve yeni sözdizimini aynı kuralda bir arada kullanmanıza olanak tanır. Şart, eski sözdiziminin önce, yenisinin sonra yazılmasıdır:

css
div {
  display: inline-flex;
  display: inline flex;
}
/* yeni çok anahtar sözcüklü sözdizimini tanıyan tarayıcı ikinci
   satırı uygular; tanımayan tarayıcı onu atar ve ilk satırda kalır */

Sıra tersine çevrilirse yeni sözdizimini tanıyan tarayıcı da eski değeri uygular, çünkü cascade'de son gelen geçerli bildirim kazanır. Aynı mantık satıcı önekleri (vendor prefix) için de geçerlidir: MDN, önekli özelliklerden mümkün olduğunca kaçınmanızı, kullanmak zorundaysanız önekli sürümleri öneksiz sürümden önce yazmanızı önerir. display değerlerinin ayrıntısı için display değerleri, özellik desteğine göre kural yazmak için @supports yazısına bakabilirsiniz.

Kural geçerli ama uygulanmıyor: cascade

Kural geçerli ama uygulanmıyor: cascade: Özgüllük, !important, Kalıtım beklentisi

Bildiriminiz geçerliyse ve yine de etkisini görmüyorsanız büyük olasılıkla başka bir bildirime yeniliyordur. Cascade, çakışan bildirimleri şu sırayla karşılaştırır: köken ve önem (!important), katmanlar, özgüllük, @scope yakınlığı ve en son kaynaktaki sıra. Özgüllük yalnızca önceki ölçütler eşitse dikkate alınır; bu yüzden daha özgül bir seçici, daha öncelikli bir katmandaki kurala yine de yenilebilir.

  • Özgüllük: #menu a (1-0-1), .nav a (0-1-1) kuralını kaynak sırası ne olursa olsun yener. Hesap için özgüllük hesaplama.
  • !important: Önemli bildirimler normal bildirimlerden ayrı bir öncelikle değerlendirilir; katmanlarla birlikte kullanıldığında sıra tersine döner. Ayrıntı cascade ve kalıtım ve @layer yazılarında.
  • Kalıtım beklentisi: Her özellik kalıtılmaz. Üst öğeye verdiğiniz border çocuklara geçmez, color geçer.

z-index çalışmıyor

z-index, konumlandırılmış öğelerde (position değeri static dışında olanlar) ve flex ile grid öğelerinde çalışır. Normal akıştaki position: static bir öğeye z-index: 9999 vermek bir şey değiştirmez. İkinci ve daha sık neden stacking context'tir: bir öğenin z-index değeri yalnızca kendi stacking context'i içinde anlam taşır ve o bağlam üst bağlamda tek bir birim olarak sıralanır.

css
.kart {
  transform: translateX(0);
}

.kart .acilir-menu {
  position: absolute;
  z-index: 1000;
}

.sonraki-bolum {
  position: relative;
  z-index: 1;
}
/* sonuç: transform değeri none olmadığı için .kart yeni bir stacking
   context oluşturur. Menünün 1000 değeri yalnızca kartın içinde
   geçerlidir; kart sonraki bölümün altında kalıyorsa menü de kalır */

MDN'deki listeye göre stacking context oluşturan durumların bazıları şunlardır: position değeri absolute ya da relative olup z-index değeri auto olmayan öğeler, fixed ve sticky öğeler, opacity değeri 1'den küçük öğeler, transform, filter, backdrop-filter gibi özelliklerden biri none dışında olan öğeler, isolation: isolate ve container-type değeri size ya da inline-size olan öğeler. Tam liste ve örnekler için z-index ve stacking context yazısına bakın.

Margin beklenmedik yerde: margin çökmesi

Blokların üst ve alt marginleri bazı durumlarda birleşir ve tek bir margin oluşur; boyutu marginlerin en büyüğüdür. Bu davranış genellikle iki biçimde "hata" gibi görünür: alt alta iki paragrafın marginleri toplanmaz, büyük olanı kalır; ya da ilk çocuğa verdiğiniz margin-top, üst öğenin içinde değil dışında, üst öğeyi aşağı iterek görünür. İkinci durum, üst öğenin border-top, padding-top veya satır içi içeriği olmadığında olur.

css
.kapsayici {
  background: lightgray;
}

.kapsayici h2 {
  margin-top: 2rem;
}
/* sonuç: boşluk gri zeminin içinde değil üstünde oluşur;
   başlığın marginini kapsayıcının margini ile çöker */

.kapsayici-duzeltilmis {
  background: lightgray;
  padding-top: 1px;
}
/* padding (ya da border) marginleri ayırır; flex veya grid
   kapsayıcıda da marginler çökmez */

MDN'e göre marginler yalnızca dikey yönde çöker; yüzen (float) ve mutlak konumlu öğelerin marginleri hiç çökmez; display değeri flex veya grid olan bir kapsayıcıda da çökme olmaz. Üst öğede yeni bir blok biçimlendirme bağlamı (BFC) oluşturmak da üst-çocuk çökmesini engeller. Bütün kurallar margin çökmesi yazısında.

Belirtiden nedene: hızlı teşhis tablosu

Belirtiden nedene: hızlı teşhis tablosu: Kuraldaki hiçbir stil uygulanmıyor, Arka arkaya iki özellik kayboldu, Dosyanın bir noktasından sonrası çalışmıyor, İçe aktarılan dosya...
BelirtiOlası nedenİlk kontrol
Kuraldaki hiçbir stil uygulanmıyorSeçici listesinde geçersiz seçiciSözde sınıf ve sözde öğe adları
Arka arkaya iki özellik kaybolduEksik noktalı virgülİlk kaybolan bildirimin sonu
Dosyanın bir noktasından sonrası çalışmıyorKapanmamış yorum veya parantezSon çalışan kuraldan sonraki satırlar
İçe aktarılan dosya etkisiz@import yanlış yerdeDosyanın başında mı
Değişkenli renk saydam çıkıyorvar() ile yanlış türde değerDeğişkenin değeri ve türü
Stil başka kurala yeniliyorÖzgüllük, katman, !importantKazanan kuralın seçicisi
z-index etkisizKonumlandırma yok veya stacking contextÜst öğelerde transform, opacity
Üstte beklenmedik boşlukMargin çökmesiÜst öğede padding veya border

Sistemli hata ayıklama adımları

  • 1. Kural eşleşiyor mu? Seçicinin hedeflediğiniz öğeyle gerçekten eşleştiğinden emin olun. Var olmayan bir sınıf adı hata üretmez, yalnızca hiçbir şeyle eşleşmez.
  • 2. Bildirim geçerli mi? Özellik adını, değer türünü ve noktalı virgülleri kontrol edin. MDN'deki "Formal syntax" bölümü özelliğin hangi değerleri kabul ettiğini gösterir.
  • 3. Bildirim kazanıyor mu? Aynı özelliği ayarlayan diğer kuralları bulun; köken, katman, özgüllük ve sırayı karşılaştırın.
  • 4. Değer beklediğiniz gibi hesaplanıyor mu? var(), yüzdeler ve em gibi göreli değerler başka değerlere bağlıdır.
  • 5. Düzen kuralı engelliyor mu? Stacking context, margin çökmesi, taşma (overflow) ve kapsayıcı blok gibi kavramları gözden geçirin.

Taşma ve kırpılma sorunları için overflow, konumlandırma referansının neresi olduğu için position yazılarına bakabilirsiniz.

Sık Sorulan Sorular

Tarayıcı CSS hatalarını neden göstermiyor?

MDN'e göre bu CSS'in tasarımının bir parçasıdır: tarayıcılar hata bildirmek yerine geçersiz içeriği atar ve devam eder. Bu sayede yeni özellikler, onları tanımayan eski tarayıcıları bozmadan kullanılabilir.

Geçersiz bir değer önceki geçerli değeri siler mi?

Normal bir bildirimde hayır; geçersiz bildirim atılır ve önceki geçerli değer kalır. Ancak var() ile oluşan geçersizlik hesaplama anında fark edildiği için özellik kalıtılan ya da başlangıç değerine döner; önceki değer kullanılmaz.

Bir seçici yanlışsa bütün dosya mı bozulur?

Hayır. Yalnızca o seçicinin bulunduğu kural bloğu atılır; ayrıştırıcı kapanış süslü parantezini bulup sonraki kurallardan devam eder. Dosyanın geri kalanı etkileniyorsa kapanmamış bir yorum ya da parantez arayın.

!important ile her sorunu çözebilir miyim?

Sorunu gizleyebilir ama cascade'i daha karmaşık hâle getirir; sonraki bir değişiklikte onu ezmek için yine !important gerekir. Önce neden yenildiğini bulun: özgüllük mü, katman mı, kaynak sırası mı? Çoğu zaman seçiciyi sadeleştirmek ya da katman kullanmak daha kalıcı bir çözümdür.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: CSS öğrenme rehberi · CSS sözdizimi · Özgüllük · z-index · Margin çökmesi