Tailwind CSS v4, ürettiği her stil dosyasının en başına @layer theme, base, components, utilities; satırını koyar. Bu satır dört CSS katmanının önceliğini baştan sabitler: tema değişkenleri en altta, temel (base) stiller onun üstünde, bileşen sınıfları daha üstte, utility sınıfları ise en üstte durur. Kendi CSS'inizi yazarken sorulacak tek soru şudur: bu kural hangi katmana ait? Element varsayılanları @layer base içine, .card gibi bileşen sınıfları @layer components içine, yeni bir utility ise @utility direktifiyle yazılır. Hiçbir katmana koymadığınız CSS ise bütün katmanların önüne geçer.

Bu yazıda katman sırasını v4.3.5 ile derlenmiş gerçek çıktılar üzerinden inceliyoruz, katmansız CSS'in neden utility sınıflarını ezdiğini gösteriyoruz, @layer utilities ile @utility arasındaki farkı ve prefix(tw) ile important bayraklarının ne işe yaradığını anlatıyoruz. Saf CSS tarafındaki @layer kuralının ayrıntıları için CSS @layer ve cascade katmanları yazısına, serinin bütününe ise Tailwind CSS öğrenme rehberi sayfasından ulaşabilirsiniz.

Tailwind'in ürettiği dört katman

Tailwind'in ürettiği dört katman: theme, base, components, utilities

Tailwind bir sınıfı derlediğinde ortaya çıkan CSS rastgele bir sırayla dosyaya yazılmaz; her kural kendi katmanının bloğuna girer. Katmanlar, CSS cascade sisteminin bir parçasıdır ve önceliği belirleyen şey, katmanın dosyada fiziksel olarak nerede durduğu değil, ilk kez hangi sırayla bildirildiğidir. Tailwind bu bildirimi çıktının ikinci satırında yaptığı için, sonradan eklediğiniz bir @layer components bloğu dosyanın en sonunda bile olsa önceliği değişmez.

Katmanİçinde ne varKim yazarÖncelik
theme:root üzerindeki tema değişkenleri (--color-*, --spacing, --text-* ...)Tailwind, @theme bloklarınızdanen düşük
basePreflight sıfırlamaları ve element varsayılanlarıTailwind ve sizin @layer base kurallarınızdüşük
componentscard, btn, badge gibi çok özellikli sınıflarsizin @layer components kurallarınızorta
utilitiesp-4, flex, hover:bg-sky-600 gibi utility sınıfları ve @utility ile tanımladıklarınızTailwind ve sizin @utility tanımlarınızkatmanlar arasında en yüksek

Tabloda dikkat edilmesi gereken nokta, utilities katmanının bileşenlerin üstünde olmasıdır. Bu bilinçli bir tasarım: Tailwind belgeleri, bileşen sınıflarını components katmanına koymanın amacının onları gerektiğinde utility sınıflarıyla ezebilmek olduğunu açıkça söyler. Yani class="card rounded-none" yazdığınızda kart görünümünü alırsınız ama köşeler kare olur.

Katman sırasını derlenmiş çıktıda görmek

Aşağıdaki giriş dosyasında bilerek sırayı karıştırdık: önce bir components bloğu, sonra bir base bloğu, en sonda da hiçbir katmana ait olmayan düz bir kural yazdık. @source inline() ile de p-4 ve rounded-none sınıflarını üretmesini istedik.

css
@import "tailwindcss" source(none);
@source inline("card rounded-none p-4");

@layer components {
  .card {
    background-color: var(--color-white);
    border-radius: var(--radius-lg);
    padding: --spacing(6);
  }
}

@layer base {
  h1 {
    font-size: var(--text-2xl);
  }
}

.serbest {
  padding: 3px;
}

v4.3.5 ile derlenen CSS'in başı ve sonu şöyle (aradaki preflight kuralları kısaltıldı):

