İçeriğe geç
LibraryCSS
@keyframesBaşlangıç3.495 efektte kullanılıyor

@keyframes ile CSS animasyonu

@keyframes, bir animasyonun zaman çizelgesini tanımlayan at-kuralıdır. Elemanın hangi anda hangi stile sahip olacağını yüzdelerle yazarsın; tarayıcı aradaki kareleri kendisi üretir. transition'dan farkı şudur: geçiş yalnızca iki durum arasında ve bir tetikleyiciye bağlı çalışır, anahtar kare animasyonu ise istediğin kadar ara duruma sahiptir ve sayfa yüklenir yüklenmez kendiliğinden başlar.

Katalogdaki yükleyicilerin, kayan arka planların, nabız atan rozetlerin ve yazı makinesi metinlerinin tamamı bu tek at-kuralına dayanır. Bu rehber sözdizimini, animation alt özelliklerini, birden fazla animasyonu tek elemanda birleştirmeyi ve hangi özelliklerin animasyonunun ucuz hangisinin pahalı olduğunu anlatıyor.

Sözdizimi: kareler ve animation kısayolu

Bir animasyon iki parçadan oluşur. Birincisi @keyframes bloğu: animasyona bir ad verir ve kareleri listeler. İkincisi elemana uygulanan animation bildirimi: hangi adın, ne kadar sürede, hangi hızlanma eğrisiyle ve kaç kez oynatılacağını söyler. @keyframes bloğu tek başına hiçbir şey yapmaz; bir eleman onu adıyla çağırana kadar tarayıcı için sadece bir tanımdır.

Kareler from / to anahtar sözcükleriyle ya da yüzdelerle yazılır. from, 0% ile; to, 100% ile aynı şeydir. Yüzde kullanmak birden fazla ara durum gerektiğinde şart olur. Aynı kare için birden fazla yüzdeyi virgülle gruplayabilirsin: 0%, 100% { opacity: 1 } yazmak, animasyonun başında ve sonunda aynı stili tekrar yazmaktan kısadır.

animation-direction
alternate her tekrarda yönü ters çevirir. Gidiş-dönüş animasyonlarında 100% karesini yazmana gerek kalmaz, kare sayısı yarıya iner.
animation-fill-mode
forwards animasyon bitince son karenin stilini korur, backwards gecikme süresince ilk kareyi uygular, both ikisini birden yapar. Varsayılan none olduğu için animasyon biter bitmez eleman eski hâline döner.
animation-play-state
paused animasyonu bulunduğu karede dondurur. :hover ile birleştirilince JavaScript'siz duraklat/devam et elde edilir.
cssNabız atan nokta — en kısa çalışan örnek
@keyframes nabiz {
  0%   { transform: scale(1);    opacity: 1; }
  50%  { transform: scale(1.18); opacity: 0.6; }
  100% { transform: scale(1);    opacity: 1; }
}

.nokta {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #3b82f6;
  animation: nabiz 1.2s ease-in-out infinite;
}
cssKısayolun açılmış hâli — her parça ayrı özellik
.nokta {
  animation-name: nabiz;
  animation-duration: 1.2s;
  animation-timing-function: ease-in-out;
  animation-delay: 0s;
  animation-iteration-count: infinite;
  animation-direction: normal;
  animation-fill-mode: none;
  animation-play-state: running;
}

Adım adım: üç noktalı yükleyici

Klasik üç noktalı yükleyici, tek bir animasyonun üç elemana farklı gecikmelerle uygulanmasından ibarettir. Üç ayrı @keyframes bloğu yazmak yerine aynı kareyi paylaşır, sadece animation-delay değerini kaydırırsın. Sonuç dalga gibi ilerleyen bir hareket olur.

Kritik nokta both doldurma modudur. Onsuz, gecikme süresi boyunca noktalar animasyonun ilk karesine değil kendi statik konumlarına yerleşir; animasyon başladığı anda gözle görülür bir sıçrama olur. both gecikme süresince de ilk kareyi uygular ve sıçramayı kaldırır.

<div class="yukleyici">
  <span></span><span></span><span></span>
</div>
cssTek animasyon, üç gecikme
.yukleyici { display: flex; gap: 8px; }

