Tailwind CSS'te hazır dört animasyon sınıfı vardır: dönen yükleme göstergeleri için animate-spin, bildirim noktası gibi dışa yayılıp kaybolan halkalar için animate-ping, iskelet (skeleton) yükleyiciler için yavaşça soluklaşıp belirginleşen animate-pulse ve aşağı kaydırma işaretleri için zıplayan animate-bounce. Animasyonu kaldırmak için animate-none kullanılır. Kendi animasyonunuz için @theme içinde bir --animate-* değişkeni ve ona ait @keyframes kuralını tanımlarsınız.

Bu yazıda hazır animasyonların derlenen CSS'ini ve keyframe tanımlarını, belgedeki kullanım kalıplarını, özel animasyon eklemeyi, keyframe'lerin hangi koşulda çıktıya girdiğini, hareket azaltma tercihini ve öğe ilk göründüğünde geçiş başlatan starting: varyantını anlatıyoruz. Tüm CSS çıktıları Tailwind CSS v4.3.5 standalone CLI ile derlendi. Durum değişikliğine bağlı tek seferlik geçişler için transition yazısına, serinin geneli için Tailwind öğrenme rehberine bakabilirsiniz.

Hazır animasyonlar ve keyframe'leri

Hazır animasyonlar ve keyframe'leri: animate-spin, animate-ping, animate-pulse, animate-bounce

Her animate-* sınıfı tek bir satır yazar: animation: var(--animate-...). Animasyonun adı, süresi, eğrisi ve tekrar sayısı tema değişkeninde, hareketin kendisi ise ayrı bir @keyframes kuralında durur. v4.3.5 tema dosyasındaki değerler şöyledir:

SınıfTema değeriTipik kullanım
animate-spinspin 1s linear infiniteYükleme göstergesi
animate-pingping 1s cubic-bezier(0, 0, 0.2, 1) infiniteBildirim rozeti
animate-pulsepulse 2s cubic-bezier(0.4, 0, 0.6, 1) infiniteİskelet yükleyici
animate-bouncebounce 1s infiniteAşağı kaydır işareti
animate-noneanimation: noneAnimasyonu kaldırma

Dört animasyonun keyframe tanımları, sınıfları kullanan bir sayfayla yapılan derlemede şu şekilde çıktı:

css
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
@keyframes ping {
  75%, 100% {
    transform: scale(2);
    opacity: 0;
  }
}
@keyframes pulse {
  50% {
    opacity: 0.5;
  }
}
@keyframes bounce {
  0%, 100% {
    transform: translateY(-25%);
    animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
  }
  50% {
    transform: none;
    animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
  }
}

Tanımları okumak her animasyonun ne yaptığını açıkça gösterir. spin yalnızca bitiş karesini (to) verir ve öğeyi 360 derece döndürür; linear eğri ve infinite tekrar sayesinde dönüş sabit hızda sürer. ping karenin yüzde 75'inde öğeyi iki katına büyütür ve opaklığını sıfırlar; son çeyrekte bu durumda bekler. pulse yarı yolda opaklığı 0.5'e indirir. bounce başta ve sonda öğeyi yüksekliğinin yüzde 25'i kadar yukarı kaldırır, ortada yerine indirir ve her iniş ile çıkış için ayrı eğri verir.

Yükleme butonu: animate-spin

Belgedeki tipik kullanım, işlem sürerken devre dışı bırakılan bir butonun içinde dönen bir SVG simgesidir.

html
<button type="button" class="inline-flex items-center bg-indigo-500" disabled>
  <svg class="mr-3 size-5 animate-spin" viewBox="0 0 24 24"></svg>
  İşleniyor
</button>

v4.3.5 ile derlenen CSS (tema ve animasyon kuralı):