css
/*! tailwindcss v4.3.5 | MIT License | https://tailwindcss.com */
@layer theme, base, components, utilities;
@layer theme {
  :root, :host {
    /* (kısaltıldı) */
    --color-white: #fff;
    --spacing: 0.25rem;
    --text-2xl: 1.5rem;
    --radius-lg: 0.5rem;
    /* (kısaltıldı) */
  }
}
@layer base {
  /* (kısaltıldı) */
}
@layer utilities {
  .rounded-none {
    border-radius: 0;
  }
  .p-4 {
    padding: calc(var(--spacing) * 4);
  }
}
@layer components {
  .card {
    background-color: var(--color-white);
    border-radius: var(--radius-lg);
    padding: calc(var(--spacing) * 6);
  }
}
@layer base {
  h1 {
    font-size: var(--text-2xl);
  }
}
.serbest {
  padding: 3px;
}

Çıktıda üç ayrıntı öğreticidir. Birincisi, @layer components bloğu dosyada utilities bloğundan sonra geliyor; buna rağmen ikinci satırdaki sıralama bildirimi yüzünden utilities yine kazanır. İkincisi, sizin yazdığınız @layer base kuralı ayrı bir blok olarak sona eklenmiş ama aynı base katmanına dahil olduğu için Preflight ile aynı öncelik düzeyinde yarışır; aynı katman içinde sonra gelen kural kazandığından sizin h1 boyutunuz Preflight'ın font-size: inherit kuralının önüne geçer. Üçüncüsü, --spacing(6) fonksiyonu derlemede calc(var(--spacing) * 6) ifadesine dönüşmüş; bu fonksiyonun ayrıntısı Tailwind --spacing() ve --alpha() fonksiyonları yazısında.

Bir başka gözlem de card kelimesiyle ilgili: @source inline() içinde yazmamıza rağmen Tailwind bunun için bir utility üretmedi, çünkü card Tailwind'in tanıdığı bir utility değil. .card kuralı sadece sizin yazdığınız düz CSS olarak çıktıya geçti. Tarayıcı açısından bir fark yoktur; HTML'de class="card" yazdığınızda kural uygulanır.

Katmansız CSS neden utility sınıflarını ezer?

CSS katman kurallarına göre hiçbir katmana ait olmayan (katmansız) normal kurallar, katmanlı kuralların hepsinden sonra değerlendirilir ve onları geçer. Tailwind'in bütün çıktısı katmanlar içinde olduğu için, giriş dosyanıza doğrudan yazdığınız bir kural, aynı özelliği ayarlayan bir utility sınıfını ezer. Aşağıdaki örnekte HTML'de hem kutu hem p-4 var:

html
<div class="kutu p-4"></div>
css
@import "tailwindcss" source(none);
@source "./ornek.html";

.kutu {
  padding: 2px;
}

v4.3.5 ile derlenen CSS'in ilgili kısmı:

css
@layer utilities {
  .p-4 {
    padding: calc(var(--spacing) * 4);
  }
}
.kutu {
  padding: 2px;
}

İki seçicinin özgüllüğü aynı olsa da .kutu katmansız olduğu için padding 2px kalır ve p-4 etkisiz görünür. Bu, Tailwind'e geçiş yapılan eski projelerde sık görülen bir şaşkınlık kaynağıdır: eski stil dosyasını olduğu gibi Tailwind girişine eklediğinizde, eski kurallar utility sınıflarının önüne geçer. Çözüm, eski kuralları uygun katmana taşımak ya da bilerek katmansız bırakmaktır. Bu davranışın arkasındaki cascade mantığını CSS @layer yazısında ayrıntılı anlattık.

Kendi CSS'inizi nereye yazmalısınız?

Kendi CSS'inizi nereye yazmalısınız? Sayfa geneli varsayılan mı?, Belirli bir HTML elementinin varsayılanı mı?, Birden çok özelliği olan, adlandırılmış bir sınıf mı?, Tailwind'de...

