---
title: Geçişler
source: 'https://academia.sh/tr/kurslar/duzen-ve-duyarli-tasarim/gecisler'
course: 'Düzen Sistemleri ve Duyarlı Tasarım'
language: tr
updated: '2026-08-17T18:09:28+00:00'
license: 'CC BY-SA 4.0'
---

# Geçişler

İki durum arasındaki değişimin zamana yayılması; geçebilen ve geçemeyen değerler, kübik Bézier zamanlama eğrisinin hesabı, kesilen geçişin davranışı ve kesikli zamanlama.

Bir önceki ders kartın vurgulu durumunu tanımladı: sekiz birim yukarıda, yüzde dört büyük.
Bildirim iki durumu da veriyor ama aralarında bir **yol** yok. İşaretçi kartın üzerine
geldiği anda kart yeni yerindedir.

Hareket, iki durum arasındaki yolun zamana yayılmasıdır. Bu ders o yolu tanımlayan
bildirimleri ele alır: hangi özellik ne kadar sürede, hangi hız eğrisiyle eski değerinden
yenisine gider ve yol yarıda kesilirse ne olur?

## Geçiş İki Değer Arasını Doldurur

**Geçiş (transition)**, bir özelliğin hesaplanmış değeri değiştiğinde eski değerden yenisine
zaman içinde ilerlemesini sağlar. Değişimi geçiş başlatmaz; geçiş yalnız zaten olacak bir
değişimi yayar.

Bir uyarı gerekir: CSS ile Görsel Sunum kursunda "geçiş" sözcüğü renkler arasındaki
hesaplanmış görsel için kullanılmıştı. Bu kursta o anlam **renk geçişi** olarak anılır;
tek başına "geçiş", bu dersteki zaman içinde değişim anlamındadır.

Geçişin dört ayrı bildirimi vardır:

| Bildirim | Yanıtladığı soru |
|---|---|
| `transition-property` | Hangi özellikler yayılacak |
| `transition-duration` | Yol ne kadar sürecek |
| `transition-timing-function` | Yol boyunca hız nasıl dağılacak |
| `transition-delay` | Değişimden ne kadar sonra başlayacak |

Kısayol `transition`, bu dördünü tek satırda alır ve virgülle ayrılmış listeler her özellik
için ayrı değer yazmayı sağlar. Süre yazılmazsa varsayılan sıfırdır; süresiz bir geçiş
bildirimi hiçbir şey yapmaz.

`transition-delay` eksi değer de alabilir. Eksi gecikme, geçişi başlangıcından değil
**ortasından** başlatır: 240 milisaniyelik bir geçişe $-60$ milisaniye gecikme yazmak,
geçişi yüzde 25 ilerlemiş durumda açar.

## Geçebilen ve Geçemeyen Değerler

Geçiş, iki değer arasında ara değer üretebilmeyi gerektirir. Uzunluk, sayı, renk ve dönüşüm
listesi için bu tanımlıdır. Anahtar sözcükler için tanımlı değildir.

Bunun sonuçları vardır. `height: auto` değerinden sabit bir yüksekliğe geçiş çalışmaz, çünkü
`auto` bir sayı değildir. `display: none` ile görünür durum arasında ara değer yoktur;
görüntüleme türü **kesikli (discrete)** bir özelliktir ve kesikli özellikler geçişin
ortasında değil sonunda ya da başında değişir.

Bir açılır bölümün yüksekliğinin yayılması isteniyorsa üç yol vardır: sabit bir üst sınır
üzerinden geçmek, ızgara şeridinin pay değerini geçirmek ya da yüksekliği hiç oynatmadan
dönüşüm ve saydamlıkla çalışmak. Üçüncüsü, sonraki derslerin göstereceği nedenle en
ucuzudur.

`visibility` özelliği bir istisnadır: kesikli olduğu hâlde geçiş süresince eski değerini
korur, bu yüzden `opacity` ile birlikte yazıldığında ögenin sönerken tıklanabilir kalmasını
önler.

## Zamanlama Eğrisi

**Zamanlama fonksiyonu (timing function)**, geçen sürenin oranını ilerleme oranına çevirir.
Girdi $0$ ile $1$ arasında zaman, çıktı $0$ ile $1$ arasında ilerlemedir.