css
@layer theme {
  :root, :host {
    /* (kısaltıldı) */
    --animate-spin: spin 1s linear infinite;
  }
}
@layer utilities {
  /* (kısaltıldı) */
  .animate-spin {
    animation: var(--animate-spin);
  }
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

Bu derlemenin çıktısında yalnızca spin keyframe'i bulunur; ping, pulse ve bounce tanımları yoktur. Tailwind yalnızca kullanılan sınıfların CSS'ini ürettiği gibi yalnızca kullanılan animasyonların keyframe'lerini de çıktıya ekler. Simge size-5 ile 16px kökte 20px genişlik ve yüksekliğe sahiptir; boyut sınıfları width, height ve size yazısında anlatılıyor.

Bildirim noktası: animate-ping

animate-ping öğeyi büyütüp soldurduğu için genellikle sabit bir noktanın arkasına, aynı boyutta ikinci bir katman olarak yerleştirilir. Böylece sabit nokta yerinde kalırken arkasından halka yayılır.

html
<span class="relative flex size-3">
  <span class="absolute inline-flex h-full w-full animate-ping rounded-full bg-sky-400 opacity-75"></span>
  <span class="relative inline-flex size-3 rounded-full bg-sky-500"></span>
</span>

v4.3.5 ile derlenen CSS (animasyon ve konum kuralları):

css
@layer utilities {
  /* (kısaltıldı) */
  .absolute {
    position: absolute;
  }
  .relative {
    position: relative;
  }
  .animate-ping {
    animation: var(--animate-ping);
  }
  .opacity-75 {
    opacity: 75%;
  }
}
@keyframes ping {
  75%, 100% {
    transform: scale(2);
    opacity: 0;
  }
}

Dıştaki span relative olduğu için içteki absolute katman onun alanını kaplar. Animasyonlu katman opacity-75 ile başlar ve keyframe boyunca sıfıra iner; önündeki relative nokta ise hareketsiz kalır. Konumlandırma sınıflarının ayrıntıları position yazısında anlatılıyor.

İskelet yükleyici: animate-pulse

İskelet yükleyici: animate-pulse

İçerik yüklenirken gri çubuklarla sayfanın iskeletini göstermek ve bu iskeleti yavaşça soluklaştırıp belirginleştirmek, kullanıcıya bir şeyin geldiğini anlatmanın sık kullanılan yoludur. Animasyon kapsayıcıya verilir; tüm çocuklar birlikte nabız atar.

html
<div class="animate-pulse space-y-3">
  <div class="h-2 rounded bg-gray-200"></div>
  <div class="h-2 w-2/3 rounded bg-gray-200"></div>
</div>

v4.3.5 ile derlenen CSS (animasyon kuralı):

css
@layer utilities {
  /* (kısaltıldı) */
  .animate-pulse {
    animation: var(--animate-pulse);
  }
}
@keyframes pulse {
  50% {
    opacity: 0.5;
  }
}

Opaklık kapsayıcıya uygulandığı için iç öğelerin renkleri ayrı ayrı animasyonlanmaz; tüm iskelet tek parça olarak yarı saydamlığa iner ve geri döner. 2 saniyelik süre, 1 saniyelik dönme ve zıplamaya göre daha yavaş bir ritim verir.

Kaydırma işareti: animate-bounce

html
<svg class="size-6 animate-bounce"></svg>

v4.3.5 ile derlenen CSS (animasyon kuralı):

css
@layer utilities {
  /* (kısaltıldı) */
  .animate-bounce {
    animation: var(--animate-bounce);
  }
}

bounce keyframe'i yukarıda gösterildiği gibi translateY(-25%) kullanır. Yüzde değeri öğenin kendi yüksekliğine göre hesaplandığı için 24px'lik bir simge 6px yukarı çıkar; daha büyük bir öğe orantılı olarak daha fazla zıplar.

Kendi animasyonunuzu tanımlamak

Resmî belgeye göre özel bir animasyon için @theme içinde bir --animate-* değişkeni ve ona karşılık gelen @keyframes kuralı birlikte yazılır. Belgedeki örnek, öğeyi hafifçe sağa sola sallayan bir wiggle animasyonudur.

css
@import "tailwindcss";

@theme {
  --animate-wiggle: wiggle 1s ease-in-out infinite;
  @keyframes wiggle {
    0%,
    100% {
      transform: rotate(-3deg);
    }
    50% {
      transform: rotate(3deg);
    }
  }
}
html
<div class="animate-wiggle"></div>

v4.3.5 ile derlenen CSS (ilgili kısımlar):

css
@layer theme {
  :root, :host {
    /* (kısaltıldı) */
    --animate-wiggle: wiggle 1s ease-in-out infinite;
  }
}
@layer utilities {
  .animate-wiggle {
    animation: var(--animate-wiggle);
  }
}
@keyframes wiggle {
  0%, 100% {
    transform: rotate(-3deg);
  }
  50% {
    transform: rotate(3deg);
  }
}

@theme içindeki keyframe, çıktıda katmanların dışına, kök düzeyine taşınır. Aynı tema bloğunu kullanan ama hiçbir animasyon sınıfı içermeyen bir sayfayla yaptığımız derlemede çıktıda hiç @keyframes kuralı yoktu. Yani temaya onlarca animasyon tanımlasanız da yalnızca kullandıklarınız son CSS dosyasına girer.

Keyfi animasyon değeri

Tema değişkeni tanımlamadan tek bir yerde animasyon kullanmak için köşeli parantez yazımı vardır; boşluklar alt çizgiyle yazılır. Bu durumda keyframe'i sıradan bir CSS kuralı olarak kendiniz eklersiniz.

css
@import "tailwindcss";

@keyframes wiggle {
  0%, 100% { transform: rotate(-3deg); }
  50% { transform: rotate(3deg); }
}
html
<div class="animate-[wiggle_1s_ease-in-out_infinite]"></div>

v4.3.5 ile derlenen CSS:

css
@layer utilities {
  .animate-\[wiggle_1s_ease-in-out_infinite\] {
    animation: wiggle 1s ease-in-out infinite;
  }
}
@keyframes wiggle {
  0%, 100% {
    transform: rotate(-3deg);
  }
  50% {
    transform: rotate(3deg);
  }
}

Bu yol kısa denemeler için pratiktir, ancak aynı animasyon birden fazla yerde geçiyorsa @theme yöntemi daha düzenlidir: sınıf adı okunur kalır ve keyframe yalnızca kullanıldığında çıktıya girer. Bir CSS değişkenini doğrudan kullanmak için animate-(--animasyonum) yazımı da vardır. Köşeli parantez kuralları arbitrary values yazısında anlatılıyor.

Hareket azaltma tercihine saygı

Sürekli dönen ya da zıplayan öğeler, hareketin azaltılmasını isteyen kullanıcılar için rahatsız edici olabilir. Belge iki yaklaşım gösterir: animasyonu yalnızca güvenliyken başlatmak (motion-safe:) ya da azaltma isteyenler için öğeyi gizlemek veya animasyonu kaldırmak (motion-reduce:).

html
<svg class="motion-safe:animate-spin"></svg>
<svg class="animate-spin motion-reduce:hidden"></svg>

v4.3.5 ile derlenen CSS:

css
@layer utilities {
  .animate-spin {
    animation: var(--animate-spin);
  }
  @media (prefers-reduced-motion: no-preference) {
    .motion-safe\:animate-spin {
      animation: var(--animate-spin);
    }
  }
  @media (prefers-reduced-motion: reduce) {
    .motion-reduce\:hidden {
      display: none;
    }
  }
}

İlk simge, kullanıcı hareket azaltma tercihini belirtmediği sürece döner; belirttiğinde hareketsiz kalır. İkinci simge ise azaltma isteyen kullanıcılara hiç gösterilmez; bu, simgenin yanında "İşleniyor" gibi bir metin olduğunda uygundur, çünkü bilgi metinle iletilmeye devam eder. Erişilebilirlik varyantlarının tamamı erişilebilirlik yazısında anlatılıyor.

İlk görünüşte geçiş: starting: varyantı

Bir öğe sayfaya ilk eklendiğinde ya da display: none durumundan görünür hâle geçtiğinde normalde geçiş oynamaz, çünkü tarayıcının başlangıç olarak alacağı bir önceki değer yoktur. Belgeye göre starting: varyantı tam bu an için başlangıç görünümünü tanımlar ve CSS'in @starting-style kuralını üretir. Aşağıdaki örnekte bir popover açıldığında opaklığı sıfırdan bire yumuşakça yükselir.

html
<button popovertarget="bildirim">Güncellemeleri göster</button>
<div popover id="bildirim" class="opacity-0 transition-discrete transition-opacity duration-300 open:opacity-100 starting:open:opacity-0">
  Yeni sürüm hazır.
</div>

v4.3.5 ile derlenen CSS:

css
@layer utilities {
  .opacity-0 {
    opacity: 0%;
  }
  .transition-opacity {
    transition-property: opacity;
    transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
    transition-duration: var(--tw-duration, var(--default-transition-duration));
  }
  .transition-discrete {
    transition-behavior: allow-discrete;
  }
  .duration-300 {
    --tw-duration: 300ms;
    transition-duration: 300ms;
  }
  .open\:opacity-100:is([open], :popover-open, :open) {
    opacity: 100%;
  }
  @starting-style {
    .starting\:open\:opacity-0:is([open], :popover-open, :open) {
      opacity: 0%;
    }
  }
}

Akış şöyledir: popover açıldığında open:opacity-100 devreye girer ve hedef opaklık yüzde 100 olur. @starting-style içindeki starting:open:opacity-0, tarayıcıya ilk karenin opaklığının yüzde 0 olduğunu söyler; transition-opacity duration-300 de aradaki geçişi 300ms içinde oynatır. open: varyantının [open], :popover-open ve :open seçicilerini birlikte kapsadığına dikkat edin; bu sayede aynı sınıf details, dialog ve popover öğelerinde çalışır. transition-discrete sınıfı transition-behavior: allow-discrete yazar; bu ayar, display gibi kesikli değer alan özelliklerin geçiş listesine katılmasına izin verir. Geniş transition sınıfının listesinde display ve overlay bulunduğunu transition yazısında görebilirsiniz.

Animasyonu duruma ve ekrana bağlamak

animate-* sınıfları diğer sınıflar gibi varyant alır. Belgedeki örnekte animate-none md:animate-spin yazımı animasyonu yalnızca orta ve büyük ekranlarda çalıştırır. Benzer şekilde hover:animate-bounce yalnızca fareyle üzerine gelindiğinde zıplatır; v4.3.5 bu kuralı @media (hover: hover) içine yerleştirir. Animasyonu bir varyantla kaldırırken animate-none kullanın; animation: none yazar ve çalışan animasyonu tamamen durdurur.

Hazır bir animasyonun hızını değiştirmek için yeni keyframe yazmanız gerekmez; mevcut keyframe adını kullanan yeni bir tema değişkeni yeterlidir. Aşağıdaki örnekte spin keyframe'ini 3 saniyede bir tur atacak şekilde kullanan bir sınıf tanımlanıyor, ayrıca hareket ve ekran varyantları birleştiriliyor.

css
@theme {
  --animate-spin-yavas: spin 3s linear infinite;
}
html
<div class="animate-spin-yavas motion-safe:md:animate-spin animate-(--animasyonum)"></div>

v4.3.5 ile derlenen CSS:

css
@layer utilities {
  .animate-\(--animasyonum\) {
    animation: var(--animasyonum);
  }
  .animate-spin-yavas {
    animation: var(--animate-spin-yavas);
  }
  @media (prefers-reduced-motion: no-preference) {
    @media (width >= 48rem) {
      .motion-safe\:md\:animate-spin {
        animation: var(--animate-spin);
      }
    }
  }
}

Bu derlemenin çıktısında @keyframes spin kuralı bir kez yer aldı: animate-spin-yavas değeri spin adını kullandığı için CLI hazır keyframe'i de ekledi. motion-safe:md: yazımı iki medya sorgusunu iç içe yerleştirir; animasyon yalnızca kullanıcı hareket azaltma istemediğinde ve ekran genişliği 48rem ve üzerindeyken çalışır. Örnekteki üç sınıf aynı animation özelliğini yazdığı için gerçek bir projede birini seçersiniz; burada üç yazımı birlikte göstermek için yan yana kondu.

Sık yapılan hatalar

Sık yapılan hatalar: Keyframe'i unutmak, Geçiş gereken yerde animasyon kullanmak, Hareket azaltmayı yok saymak, Dönüşüm sınıflarının ezileceğini düşünmek
  • Keyframe'i unutmak: @theme içinde yalnızca --animate-salla: salla 1s infinite yazıp @keyframes salla tanımlamazsanız sınıf CSS üretir (animation: var(--animate-salla)), ama çıktıda hiçbir keyframe bulunmaz ve öğe hareket etmez. Değişken adındaki kök (--animate-salla) sınıf adını, değerin başındaki ad (salla) ise keyframe adını belirler; ikincisi @keyframes adıyla birebir aynı olmalıdır.
  • Geçiş gereken yerde animasyon kullanmak: Hover'da tek seferlik renk ya da boyut değişimi için transition daha uygundur; animate-* sınıfları süresiz tekrar eden ya da kendiliğinden başlayan hareketler içindir.
  • Hareket azaltmayı yok saymak: Süresiz animasyonları motion-safe: ile sınırlamak ya da motion-reduce:animate-none eklemek az kodla erişilebilirliği artırır.
  • Dönüşüm sınıflarının ezileceğini düşünmek: Hazır keyframe'ler transform özelliğini yazar. Yükseltme rehberine göre v4'te rotate-*, scale-* ve translate-* sınıfları ayrı rotate, scale ve translate özelliklerini kullanır; yani bu sınıflar animasyonun yazdığı transform değerini ezmez, onunla aynı anda uygulanır. Dönüşüm sınıfları transform yazısında anlatılıyor.

Sık Sorulan Sorular

Tailwind'de hangi hazır animasyonlar var?

v4.3.5'te dört hazır animasyon vardır: animate-spin, animate-ping, animate-pulse ve animate-bounce. Bunlara ek olarak animasyonu kaldıran animate-none sınıfı bulunur.

animate-spin kaç saniyede bir tur atar?

Tema değeri spin 1s linear infinite olduğu için bir tur 1 saniye sürer ve sabit hızla sonsuza kadar tekrarlanır. Farklı bir hız için kendi değişkeninizi tanımlayın, örneğin --animate-spin-yavas: spin 3s linear infinite.

Özel animasyonun keyframe'i nereye yazılır?

Resmî belgedeki yöntemde @theme bloğunun içine, --animate-* değişkeninin hemen yanına yazılır. Derleme sırasında kök düzeye taşınır ve yalnızca animasyon kullanıldığında çıktıya eklenir.

Animasyonu yalnızca masaüstünde nasıl çalıştırırım?

Animasyonu küçük ekranda kapatıp büyük ekranda açın: animate-none md:animate-spin. Kullanıcının hareket azaltma tercihini de hesaba katmak için motion-safe:md:animate-spin gibi varyantları birleştirebilirsiniz.

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 · Transition ve duration · Transform sınıfları · @theme direktifi · Erişilebilirlik · Sık hatalar