Tailwind belgeleri, özel stil ekleme konusunda kademeli bir yol önerir. İlk tercih her zaman HTML içindeki utility sınıflarıdır; ancak bu yetmediğinde katman seçimi şu sorulara göre yapılır:

  • Sayfa geneli varsayılan mı? Arka plan rengi, yazı tipi, metin rengi gibi sayfa genelini ilgilendiren kararlar için belgeler önce <html> veya <body> elementine sınıf vermeyi önerir. Böylece temel kararlar ayrı bir dosyada saklı kalmaz, markup içinde görünür.
  • Belirli bir HTML elementinin varsayılanı mı? Tüm h1 veya h2 başlıklarına boyut vermek gibi işler @layer base içine yazılır. Preflight bu elementlerin boyutunu sıfırladığı için bu katman doğal yeridir; Preflight'ın neleri sıfırladığını Tailwind Preflight yazısında bulabilirsiniz.
  • Birden çok özelliği olan, adlandırılmış bir sınıf mı? .card, .btn, .badge ya da üçüncü taraf bir kütüphanenin sınıflarına ait stiller @layer components içine gider. Utility sınıfları bu katmanı ezebildiği için tek tek istisnalar HTML'den yönetilebilir.
  • Tailwind'de karşılığı olmayan tek amaçlı bir CSS özelliği mi? Bunun yeri @utility direktifidir. Tanımladığınız sınıf utilities katmanına girer ve hover:, md: gibi varyantlarla otomatik çalışır. Ayrıntılar @utility direktifi yazısında.
  • Tasarım belirteci (renk, font, aralık) mi? Bunlar katman değil, @theme işidir; değişkenler theme katmanına yazılır ve ilgili utility sınıflarını da oluşturur. Ayrıntılar @theme direktifi yazısında.

Bileşen sınıflarını yazarken utility sınıflarını CSS içine taşımak isterseniz @apply kullanabilirsiniz; bu direktifin ne zaman mantıklı olduğunu @apply ve bileşen sınıfları yazısında tartıştık. Belgeler, bileşen sınıflarına çoğu zaman sanıldığı kadar ihtiyaç olmadığını, tekrar eden markup için önce döngüleri, çoklu imleç düzenlemeyi ve şablon bileşenlerini düşünmeyi önerir.

@layer utilities ile @utility arasındaki fark

v3 alışkanlığıyla @layer utilities içine bir sınıf yazıp onu hover: veya md: ile kullanmayı denemek, v4'te beklediğiniz sonucu vermez. Yükseltme kılavuzu, v4'te @layer utilities ve @layer components bloklarının artık utility kaydetmediğini, bunun için @utility kullanılması gerektiğini belirtir. Aynı özelliği iki yolla tanımlayıp ikisini de varyantla kullandık:

html
<p class="hover:katman-sinifi md:arac-sinifi"></p>
css
@import "tailwindcss" source(none);
@source "./ornek.html";

@layer utilities {
  .katman-sinifi {
    content-visibility: auto;
  }
}

@utility arac-sinifi {
  content-visibility: auto;
}

v4.3.5 ile derlenen CSS:

css
@layer utilities {
  @media (width >= 48rem) {
    .md\:arac-sinifi {
      content-visibility: auto;
    }
  }
  .katman-sinifi {
    content-visibility: auto;
  }
}

md:arac-sinifi için @media (width >= 48rem) bloğu üretildi; hover:katman-sinifi için ise hiçbir kural yok. .katman-sinifi sadece yazdığınız düz CSS olarak, utilities katmanının içinde kaldı. Kısacası @layer utilities bir kuralı o katmana yerleştirir ama Tailwind'e yeni bir utility öğretmez. Varyantlarla çalışacak, yalnızca kullanıldığında üretilecek bir sınıf istiyorsanız @utility yazın.

prefix(tw): sınıf ve değişken adlarına önek eklemek

Tailwind'i, zaten .flex veya .hidden gibi sınıf adları kullanan bir projeye eklediğinizde ad çakışmaları yaşanabilir. Bunun için Tailwind'i içe aktarırken prefix() seçeneği verilir. Önek, sınıf adının başında bir varyant gibi durur: text-red-500 yerine tw:text-red-500, hover durumu için de tw:hover:underline yazılır.

