@apply, Tailwind sınıflarını kendi CSS kuralınızın içine açan bir direktiftir: .btn { @apply px-4 py-2 rounded-lg; } yazdığınızda derleyici bu sınıfların ürettiği bildirimleri .btn kuralına kopyalar. En yaygın kullanım, tekrar eden bir bileşeni @layer components içinde tek sınıfa toplamak ya da kontrol etmediğiniz üçüncü taraf HTML'ini kendi tema değerlerinizle biçimlendirmektir. Vue, Svelte veya CSS modülleri gibi ayrı derlenen stil bloklarında ise @apply'ın çalışması için @reference gerekir.

Bu yazıda @apply'ın ürettiği gerçek CSS'i, varyantların ve ! işaretinin nasıl çevrildiğini, bilinmeyen sınıf hatasının iki farklı mesajını, @reference'ın çıktıyı nasıl etkilediğini ve @apply'ın ne zaman doğru, ne zaman gereksiz bir araç olduğunu v4.3.5 ile derleyerek anlatıyoruz. Seriye genel bakış için Tailwind öğrenme rehberine bakabilirsiniz; hazır bileşen kalıpları kart, buton ve input örnekleri yazısında.

@apply ne üretir?

@apply ne üretir?

Bir buton sınıfını bileşen katmanında tanımlayıp HTML'de btn ile birlikte rounded-none kullandığımız şu dosyayı derledik:

css
@import "tailwindcss" source(none);
@source inline("btn rounded-none");
@layer components {
  .btn {
    @apply rounded-lg bg-sky-600 px-4 py-2 font-semibold text-white hover:bg-sky-700 focus-visible:outline-2;
  }
}

v4.3.5 ile derlenen CSS:

css
@layer theme, base, components, utilities;
/* (kısaltıldı: @layer theme ve @layer base) */
@layer utilities {
  .rounded-none {
    border-radius: 0;
  }
}
@layer components {
  .btn {
    border-radius: var(--radius-lg);
    background-color: var(--color-sky-600);
    padding-inline: calc(var(--spacing) * 4);
    padding-block: calc(var(--spacing) * 2);
    --tw-font-weight: var(--font-weight-semibold);
    font-weight: var(--font-weight-semibold);
    color: var(--color-white);
    &:hover {
      @media (hover: hover) {
        background-color: var(--color-sky-700);
      }
    }
    &:focus-visible {
      outline-style: var(--tw-outline-style);
      outline-width: 2px;
    }
  }
}
/* (kısaltıldı: @property ve @layer properties) */

Çıktıda dikkat edilecek dört nokta var. Birincisi, her sınıf kendi bildirimlerini getiriyor ve değerler tema değişkenlerinden okunuyor; --radius-lg varsayılan temada 0.5rem, --color-sky-600 ise oklch(58.8% 0.158 241.966). İkincisi, varyantlar kaybolmuyor: hover:bg-sky-700 iç içe bir &:hover bloğuna ve onun içinde @media (hover: hover) sorgusuna, focus-visible:outline-2 ise &:focus-visible bloğuna dönüşüyor. Üçüncüsü, sınıfların sırası tek tek kopyalanıyor ama bu, HTML'de yazdığınız sıradan değil derleyicinin kendi düzeninden geliyor. Dördüncüsü, .btn kuralı components katmanında, rounded-none ise utilities katmanında yer alıyor.

Son nokta önemlidir. Dosyanın ilk satırındaki @layer theme, base, components, utilities; bildirimi katman önceliğini belirler; belgedeki ifadeyle bileşen katmanı, utility sınıflarının üzerine yazabildiği sınıflar içindir. Böylece class="btn rounded-none" yazdığınızda köşeler sıfırlanır, butonun geri kalanı aynı kalır. Çıktıda utilities bloğunun fiziksel olarak önce yazılmış olması bu sonucu değiştirmez, çünkü belirleyici olan bildirilen katman sırasıdır. Katman mantığının ayrıntısı katmanlar ve özel CSS yazısında, saf CSS tarafı CSS @layer yazısında.

Varyant ve important ile @apply

Responsive varyantlar ve ! işareti de @apply içinde çalışır. Bu kez kuralı herhangi bir katmana koymadan yazdık:

css
@import "tailwindcss" source(none);
.uyari {
  @apply bg-red-500! md:p-6;
}
css
@layer utilities;
.uyari {
  background-color: var(--color-red-500) !important;
  @media (width >= 48rem) {
    padding: calc(var(--spacing) * 6);
  }
}

