Aynı CSS özelliğini ayarlayan iki Tailwind sınıfını bir elemente birlikte yazdığınızda, kazanan sınıfı class niteliğindeki sıra değil, üretilen CSS dosyasındaki sıra belirler. class="grid flex" yazan bir div, flex sonda olmasına rağmen display: grid alır, çünkü derlenmiş CSS'te .grid kuralı .flex kuralından sonra gelir. Bu yüzden en güvenli kural basittir: çakışan iki sınıfı aynı elemente hiç yazmayın, koşula göre yalnızca birini verin. Gerçekten zorlamanız gerektiğinde sınıfın sonuna ! ekleyerek onu !important yapabilirsiniz.

Bu yazıda çakışma kuralını v4.3.5 ile derlenmiş çıktılarla gösteriyoruz, responsive varyantlarla ortaya çıkan daha sinsi bir çakışmayı inceliyoruz, important modifier'ının nasıl yazıldığını ve tailwindcss canonicalize komutunun gereksiz sınıfları nasıl ayıkladığını anlatıyoruz. Katmanlar ve important bayrağı Tailwind @layer katmanları yazısında, serinin tamamı ise Tailwind CSS öğrenme rehberi sayfasında.

HTML sırası neden önemsiz?

HTML sırası neden önemsiz? grid flex, px-2 p-4, text-sm text-lg, bg-teal-500 bg-red-500!

CSS'te iki kural aynı elemente aynı özgüllükle uygulandığında, stil dosyasında sonra gelen kazanır. class niteliği ise sadece bir sınıf listesidir; tarayıcı için class="a b" ile class="b a" arasında hiçbir fark yoktur. Tailwind'in her utility sınıfı tek bir sınıf seçicisi kullandığı için özgüllükler eşittir ve karar tamamen dosyadaki sıraya kalır. Bu sırayı da siz değil, Tailwind belirler. Beş farklı çakışmayı tek dosyada derledik:

html
<div class="grid flex"></div>
<div class="px-2 p-4"></div>
<div class="text-sm text-lg"></div>
<div class="bg-teal-500 bg-red-500!"></div>
<div class="p-4 md:p-8 px-6"></div>

v4.3.5 ile derlenen CSS'in utilities katmanı:

css
@layer utilities {
  .flex {
    display: flex;
  }
  .grid {
    display: grid;
  }
  .bg-red-500\! {
    background-color: var(--color-red-500) !important;
  }
  .bg-teal-500 {
    background-color: var(--color-teal-500);
  }
  .p-4 {
    padding: calc(var(--spacing) * 4);
  }
  .px-2 {
    padding-inline: calc(var(--spacing) * 2);
  }
  .px-6 {
    padding-inline: calc(var(--spacing) * 6);
  }
  .text-lg {
    font-size: var(--text-lg);
    line-height: var(--tw-leading, var(--text-lg--line-height));
  }
  .text-sm {
    font-size: var(--text-sm);
    line-height: var(--tw-leading, var(--text-sm--line-height));
  }
  @media (width >= 48rem) {
    .md\:p-8 {
      padding: calc(var(--spacing) * 8);
    }
  }
}

Şimdi her satırı çıktıya bakarak okuyalım:

  • grid flex: .grid sonra geldiği için display: grid kazanır. HTML'de flex'in sonda olması bir şey değiştirmez.
  • px-2 p-4: Kısa yazım olan padding önce, padding-inline sonra geliyor. Sonuç: dikeyde p-4 (1rem), yatayda px-2 (0.5rem). Bu örnekte iki sınıf zaten farklı şeyler söylemek için birlikte kullanılabilir; çakışma yalnızca yatay eksendedir.
  • text-sm text-lg: Bu derlemede .text-sm, .text-lg'den sonra yazıldı; dolayısıyla HTML'de son olan text-lg değil, text-sm uygulanır. Kök yazı boyutu 16px kabul edilirse metin 14px (0.875rem) olur.
  • bg-teal-500 bg-red-500!: !important taşıyan kural, dosyada önce gelmesine rağmen kazanır. Arka plan kırmızıdır.
  • p-4 md:p-8 px-6: Bunu bir sonraki bölümde ayrıca inceliyoruz.

Buradan çıkan ders, sınıf sırasını ezberlemeye çalışmamak gerektiğidir. Tailwind'in sıralama mantığı bir uygulama ayrıntısıdır ve sürümler arasında değişebilir; yükseltme kılavuzu örneğin özel utility sınıflarının özellik sayısına göre sıralandığını belirtir. Güvendiğiniz tek şey "bir elementte aynı özelliği ayarlayan iki sınıf olmasın" ilkesi olmalı.