Adlı fonksiyonların tamamı, $(0,0)$ ve $(1,1)$ uçlarını iki denetim noktasıyla birleştiren
**kübik Bézier** eğrisidir. `cubic-bezier(x1, y1, x2, y2)` yazımı bu iki noktayı verir.

Eğrinin değerlendirilmesi tek adımda yapılamaz: eğri $t$ parametresine göre tanımlıdır,
oysa elimizdeki zaman $x$ eksenindedir. Önce $x$ değerini veren $t$ bulunur, sonra o $t$
için $y$ okunur.

```js
// gecis.mjs — kubik Bezier zamanlama egrisinin degerlendirilmesi ve ara deger hesabi
// Zamanlama egrisi (0,0) ile (1,1) arasinda, denetim noktalari (x1,y1) ve (x2,y2).
const bez = (a, b, t) => {
  const u = 1 - t;
  return 3 * u * u * t * a + 3 * u * t * t * b + t * t * t;   // p0=0, p3=1
};

// Verilen x icin egri parametresi t ikili aramayla bulunur, sonra y okunur.
function egri(x1, y1, x2, y2) {
  return (x) => {
    if (x <= 0) return 0;
    if (x >= 1) return 1;
    let alt = 0, ust = 1, t = x;
    for (let i = 0; i < 60; i++) {
      t = (alt + ust) / 2;
      if (bez(x1, x2, t) < x) alt = t; else ust = t;
    }
    return bez(y1, y2, t);
  };
}

const ADLI = {
  linear: [0, 0, 1, 1],
  ease: [0.25, 0.1, 0.25, 1],
  "ease-in": [0.42, 0, 1, 1],
  "ease-out": [0, 0, 0.58, 1],
  "ease-in-out": [0.42, 0, 0.58, 1],
};

console.log("--- adli zamanlama fonksiyonlarinin ilerleme degerleri ---");
console.log("gecen sure".padEnd(12) + Object.keys(ADLI).map((k) => k.padStart(12)).join(""));
for (let i = 0; i <= 10; i++) {
  const x = i / 10;
  const satir = Object.values(ADLI).map((c) => egri(...c)(x).toFixed(4).padStart(12)).join("");
  console.log(`%${(x * 100).toFixed(0)}`.padEnd(12) + satir);
}

console.log("\n--- ayni ilerlemenin iki ozellige uygulanmasi (240 ms, ease-out) ---");
const f = egri(...ADLI["ease-out"]);
const SURE = 240;
const ara = (bas, son, p) => bas + (son - bas) * p;
console.log("ms".padStart(5), "ilerleme".padStart(10), "translateY".padStart(12), "scale".padStart(10));
for (const ms of [0, 30, 60, 90, 120, 180, 240]) {
  const p = f(ms / SURE);
  console.log(
    String(ms).padStart(5),
    p.toFixed(4).padStart(10),
    (ara(0, -8, p).toFixed(2) + "px").padStart(12),
    ara(1, 1.04, p).toFixed(4).padStart(10),
  );
}

console.log("\n--- gecisin ortasinda kesilmesi ---");
const KESME = 72;                     // ms; isaretci 72. ms'de karttan cikiyor
const durum = ara(0, -8, f(KESME / SURE));
console.log(`kesme aninda translateY = ${durum.toFixed(2)}px`);
console.log("geri donus, ayni sure ve ayni egriyle bu degerden 0'a gider:");
for (const ms of [0, 30, 60, 90, 120, 180, 240]) {
  const p = f(ms / SURE);
  console.log(`  ${String(ms).padStart(3)} ms -> ${ara(durum, 0, p).toFixed(2)}px`);
}

console.log("\n--- steps() ile kesikli ilerleme, 4 adim ---");
const basamak = (n, kip) => (x) => {
  if (x <= 0) return kip === "start" ? 1 / n : 0;
  if (x >= 1) return 1;
  const k = Math.floor(x * n);
  return (kip === "start" ? k + 1 : k) / n;
};
const bStart = basamak(4, "start");
const bEnd = basamak(4, "end");
console.log("gecen sure".padEnd(12) + "steps(4, start)".padStart(16) + "steps(4, end)".padStart(16));
for (let i = 0; i <= 10; i++) {
  const x = i / 10;
  console.log(
    `%${(x * 100).toFixed(0)}`.padEnd(12) +
    bStart(x).toFixed(2).padStart(16) +
    bEnd(x).toFixed(2).padStart(16),
  );
}
```