v4.3.5 çıktısında bg-red-500! bildirimi !important ile, md:p-6 ise iç içe bir @media (width >= 48rem) bloğu olarak geldi. v4'te ! işareti sınıf adının sonuna yazılır; başa yazılan eski biçim uyumluluk için hâlâ kabul edilir, ama yükseltme rehberi onu kullanımdan kalkmış sayar. !important'ın çakışmaları nasıl etkilediği çakışan sınıflar ve important yazısında. Katmansız yazılan .uyari kuralının çıktıda @layer dışında kaldığına da dikkat edin; bu kural bileşen katmanındaki bir kuraldan farklı bir öncelikle davranır.

Bilinmeyen sınıf hatası ve iki farklı mesajı

@apply yalnızca derleyicinin tanıdığı sınıfları kabul eder ve tanımadığında derlemeyi durdurur. Bu, HTML'deki yanlış bir sınıf adından çok daha güvenli bir davranıştır, çünkü HTML'de yanlış yazılmış sınıf hiçbir uyarı vermeden sessizce yok sayılır. Varsayılan temada olmayan bir rengi uyguladığımızda CLI şu mesajla çıktı:

css
@import "tailwindcss" source(none);
.kart {
  @apply bg-yok-500 p-4;
}
bash
Error: Cannot apply unknown utility class `bg-yok-500`

Aynı hata, temayı hiç görmeyen bir dosyada daha uzun bir ipucuyla gelir. @import satırı olmayan, yalnızca .kart { @apply bg-marka p-4; } içeren bir dosyayı ayrı derlediğimizde mesaj şuydu:

bash
Error: Cannot apply unknown utility class `bg-marka`. Are you using CSS modules or similar and missing `@reference`? https://tailwindcss.com/docs/functions-and-directives#reference-directive

İlk durumda sınıf gerçekten yok: ya ad yanlış yazılmıştır ya da renk temada tanımlı değildir. İkinci durumda sınıf ana stil dosyanızda var olabilir, ama bu dosya ona erişemiyor; çözüm aşağıdaki @reference direktifidir.

Bileşen sınıfını @apply ile kullanmak

Sık karşılaşılan bir sürpriz de @layer components içinde tanımladığınız bir sınıfı başka bir kuralda @apply ile kullanmaya çalışmaktır. .btn sınıfını bileşen katmanında tanımlayıp .btn-buyuk { @apply btn text-lg; } yazdığımızda derleme Error: Cannot apply unknown utility class `btn` mesajıyla durdu. @apply, sıradan CSS sınıflarını değil Tailwind'in utility kayıtlarını tanır. Aynı adı @utility dugme { ... } ile kaydettiğimizde ise sorun kalmadı:

css
@import "tailwindcss" source(none);
@utility dugme {
  padding: 1rem;
  border-radius: 0.5rem;
}
.dugme-buyuk {
  @apply dugme text-lg;
}
css
.dugme-buyuk {
  padding: 1rem;
  border-radius: 0.5rem;
  font-size: var(--text-lg);
  line-height: var(--tw-leading, var(--text-lg--line-height));
}

text-lg sınıfının yazı boyutuyla birlikte satır yüksekliğini de getirdiğini görüyorsunuz; --text-lg--line-height değeri temada calc(1.75 / 1.125). Kendi utility sınıflarınızı yazmanın tüm ayrıntıları @utility direktifi yazısında.

@reference: Vue, Svelte ve CSS modüllerinde @apply

Ana CSS dosyanızdan ayrı paketlenen stil blokları (Vue ya da Svelte bileşenlerindeki <style> blokları, CSS modülleri) temanıza, özel utility sınıflarınıza ve özel varyantlarınıza varsayılan olarak erişemez. @reference, ana stil dosyanızı yalnızca bağlam için içe aktarır, onun CSS'ini çıktıya tekrar yazmaz. Belgedeki Vue örneğinin yapısı şöyledir:

html
<template>
  <h1>Merhaba dünya!</h1>
</template>

<style>
  @reference "../../app.css";

  h1 {
    @apply text-2xl font-bold text-red-500;
  }
</style>