Responsive varyantlarla gelen gizli çakışma

Son örnekteki p-4 md:p-8 px-6 listesine bakan biri muhtemelen şunu bekler: mobilde 1rem dikey ve 1.5rem yatay padding, md ve üstünde 2rem dikey ve yine 1.5rem yatay. Ancak çıktı farklı bir şey söylüyor. Varyantlı kurallar, yani @media (width >= 48rem) bloğu, temel utility kurallarının hepsinden sonra gelir. md ve üstünde .md\:p-8 kuralı devreye girdiğinde padding kısa yazımı dört yönün hepsini 2rem yapar ve kendisinden önce gelen .px-6 kuralını ezer. Sonuç olarak md ve üstünde yatay padding 1.5rem değil, 2rem olur.

Bu tür durumlarda niyetinizi her eksen için ayrı ayrı yazmak daha açıktır: px-6 py-4 md:py-8. Böylece hiçbir sınıf bir diğerinin alanına taşmaz ve sonuç sıralamaya bağlı kalmaz. Aynı durum m-*/mx-*, border/border-x, rounded/rounded-t gibi kısa ve uzun yazım çiftleri için de geçerlidir. Responsive önceliklerin genel mantığı Tailwind responsive tasarım yazısında anlatılıyor.

Doğru yaklaşım: yalnızca bir sınıf verin

Doğru yaklaşım: yalnızca bir sınıf verin

Tailwind belgelerinin önerisi nettir: aynı elemente çakışan iki sınıf koymayın, istediğiniz sınıfı koşula göre seçin. Örneğin bir bileşen hem grid hem flex düzende gösterilebiliyorsa, iki sınıfı birden yazıp birinin kazanmasını ummak yerine koşullu ifade ile yalnızca birini üretin. Koşulun içinde tam sınıf adları yazılmalıdır; "text-" + renk + "-600" gibi parçalardan birleştirilen adlar Tailwind tarafından görülmez ve CSS'i üretilmez. Bu konu sınıf tarama ve @source yazısının ana başlıklarından biri.

html
<!-- Kötü: iki sınıf yarışıyor, sonucu CSS sırası belirliyor -->
<div class="flex grid">...</div>

<!-- İyi: şablon dilinde koşula göre tek ve tam bir sınıf -->
<div class="{{ izgara ? 'grid' : 'flex' }}">...</div>

Belgeler bir adım daha ileri gider: React veya Vue gibi bileşen tabanlı projelerde, bileşeni kullananların dışarıdan rastgele sınıf eklemesine izin vermek yerine, özelleştirme için belirli prop'lar tanımlamayı önerir. Çünkü dışarıdan eklenen sınıflar çoğu zaman bileşenin kendi sınıflarıyla çakışır ve hangisinin kazanacağı öngörülemez hâle gelir.

Important modifier: sınıfın sonuna ! eklemek

Başka hiçbir yolla özgüllüğü yönetemediğinizde, örneğin üçüncü taraf bir bileşenin yüksek özgüllüklü kuralını ezmeniz gerektiğinde, sınıf adının sonuna ! eklersiniz. Varyantlı sınıflarda da işaret en sona gelir: md:p-6!, hover:bg-red-600/50!. Yükseltme kılavuzu, v3'teki baştaki ünlem yazımının (!p-2) hâlâ çalıştığını ama kullanımdan kaldırıldığını (deprecated) belirtir. İkisini birlikte derledik:

html
<div class="hover:bg-red-500 hover:bg-blue-500"></div>
<div class="!p-2 md:p-6!"></div>

v4.3.5 ile derlenen CSS:

css
@layer utilities {
  .\!p-2 {
    padding: calc(var(--spacing) * 2) !important;
  }
  @media (hover: hover) {
    .hover\:bg-blue-500:hover {
      background-color: var(--color-blue-500);
    }
    .hover\:bg-red-500:hover {
      background-color: var(--color-red-500);
    }
  }
  @media (width >= 48rem) {
    .md\:p-6\! {
      padding: calc(var(--spacing) * 6) !important;
    }
  }
}