```
--- adli zamanlama fonksiyonlarinin ilerleme degerleri ---
gecen sure        linear        ease     ease-in    ease-out ease-in-out
%0                0.0000      0.0000      0.0000      0.0000      0.0000
%10               0.1000      0.0948      0.0170      0.1606      0.0197
%20               0.2000      0.2952      0.0623      0.3084      0.0817
%30               0.3000      0.5133      0.1296      0.4452      0.1874
%40               0.4000      0.6825      0.2149      0.5709      0.3319
%50               0.5000      0.8024      0.3154      0.6846      0.5000
%60               0.6000      0.8852      0.4291      0.7851      0.6681
%70               0.7000      0.9408      0.5548      0.8704      0.8126
%80               0.8000      0.9756      0.6916      0.9377      0.9183
%90               0.9000      0.9943      0.8394      0.9830      0.9803
%100              1.0000      1.0000      1.0000      1.0000      1.0000

--- ayni ilerlemenin iki ozellige uygulanmasi (240 ms, ease-out) ---
   ms   ilerleme   translateY      scale
    0     0.0000       0.00px     1.0000
   30     0.1986      -1.59px     1.0079
   60     0.3781      -3.03px     1.0151
   90     0.5405      -4.32px     1.0216
  120     0.6846      -5.48px     1.0274
  180     0.9065      -7.25px     1.0363
  240     1.0000      -8.00px     1.0400

--- gecisin ortasinda kesilmesi ---
kesme aninda translateY = -3.56px
geri donus, ayni sure ve ayni egriyle bu degerden 0'a gider:
    0 ms -> -3.56px
   30 ms -> -2.85px
   60 ms -> -2.21px
   90 ms -> -1.64px
  120 ms -> -1.12px
  180 ms -> -0.33px
  240 ms -> 0.00px

--- steps() ile kesikli ilerleme, 4 adim ---
gecen sure   steps(4, start)   steps(4, end)
%0                      0.25            0.00
%10                     0.25            0.00
%20                     0.25            0.00
%30                     0.50            0.25
%40                     0.50            0.25
%50                     0.75            0.50
%60                     0.75            0.50
%70                     0.75            0.50
%80                     1.00            0.75
%90                     1.00            0.75
%100                    1.00            1.00
```

İlk tablo beş eğriyi aynı zaman noktalarında karşılaştırıyor. `linear` dışındaki hepsi
zamanın yarısında yolun yarısında değil.

`ease` yolun yarısını sürenin yaklaşık yüzde 30'unda tamamlar; hızlı başlar, uzun bir
yavaşlama kuyruğu bırakır. `ease-in` yavaş başlar, sona doğru hızlanır — sürenin yarısında
yolun ancak üçte biri alınmıştır. `ease-out` bunun tersidir. `ease-in-out` simetriktir ve
tam ortada yolun tam yarısındadır.

Seçim keyfî değildir. Bir öge ekrana **giriyorsa** yavaşlayarak durması beklenir
(`ease-out`); ekrandan **çıkıyorsa** hızlanarak gitmesi beklenir (`ease-in`). Yerinde kalıp
biçim değiştiren bir ögede simetrik eğri kullanılır.

## Ara Değerin Hesabı

Çıktının ikinci bloğu, tek bir ilerleme değerinin iki ayrı özelliğe nasıl uygulandığını
gösteriyor. 240 milisaniyelik geçişin 60. milisaniyesinde ilerleme $0{,}3781$; öteleme bu
oranda $-3{,}03$ birim, ölçek çarpanı $1{,}0151$.

Formül her özellik için aynıdır:

$$
\text{değer}(t) = \text{başlangıç} + (\text{bitiş} - \text{başlangıç}) \times \text{ilerleme}(t)
$$

Dönüşüm listelerinde bu hesap fonksiyon fonksiyon yapılır — iki listede aynı fonksiyonlar
aynı sırada varsa her fonksiyonun kendi sayıları ara değerlenir. Listeler uyuşmuyorsa
tarayıcı ikisini de matrise indirger ve matrisleri ara değerler; sonuç genellikle beklenen
yol değildir. Geçişe girecek iki dönüşüm listesinin **aynı fonksiyonları aynı sırada**
taşıması bu yüzden bir yazım kuralıdır.

## Kesilme ve Geri Dönüş