css
@import "tailwindcss" source(none) prefix(tw);
@source inline("tw:text-red-500 tw:hover:underline text-red-500 tw:p-4");

v4.3.5 ile derlenen CSS'in tema ve utility kısımları:

css
@layer theme {
  :root, :host {
    /* (kısaltıldı) */
    --tw-color-red-500: oklch(63.7% 0.237 25.331);
    --tw-spacing: 0.25rem;
    /* (kısaltıldı) */
  }
}
/* (kısaltıldı) */
@layer utilities {
  .tw\:p-4 {
    padding: calc(var(--tw-spacing) * 4);
  }
  .tw\:text-red-500 {
    color: var(--tw-color-red-500);
  }
  @media (hover: hover) {
    .tw\:hover\:underline:hover {
      text-decoration-line: underline;
    }
  }
}

Çıktıdan üç sonuç çıkıyor. Tema değişkenleri de önek aldı: --color-red-500 artık --tw-color-red-500 adıyla tanımlanıyor; kendi CSS'inizde bu değişkenlere başvururken önekli adı kullanmanız gerekir. Varyant, önekten sonra gelir (tw:hover:underline). En önemlisi, öneksiz yazdığımız text-red-500 için hiçbir kural üretilmedi; önek açıldığında öneksiz sınıflar artık Tailwind sınıfı sayılmaz. Belgeler, temayı önek olmadan yapılandırmanızı söyler: @theme içinde --color-avocado-100 yazarsınız, Tailwind çıktıda bunu önekli üretir.

important bayrağı: bütün utility sınıflarını !important yapmak

important bayrağı: bütün utility sınıflarını !important yapmak: prefix, important bayrağı, important modifier, source(none)

Tailwind'i, yüksek özgüllüklü seçicilerle dolu karmaşık bir CSS'e sahip mevcut bir projeye eklerken utility sınıfları sürekli eziliyorsa important bayrağı bir çıkış yoludur. Bu bayrak, üretilen her utility bildirimine !important ekler:

css
@import "tailwindcss" source(none) important;
@source inline("flex gap-4 md:p-8");

v4.3.5 ile derlenen CSS:

css
@layer utilities {
  .flex {
    display: flex !important;
  }
  .gap-4 {
    gap: calc(var(--spacing) * 4) !important;
  }
  @media (width >= 48rem) {
    .md\:p-8 {
      padding: calc(var(--spacing) * 8) !important;
    }
  }
}

Bayrak, responsive varyantlar dahil her kurala uygulanır. Bunun bedeli de vardır: artık utility sınıflarını ezmek için sizin de !important kullanmanız gerekir ve sorunu çözmek yerine bir üst seviyeye taşımış olabilirsiniz. Yeni bir projede bu bayrağa genellikle ihtiyaç yoktur; tek bir sınıfı zorlamak için sınıf sonuna ! eklenen important modifier'ı daha dar kapsamlı bir araçtır.

SeçenekYazımıEtkisiNe zaman
prefix@import "tailwindcss" prefix(tw);Sınıflar tw: ile başlar, değişkenler --tw- ileMevcut sınıf adlarıyla çakışma varsa
important bayrağı@import "tailwindcss" important;Tüm utility bildirimleri !important olurEski, yüksek özgüllüklü CSS ile birlikte çalışırken
important modifierbg-red-500!Sadece o sınıf !important olurTek bir yerde başka yolu kalmadığında
source(none)@import "tailwindcss" source(none);Otomatik dosya taramasını kapatırKaynakları @source ile kendiniz vermek istediğinizde

source(none) seçeneği katmanlarla ilgili değil ama aynı @import satırında yazıldığı için tabloya ekledik; dosya taramasının ayrıntıları Tailwind sınıf tarama ve @source yazısında. Bu seçenekler aynı satırda birlikte de kullanılabilir; bu yazıdaki önek örneğinde source(none) prefix(tw) birlikte derlendi.