Eski yazım .\!p-2 seçicisiyle, yeni yazım .md\:p-6\! seçicisiyle üretildi; her ikisi de !important taşıyor. md ve üstünde iki important kural yarıştığında yine sonra gelen kazanır, yani padding 1.5rem olur. Aynı örnekteki hover:bg-red-500 hover:bg-blue-500 çifti ise varyantların da çakışabileceğini gösteriyor: hover bloğunda .hover\:bg-red-500 sonra geldiği için üzerine gelindiğinde arka plan kırmızı olur. Hover varyantının neden @media (hover: hover) içinde üretildiği hover, focus ve active durumları yazısında.

canonicalize ile gereksiz sınıfları ayıklamak

Standalone CLI'daki canonicalize alt komutu, verdiğiniz sınıf gruplarını Tailwind'in tasarım sistemine göre sadeleştirip kanonik yazıma dönüştürür. Her tırnaklı argüman bir sınıf grubu sayılır ve sonuç her grup için ayrı satıra yazılır. Kendi denemelerimizde komut sadece eski adları yenilemekle kalmadı, aynı özelliği ayarlayan sınıflardan ezileni de listeden çıkardı:

bash
tailwindcss canonicalize 'grid flex' 'flex grid' 'text-sm text-lg' 'px-4 py-4' 'h-4 w-4' 'top-0 right-0 bottom-0 left-0' '!bg-red-500' 'flex-grow bg-gradient-to-r' 'p-4 md:p-8 px-6'
grid
grid
text-sm
p-4
size-4
inset-0
bg-red-500!
grow bg-linear-to-r
p-4 px-6 md:p-8

Çıktıyı yorumlayalım. grid flex ve flex grid gruplarının ikisi de yalnızca grid olarak döndü, çünkü derlenmiş CSS'te kazanan grid ve flex hiçbir etki bırakmıyor. text-sm text-lg için de aynı şey oldu: kazanan text-sm kaldı. px-4 py-4 tek bir p-4'e, h-4 w-4 bir size-4'e, dört kenar konumu tek bir inset-0'a indirildi. Baştaki ünlem sondaki yazıma, flex-grow ve bg-gradient-to-r gibi eski adlar grow ve bg-linear-to-r'ye çevrildi. Son grupta ise yalnızca sıralama değişti: komut px-6'yı silmedi, çünkü md altındaki ekranlarda o sınıf hâlâ etkilidir.

Bu komut, çakışan sınıfları bulmak için hızlı bir kontrol aracı olarak kullanılabilir: bir sınıf listesi kısalarak dönüyorsa, içinde hiçbir etkisi olmayan bir sınıf var demektir. --format json seçeneği her grup için giriş, çıkış ve changed alanlarını verir; --css ile kendi tema dosyanızı yükleyebilirsiniz. CLI'ın diğer seçenekleri Tailwind CLI standalone kullanımı yazısında.

bash
tailwindcss canonicalize --format json 'h-4 w-4'
[
  {
    "input": "h-4 w-4",
    "output": "size-4",
    "changed": true
  }
]

Mini örnek: dışarıdan sınıf alan bir buton

Çakışmanın en sık yaşandığı yer, tekrar kullanılan bir şablon parçasıdır. Diyelim ki bir buton parçanız var ve içinde bg-blue-600 px-4 py-2 sınıfları sabit. Bir sayfada bu butonu kırmızı yapmak için parçaya dışarıdan bg-red-600 eklediniz. Artık elementte iki arka plan sınıfı var ve hangisinin kazanacağını sınıf sırası değil, Tailwind'in CSS'i yazdığı sıra belirliyor. Yukarıdaki hover örneğinde kırmızı sınıf maviden sonra yazılmıştı, bu yüzden kırmızı kazandı; ama bu sizin seçiminizle değil, Tailwind'in iç sıralamasıyla oldu. Parçayı başka bir renkle kullandığınızda sonucu yeniden kontrol etmeniz gerekir ve bu, aynı kodun bir sayfada beklendiği gibi çalışıp diğerinde çalışmaması riskini doğurur.

Belgelerin önerdiği çözüm, parçanın dışarıdan sınıf yerine bir seçenek almasıdır: renk="tehlike" gibi bir değer, parçanın içinde önceden yazılmış tam bir sınıf listesine eşlenir. Böylece elementte her zaman tek bir arka plan sınıfı bulunur ve sonucun sırayla bir ilgisi kalmaz. Eşleme tablosunda tam sınıf adlarını yazdığınız için Tailwind tarayıcısı da hepsini görür. Bu yaklaşımın hazır bir uygulaması buton varyantları bölümünde var.