Çıktının üçüncü bloğu, işaretçinin 72. milisaniyede karttan çıktığı durumu hesaplıyor. O
anda öteleme $-3{,}56$ birimdir ve geri dönüş bu değerden başlar, $-8$ biriminden değil.

Kural şudur: bir geçiş kesildiğinde yeni geçiş, özelliğin **o andaki hesaplanmış
değerinden** başlar. Bu, hareketin sıçramamasını sağlar.

Ama bir yan etki bırakır: geri dönüş de tam süreyi kullanır. Kart 72 milisaniye yükselip
240 milisaniye boyunca iner. Kısa bir dokunuş, uzun bir geri dönüşle yanıtlanır ve hareket
gecikmeli hissettirir. Bunun önüne geçmek için giriş ve çıkış süreleri ayrı yazılır: çıkış
süresi girişten kısa tutulur.

Bir geçiş bildirimi, ögenin **temel durumuna** yazıldığında hem gidiş hem dönüş için
geçerlidir; yalnız `:hover` kuralına yazıldığında yalnız gidiş yayılır, dönüş anlık olur.

## Kesikli Zamanlama

`steps(n, kip)` fonksiyonu ilerlemeyi sürekli değil **basamaklı** üretir. Çıktının son
bloğu dört adımlık iki kipi karşılaştırıyor.

`end` kipi sıfırdan başlar ve son basamağı sonda atar; `start` kipi ilk basamağı hemen
atar ve sıfır değerini hiç göstermez. Dört adımda ilerleme yalnız $0$, $0{,}25$, $0{,}5$,
$0{,}75$, $1$ değerlerini alır; aradaki her şey atlanır.

Bu, kare kare ilerleyen bir gösterge ya da sayaç için kullanılır. Süreklilik istenmeyen
yerlerde kesikli zamanlama, hareketi daha az dikkat dağıtıcı yapar.

## İstasyon Sayfasında Geçiş

```css
/* hareket.css — 2. adım: kart vurgusunun zamana yayılması */
.olcum-kartlari > .kart {
  transform-origin: center bottom;
  transition:
    transform 240ms ease-out,
    box-shadow 240ms ease-out;
}

.olcum-kartlari > .kart:hover,
.olcum-kartlari > .kart:focus-within {
  transform: translateY(-8px) scale(1.04);
  transition-duration: 160ms;
}
```

Geçiş bildirimi temel duruma yazıldı; dönüş de yayılıyor. Vurgulu durumda süre 160
milisaniyeye çekildi: giriş kısa, dönüş biraz uzun. Sıralama böylece hem tepkili hem
yumuşak olur.

Listede `transform` ve `box-shadow` tek tek sayıldı. `transition-property: all` yazmak daha
az yazıdır ama her hesaplanmış değer değişimini geçişe sokar; sonradan eklenen bir renk ya
da ölçü bildirimi istemeden yayılmaya başlar. Özellikleri saymak bu sürprizi önler.

## Özet

- Geçiş bir değişimi başlatmaz; hesaplanmış değeri zaten değişen bir özelliğin eski
  değerinden yenisine ilerlemesini zamana yayar.
- Ara değer üretilemeyen değerler geçemez: `auto`, `display` gibi kesikli özellikler ve
  anahtar sözcükler yol değil sıçrama üretir.
- Zamanlama fonksiyonu geçen sürenin oranını ilerleme oranına çevirir; adlı fonksiyonlar
  kübik Bézier eğrileridir ve `linear` dışında zamanın yarısı yolun yarısı değildir.
- Kesilen bir geçiş, özelliğin o andaki hesaplanmış değerinden yeniden başlar ve tam
  süresini kullanır; giriş ile çıkış süreleri ayrı yazılarak dengelenir.
- `steps(n, kip)` ilerlemeyi basamaklı üretir; `start` ilk basamağı hemen atar, `end` son
  basamağı sonda atar.

## Sonraki Adım

Geçiş bir koşula bağlıdır: değer değişmelidir. Değer kendiliğinden değişmiyorsa — bir
yükleme göstergesi dönmeye devam ediyorsa, bir uyarı iki renk arasında gidip geliyorsa —
geçişin tetikleyecek bir olayı yoktur. Sonraki ders, zaman çizelgesini bildirimin kendisine
yazan mekanizmayı ele alır: ara duraklar, yineleme sayısı ve yön.