.yukleyici span {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #60a5fa;
  /* both: gecikme boyunca da ilk kare uygulansın — başlangıç sıçraması olmasın */
  animation: zipla 0.6s ease-in-out infinite alternate both;
}

.yukleyici span:nth-child(2) { animation-delay: 0.15s; }
.yukleyici span:nth-child(3) { animation-delay: 0.30s; }

@keyframes zipla {
  from { transform: translateY(0); }
  to   { transform: translateY(-10px); }
}

Zamanlama fonksiyonları ve steps()

animation-timing-function iki kare arasındaki ara değerlerin nasıl dağıtılacağını belirler. linear sabit hızda ilerler ve dönen yükleyicilerde doğru seçimdir; ease-in-out ise başta ve sonda yavaşlar, doğal hareket taklidi için uygundur. Daha hassas kontrol için cubic-bezier(0.68, -0.55, 0.27, 1.55) gibi değerlerle geri esneyen (overshoot) eğriler yazılabilir — kontrol noktaları 0–1 aralığının dışına çıktığında animasyon hedefi aşıp geri döner.

steps(n) ara değer üretmeyi tamamen kapatır: animasyon n eşit sıçramayla ilerler. Yazı makinesi efekti, kare kare sprite oynatma ve yanıp sönen imleç bu fonksiyonla yazılır. Aşağıdaki örnekte genişlik ch biriminde artar, dolayısıyla her adım tam bir karakter genişliğine denk gelir.

Zamanlama fonksiyonu @keyframes bloğu içinde tek tek karelere de yazılabilir. Bir karede animation-timing-function: linear yazarsan, o kareden sonrakine geçiş o eğriyle yapılır — böylece tek animasyonun farklı bölümleri farklı hızlanma davranışı gösterir.

cssYazı makinesi + yanıp sönen imleç, iki animasyon virgülle
.yazi {
  width: 12ch;              /* metin tam 12 karakter olmalı */
  overflow: hidden;
  white-space: nowrap;
  border-right: 2px solid #60a5fa;
  font-family: monospace;
  animation:
    yaz 2s steps(12) forwards,
    imlec 0.7s steps(1) infinite;
}

@keyframes yaz   { from { width: 0; }             to { width: 12ch; } }
@keyframes imlec { 50%  { border-color: transparent; } }

Performans: hangi özelliği animasyonlamalı

Tarayıcı her karede üç aşamadan geçebilir: layout (geometriyi yeniden hesapla), paint (pikselleri boya), composite (katmanları birleştir). width, height, top, left, margin ve padding animasyonu üçünü birden tetikler ve uzun listelerde kare düşmesine yol açar. transform ve opacity ise yalnızca composite aşamasını çalıştırır; bu iş GPU'da, ana iş parçacığından bağımsız yürür.

Pratik kural: konum için top/left yerine transform: translate(), boyut için width/height yerine transform: scale(), görünürlük için display yerine opacity kullan. Yukarıdaki yükleyici örneğinde noktalar margin-top ile değil translateY ile hareket ettiriliyor; aradaki fark tek elemanda görünmez ama ekranda otuz kart varken belirgindir.

will-change: transform tarayıcıya elemanı önceden ayrı bir katmana almasını söyler. Faydalıdır ama bedava değildir: her katman ayrı bellek tüketir. Sayfadaki her animasyonlu elemana yazmak yerine yalnızca gözle görülür takılma olan yerlere ekle, animasyon bitince kaldır.

Son olarak erişilebilirlik: vestibüler rahatsızlığı olan kullanıcılar için prefers-reduced-motion sorgusunu ekle. Sitedeki tüm efektler bu sorguya saygı duyar; kendi kodunda da tek blokla halledebilirsin.

cssHareket azaltma tercihine saygı
@media (prefers-reduced-motion: reduce) {
  .nokta,
  .yukleyici span {
    animation: none;
  }
}

Katalogdan canlı örnekler

Aşağıdakiler @keyframes kullanan gerçek efektler — anlatılan teknik burada çalışır hâlde. Herhangi birine tıklayıp tam kaynağını açabilir, tarayıcı içi editörde değiştirip sonucu anında görebilirsin.

Tarayıcı desteği

Sürüm numaraları özelliğin öneksiz ve varsayılan olarak açık hâle geldiği ilk kararlı sürümü gösterir.