Mini senaryo: mevcut bir projeye Tailwind eklemek

Elinizde yıllardır büyümüş bir stil.css dosyası olduğunu ve yeni sayfaları Tailwind ile yazmak istediğinizi düşünelim. Bu yazıdaki bulguları sırayla uyguladığınızda yol şöyle görünür. Önce eski dosyayı Tailwind girişine nasıl bağladığınıza karar verin: dosyayı olduğu gibi katmansız bırakırsanız eski kurallar utility sınıflarını ezer; bu, eski sayfaların bozulmamasını garanti eder ama yeni sayfalarda sürprizlere yol açar. Eski dosyadaki element seçicilerini (h1, a, table) @layer base içine, .panel veya .btn gibi sınıf kurallarını @layer components içine taşırsanız utility sınıfları istediğiniz yerde onları geçebilir.

İkinci adım ad çakışmalarını kontrol etmektir. Eski CSS'te .hidden, .container veya .flex gibi Tailwind ile aynı adı taşıyan sınıflar varsa ve bunlar farklı şeyler yapıyorsa prefix(tw) seçeneği iki dünyayı ayırır. Son çare olarak, eski kurallar çok yüksek özgüllüğe sahipse important bayrağı düşünülebilir. Her adımdan sonra derlenmiş CSS'e bakmak, hangi kuralın hangi katmanda kaldığını görmenin en güvenilir yoludur.

Sık yapılan hatalar

  • Eski CSS'i katmansız bırakmak: Utility sınıfları "çalışmıyor" gibi görünür; aslında katmansız kurallar onları ezer.
  • Bileşen sınıfını katmansız yazmak: .btn kuralı katmansız olursa class="btn px-8" içindeki px-8 uygulanmaz. Bileşenleri @layer components içine koyun.
  • @layer utilities ile utility tanımlamaya çalışmak: Varyantlı kullanımlar üretilmez; @utility yazın.
  • Önek açıkken öneksiz sınıf yazmak: Öneksiz sınıflar için CSS üretilmez ve hata da verilmez; sessizce kaybolur.
  • important bayrağını ilk refleks olarak açmak: Özgüllük sorununu çözmez, yalnızca herkesi !important kullanmaya zorlar.

Sık Sorulan Sorular

Tailwind v4'te @tailwind base, @tailwind components satırları hâlâ gerekli mi?

Hayır. Yükseltme kılavuzuna göre v3'teki üç @tailwind satırının yerini tek bir @import "tailwindcss"; satırı alır; katman bildirimini de bu içe aktarma yapar. v3'ten geçişteki diğer değişiklikler için Tailwind CSS v4 yenilikleri yazısına bakabilirsiniz.

Kendi base kurallarım Preflight'ı ezer mi?

@layer base içine yazdığınız kurallar Preflight ile aynı katmandadır ve derlenmiş çıktıda Preflight'tan sonra gelir. Bu derlemede h1 için yazdığımız boyut, Preflight'ın font-size: inherit kuralından sonra yer aldı; aynı özgüllükte sonra gelen kural kazandığı için sizin değeriniz geçerli olur.

Bir bileşen sınıfını utility ile ezmek için ne yapmalıyım?

Hiçbir şey yapmanıza gerek yok, sınıfı @layer components içinde tanımladıysanız HTML'e eklediğiniz utility sınıfı onu doğal olarak ezer. Örneğin class="card rounded-none" kartın köşelerini kare yapar.

Prefix kullanırken tema değişkenini CSS'te nasıl okurum?

Önekli adla okursunuz. Bu derlemede prefix(tw) açıkken kırmızı renk değişkeni --tw-color-red-500, aralık değişkeni --tw-spacing adını aldı; var(--tw-color-red-500) şeklinde kullanılı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: Tailwind CSS öğrenme rehberi · Çakışan sınıflar ve important · @apply ve bileşen sınıfları · @utility direktifi · Preflight temel stiller · CSS @layer katmanları