Bu örneğin ikinci dersi, sorun çıktığında hızlı teşhis yapabilmektir. Elementin sınıf listesini canonicalize komutuna verdiğinizde sonuç kısalıyorsa, listede etkisiz kalan bir sınıf var demektir. Tarayıcı geliştirici araçlarında üstü çizili görünen bildirimler de aynı şeyi söyler: o sınıfın kuralı üretilmiştir ama başka bir kural tarafından ezilmiştir.

Özel CSS ile utility çakışmaları

Çakışmalar yalnızca iki Tailwind sınıfı arasında olmaz. Kendi yazdığınız bir kural ile bir utility aynı özelliği ayarladığında, karar katmanlara göre verilir: @layer components içindeki bir .card kuralını utility sınıfları ezer; katmansız yazılmış bir kural ise utility sınıflarını ezer. Bu nedenle bir utility sınıfı "çalışmıyor" gibi görünüyorsa, önce o özelliği ayarlayan katmansız bir kural olup olmadığına bakın. Katmanların derlenmiş çıktısını katmanlar yazısında ayrıntılı gösterdik.

Sık yapılan hatalar

Sık yapılan hatalar: Bileşene dışarıdan aynı özellikte sınıf eklemek, Kısa yazım ile responsive varyantı karıştırmak, Son yazılan kazanır sanmak, Her sorunu ! ile çözmek
  • Bileşene dışarıdan aynı özellikte sınıf eklemek: <Buton class="bg-red-500"> içerideki bg-blue-600 ile çakışır; hangisinin kazanacağı CSS sırasına kalır.
  • Kısa yazım ile responsive varyantı karıştırmak: md:p-8, kendisinden önce gelen px-* değerini md ve üstünde ezer.
  • Son yazılan kazanır sanmak: text-sm text-lg örneğinde HTML'de son olan değil, CSS'te sonra gelen kazandı.
  • Her sorunu ! ile çözmek: Important modifier kalıcı bir özgüllük yarışına dönüşür.
  • Ünlemi başa yazmaya devam etmek: Çalışır ama kullanımdan kaldırılmıştır; canonicalize bunu otomatik olarak sona taşır.

Sık Sorulan Sorular

İki sınıftan hangisinin kazanacağını önceden nasıl bilirim?

Güvenilir yol, CSS'i derleyip çıktıya bakmaktır. Daha pratik yol ise tailwindcss canonicalize 'sinif1 sinif2' çalıştırmaktır; tamamen ezilen sınıf sonuçtan çıkarılır. Ama asıl hedef, bunu bilmeye ihtiyaç duymayacak şekilde tek sınıf yazmaktır.

Important modifier hangi tarafa yazılır?

v4'te sınıfın en sonuna: bg-red-500!, md:p-6!. Baştaki ünlem (!bg-red-500) bu derlemede hâlâ üretildi ama yükseltme kılavuzu onu kullanımdan kaldırılmış olarak işaretliyor.

important bayrağı ile modifier aynı şey mi?

Hayır. @import "tailwindcss" important; bütün utility sınıflarını !important yapar; modifier ise yalnızca yazdığınız sınıfı etkiler. Bayrak, Tailwind'i karmaşık eski CSS içeren projelere eklerken düşünülen genel bir ayardır.

Tailwind sürümünü yükseltince kazanan sınıf değişebilir mi?

Sınıfların CSS'e yazılma sırası Tailwind'in iç sıralama mantığına bağlıdır ve belgeler bu sırayı bir sözleşme olarak tanımlamaz. Yükseltme kılavuzunda bile özel utility sınıflarının sıralanma biçimiyle ilgili bir değişiklik anlatılır. Bu yüzden bugün çakışan iki sınıftan birinin "tesadüfen" doğru sonucu verdiği bir kod, ileride farklı davranabilir. Çakışmasız bir sınıf listesi ise sıralamadan bağımsız olduğu için yükseltmelerden etkilenmez; uzun ömürlü projelerde asıl korumanız budur.

Tekrar eden sınıf listelerini kısaltmak için ne yapmalıyım?

Belgeler önce döngüleri, çoklu imleçle düzenlemeyi ve şablon bileşenlerini önerir; tek elementlik küçük kalıplar için @layer components içinde bir sınıf da kabul edilebilir. Hazır kalıplar için kart, buton ve input örnekleri yazısına bakabilirsiniz.

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: Tailwind CSS öğrenme rehberi · Tailwind @layer katmanları · Tailwind CLI kullanımı · Responsive tasarım · Tailwind sınıfı çalışmıyor: sık hatalar · Utility class mantığı