Bu yazıda bir Vue projesi kurmadık; aynı mekanizmayı CLI ile iki düz CSS dosyasında denedik. app.css içinde @import "tailwindcss" source(none); ve @theme { --color-marka: #5b21b6; } vardı. Alt klasördeki kart.css şöyleydi:

css
@reference "../app.css";
.kart {
  @apply bg-marka p-4 rounded-xl;
}

kart.css dosyasını tek başına derlediğimizde çıktının tamamı şuydu:

css
/*! tailwindcss v4.3.5 | MIT License | https://tailwindcss.com */
.kart {
  border-radius: var(--radius-xl, 0.75rem);
  background-color: var(--color-marka, #5b21b6);
  padding: calc(var(--spacing, 0.25rem) * 4);
}

Çıktıda preflight, tema katmanı ya da başka bir utility yok; yalnızca .kart kuralı var. Değişkenlerin yanına yedek değer eklendiğine dikkat edin: var(--color-marka, #5b21b6). Bu sayede bileşen stili, ana dosyadaki değişkenler sayfada tanımlıysa onları kullanır, değilse temadaki değere düşer. Hiç özelleştirme yapmıyorsanız (özel @theme, @custom-variant ya da @plugin yoksa) belge doğrudan @reference "tailwindcss"; yazmanıza izin verir. Bunu da denedik: h1 { @apply text-2xl font-bold text-red-500; } kuralı font-size: var(--text-2xl, 1.5rem) ve color: var(--color-red-500, oklch(63.7% 0.237 25.331)) gibi yedekli bildirimlerle derlendi.

@apply ne zaman kullanılmalı?

@apply ne zaman kullanılmalı? Üçüncü taraf HTML, Şablonu kontrol edemediğiniz içerik, Bileşen başına stil bloğu, Utility'nin kendisi olarak

Belge, bileşen katmanına ve @apply'a beklediğinizden daha az ihtiyaç duyacağınızı vurgular. Tekrar eden bir buton için çoğu projede en temiz çözüm, HTML'i bir şablon parçasına ya da framework bileşenine taşıyıp sınıfları orada bir kez yazmaktır. @apply'ın gerçekten öne çıktığı durumlar şunlardır:

  • Üçüncü taraf HTML: belgedeki örnek, bir seçim kutusu kütüphanesinin .select2-dropdown gibi sınıflarını @apply rounded-b-lg shadow-md; ile kendi tema değerlerinize bağlamaktır.
  • Şablonu kontrol edemediğiniz içerik: CMS ya da Markdown çıktısı gibi; ancak burada tema değişkenlerini var() ile kullanmak da aynı işi görür (@theme yazısı).
  • Bileşen başına stil bloğu: Vue veya Svelte bileşenlerinde, @reference ile birlikte.
  • Utility'nin kendisi olarak: yeni ve tekrar kullanılabilir bir sınıf gerekiyorsa @apply yerine @utility tercih edin; böylece varyantlarla otomatik çalışır.

Örnek: üçüncü taraf bileşeni temaya bağlamak

Belgedeki seçim kutusu örneğini derleyip çıktıya baktık. HTML'ine sınıf ekleyemediğiniz bir kütüphanenin sınıflarını kendi CSS'inizde yakalayıp tema değerlerinizi uyguluyorsunuz:

css
@import "tailwindcss" source(none);
.select2-dropdown {
  @apply rounded-b-lg shadow-md;
}
.select2-search {
  @apply rounded border border-gray-300;
}
css
.select2-dropdown {
  border-bottom-right-radius: var(--radius-lg);
  border-bottom-left-radius: var(--radius-lg);
  --tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.select2-search {
  border-radius: 0.25rem;
  border-style: var(--tw-border-style);
  border-width: 1px;
  border-color: var(--color-gray-300);
}
/* (kısaltıldı: @layer theme, @property ve @layer properties) */

v4.3.5 çıktısında tek bir rounded-b-lg iki ayrı köşe bildirimine, shadow-md ise gölge değişkeni ve uzun bir box-shadow zincirine dönüştü. Zincir, halka (ring) ve iç gölge değişkenlerini de taşıyor; bu yapının nedeni ve ring sınıflarıyla ilişkisi shadow ve ring yazısında. Ek bilgi olarak, çıplak rounded sınıfı burada değişken yerine doğrudan 0.25rem yazdı. Bu kurallar herhangi bir katmana konmadığı için katman dışında kaldı; kütüphanenin kendi stillerini ezmeniz gerekiyorsa bu genellikle istenen sonuçtur, ama utility sınıflarıyla ezilebilir olmasını istiyorsanız kuralları @layer components içine alın.

Yükseltme rehberi ayrıca, ayrı stil bloklarında @apply yerine tema değişkenlerini doğrudan kullanmanın da bir seçenek olduğunu belirtir. Örneğin color: var(--color-red-500); yazmak hem kısa hem de derleme bağımlılığı olmayan bir yoldur.

YöntemNereye yazılırVaryantlarla (hover:, md:) kullanılabilir miUtility ile ezilebilir mi
Doğrudan HTML sınıflarıHTMLEvetKendisi utility
@layer components + @applyCSSHayır, sınıf adı varyant almazEvet, katman sırası sayesinde
@utilityCSSEvet, otomatikÖzellik sayısına göre sıralanır
var(--tema-degiskeni)CSSKendi seçicinizleBulunduğu katmana bağlı

Tablodaki "varyant almaz" ifadesi şunu anlatır: @layer components içindeki .btn sıradan bir CSS sınıfıdır, md:btn yazdığınızda Tailwind bunu bir utility olarak tanımaz. @utility btn ile kaydedilen sınıf ise md:btn ve hover:btn biçimlerinde de üretilir. Bunu denedik: bileşen katmanında .btn, @utility ile dugme tanımlayıp md:btn md:dugme hover:dugme kullandığımızda çıktıda .md\:dugme ve .hover\:dugme:hover kuralları vardı, md:btn için ise hiçbir kural yoktu. Yalnızca düz .btn kuralı her zamanki gibi bileşen katmanında yazılmıştı; çünkü o, kaynakta kullanılıp kullanılmadığına bakılmadan çıktıya giren sıradan bir CSS kuralıdır.

Sık yapılan hatalar

  • Bileşen sınıfını @apply etmek: @layer components içindeki sınıf @apply ile kullanılamaz; @utility ile kaydedin.
  • Ayrı stil bloğunda @reference unutmak: hata mesajındaki "missing @reference" ipucu bunu gösterir.
  • @reference yerine @import kullanmak: @import ana dosyanın tüm CSS'ini o bloğa da kopyalar; belge @reference'ı tam olarak bu tekrarı önlemek için önerir.
  • Her şeyi @apply ile soyutlamak: HTML'de tek satırda okunabilen bir tasarımı CSS dosyasına taşıyıp yeni adlar uydurmak, utility yaklaşımının avantajını azaltır; utility class mantığı yazısına bakın.
  • Eski ! yazımı: !bg-red-500 yerine bg-red-500! yazın.

Sık Sorulan Sorular

@apply içinde hover: ve md: kullanabilir miyim?

Evet. Derleyici bunları iç içe &:hover ve @media bloklarına çevirir; yukarıdaki .btn ve .uyari çıktıları bunu gösteriyor. Kendi CSS'inizde bir varyantı sınıf olmadan uygulamak isterseniz @variant direktifi vardır; özel varyantlar yazısında.

@apply içinde dark: çalışır mı?

Çalışır. .panel { @apply bg-white dark:bg-gray-900; } kuralı, beyaz arka planı ve onun altında @media (prefers-color-scheme: dark) bloğu içinde var(--color-gray-900) değerini üretti. Koyu temayı bir sınıf ya da öznitelikle yönetiyorsanız dark varyantını yeniden tanımlarsınız ve @apply bu tanımı kullanır; kurulum dark mode yazısında.

@apply kullanırsam çıktı büyür mü?

@apply her kullanıldığı kurala bildirimleri kopyalar. Aynı sınıf listesini on farklı kurala uygularsanız bildirimler on kez yazılır; HTML'de aynı sınıfları kullanmak ise tek bir utility kuralını paylaşır.

@apply ile özel bir renk kullanabilir miyim?

Rengi önce @theme içinde --color-* ad alanına eklemeniz gerekir; aksi hâlde bilinmeyen sınıf hatası alırsınız. Tek seferlik bir değer için bg-[#5b21b6] gibi bir keyfi değer de uygulanabilir.

@apply içeren kuralı hangi katmana yazmalıyım?

Kuralın utility sınıflarıyla ezilebilmesini istiyorsanız @layer components içine yazın; ilk örnekteki btn rounded-none birleşimi bu sayede çalıştı. Sayfa genelindeki öğe varsayılanları (başlıklar, bağlantılar) için @layer base uygundur; belge buna h1 { font-size: var(--text-2xl); } gibi bir örnek verir. Hiçbir katmana koymadığınız kurallar ise .uyari ve .select2-dropdown çıktılarında gördüğünüz gibi katman dışında kalır. Preflight'ın temel katmanda neleri sıfırladığını preflight yazısında bulabilirsiniz.

Vue projemde @reference yolu ne olmalı?

Ana CSS dosyanıza bileşen dosyasından göreli yol verirsiniz ("../../app.css" gibi). Bu yazıda yalnızca CLI ile düz CSS dosyalarında denendi; framework ayarlarınız için Vite kurulumu yazısına bakın.

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 öğrenme rehberi · @utility direktifi · Katmanlar · Kart, buton, input örnekleri · @theme direktifi · Tailwind sıfırdan rehber