ÖzellikTarayıcılarNot
@keyframes / animationChrome 43+, Firefox 16+, Safari 9+, Edge 12+Öneksiz sürüm on yılı aşkın süredir her yerde çalışıyor; -webkit- öneki artık gereksiz.
steps(n, jump-start | jump-none)Chrome 77+, Firefox 65+, Safari 14+Eski `steps(n, start | end)` yazımı hâlâ geçerli ve daha geniş desteklidir.
animation-compositionChrome 112+, Firefox 115+, Safari 16+Aynı özelliği hedefleyen animasyonları toplama/çarpma ile birleştirir. Desteklenmeyen tarayıcı bildirimi yok sayar.
prefers-reduced-motionChrome 74+, Firefox 63+, Safari 10.1+İşletim sistemi ayarını okur; ayar kapalıysa sorgu hiç eşleşmez, kodun normal çalışır.

Yaygın hatalar

  • İkinci animation bildirimi ilkini eziyor

    Aynı seçicide iki animation satırı yazarsan ikincisi ilkini tamamen geçersiz kılar — birleşmezler. Birden fazla animasyon tek bildirimde virgülle sıralanır: animation: a 1s infinite, b 2s linear infinite;

  • display: none olan eleman animasyon çalıştırmaz

    Animasyon yalnızca render ağacındaki elemanlarda ilerler. Giriş animasyonu için display: none'dan display: block'a geçmek yerine opacity + visibility ikilisini ya da @starting-style kuralını kullan.

  • fill-mode unutulduğu için eleman geri sıçrıyor

    Varsayılan animation-fill-mode: none olduğundan animasyon bitince eleman son karesini değil kendi statik stilini gösterir. Bitiş durumunun kalması gerekiyorsa forwards şarttır.

  • @keyframes adları global bir isim alanında

    Aynı ada sahip iki @keyframes bloğu varsa, belge sırasında en sonda tanımlanan kazanır — özgüllük kuralları burada işlemez. Efektleri kendi projene taşırken adlara önek ver.

  • Birimsiz sayı animasyonu bozar

    transform: translateY(10) geçersizdir ve o kare bütünüyle atılır, hata da vermez. Uzunluk gerektiren her yerde birim yaz; sıfır için 0 kabul edilir.

Sıkça sorulan sorular

@keyframes ile transition arasındaki fark nedir?
transition iki durum arasında ve mutlaka bir tetikleyiciyle (hover, sınıf değişimi) çalışır; ara durum tanımlayamazsın. @keyframes istediğin kadar ara kareye sahiptir, tetikleyici gerektirmeden sayfa yüklenince başlar ve sonsuz tekrarlanabilir. Basit hover geçişleri için transition, sürekli hareket için @keyframes doğru seçim.
Animasyonu JavaScript olmadan durdurabilir miyim?
Evet. `animation-play-state: paused` animasyonu bulunduğu karede dondurur. `.kart:hover .ikon { animation-play-state: paused; }` yazarak fare üstüne gelince duran bir animasyon elde edersin. Bir onay kutusunun `:checked` durumuyla da aynı şey yapılabilir.
Animasyon neden bittikten sonra ilk hâline dönüyor?
Çünkü varsayılan doldurma modu `none`. Animasyon süresi dolduğunda tarayıcı anahtar kare stillerini bırakır ve elemanın kendi bildirimlerine geri döner. `animation-fill-mode: forwards` yazmak son karenin kalıcı olmasını sağlar.
Kaç animasyonu aynı anda çalıştırabilirim?
Teknik bir sınır yok; tek elemanda virgülle onlarca animasyon tanımlanabilir. Pratik sınır performanstır: yalnızca transform ve opacity animasyonlayan efektler compositor'da çalıştığı için düzinelercesi sorunsuz döner, layout tetikleyen animasyonlarda birkaç tanesi bile kare düşürebilir.
Animasyonu ekrana girince başlatmanın saf CSS yolu var mı?
`animation-timeline: view()` ile kaydırma ilerlemesine bağlı animasyon yazılabilir (Chrome 115+, Safari 26+). Firefox'ta henüz yok, dolayısıyla kritik içerikte IntersectionObserver ile sınıf eklemek hâlâ daha güvenli yöntem.

İlgili rehberler

Son güncelleme:

Tüm rehberler