Metin2Games Discord sunucusuna katılmak ve anlık destek almak için tıkla!
1

View Transition API ile Sayfa Geçişlerini Canlandırmak: Tek Satır CSS ile Sayfalar Arası Geçiş ve startViewTransition ile Kart Ekleme

Kayıtlı
1 Yıl 9 Ay 26 Gün
Katılım
10 Ocak 2025
Konular
163
Mesajlar
257
Tepkime puanı
36
Online süresi
11h 19m
Puan
53
Konum
Türkiye
Web sitesi
www.zyncra.shop
View Transition API ile Sayfa Geçişlerini Canlandırmak: Tek Satır CSS ile Sayfalar Arası Geçiş ve startViewTransition ile Kart Ekleme

📌 Konu İçeriği — Hızlı Bakış (📂 cPanel / Web • ⏱ ~7 dk okuma • 💻 Kod: CSS)
01. 1. Adım: İki Sayfayı Hazırlamak ve Her Birine @view-transition Kuralını Eklemek
02. 2. Adım: Geçişi DevTools'ta Yavaşlatmak ve Pseudo-element Ağacını Okumak
03. Adlandırılmış her grubun içi
04. 3. Adım: Başlığı view-transition-name ile İki Sayfa Arasında Taşımak
05. 4. Adım: Görseli Listeden Kapak Alanına Büyüterek Taşımak ve Bozulmaları Düzeltmek
06. 5. Adım: Karşılığı Olmayan Bir Elemanı (Koyu Katman) Keyframes ile İçeri Almak

konu-c17370fbd4.jpg

1. Kart Listesinden Detay Sayfasına Görselin Büyüyerek Taşındığı Geçişi, Önce CSS Sonra JavaScript ile Adım Adım Yapıyoruz

Bir karta tıklıyorsunuz, sayfa bir anda beyaz ekrana düşüp yeni içerikle geri geliyor. Kullanıcı neyin nereye gittiğini anlamıyor. Bunu düzeltmek için eskiden SPA'ya geçip animasyon kütüphanesi eklemek gerekiyordu. View Transition API ile düz HTML sayfaları arasında bile, birkaç satır CSS ile görselin listeden detay sayfasındaki büyük kapak alanına kayarak taşınmasını sağlayabiliyorsunuz. Bu konuda önce iki sayfalı bir örnekte bunu kuracağız, sonra aynı mantığı JavaScript ile sayfa içindeki bir değişikliğe (yeni kart eklemek) uygulayacağız.

1. Adım: İki Sayfayı Hazırlamak ve Her Birine @view-transition Kuralını Eklemek

Örnekte from.html (kart listesi) ve to.html (detay) adında iki sayfa var, ikisi de aynı style.css dosyasını kullanıyor. Önemli olan, geçişin iki sayfada da açık olması ve sayfaların aynı origin'de durması. Ortak stil dosyası olduğu için kuralı bir kez yazmanız yeter.

CSS:
/* Sayfalar arası geçişi aç: ileri/geri düğmelerinde de çalışır */
@view-transition {
    navigation: auto;
}

Bu kadarıyla bile sayfalar arasında yumuşak bir çapraz geçiş (cross-fade) görürsünüz. Asıl iş, hangi elemanın hangisine dönüşeceğini tarayıcıya söylemekte.

Sayfaların kökünü ayırt edebilmek için html etiketlerine kimlik veriyoruz. Birazdan sayfaya özel kurallarda lazım olacak.

HTML:
<!-- from.html -->
<html lang="tr" id="from">

<!-- to.html -->
<html lang="tr" id="to">

2. Adım: Geçişi DevTools'ta Yavaşlatmak ve Pseudo-element Ağacını Okumak

Animasyonu gözle yakalayamıyorsanız ayar yapamazsınız. Chrome'da DevTools'u açın, sağ üstteki üç nokta menüsünden More tools > Animations panelini getirin ve hızı %10'a çekin. Duraklatıp sayfalar arasında gezinince Elements panelinde ::view-transition katmanını göreceksiniz. İçinde varsayılan ::view-transition-group(root) ve adlandırdığınız her eleman için ayrı bir grup oluşuyor.

Bu gruplara CSS ile müdahale edebilirsiniz. Süreyi uzatmak ve kök sayfanın varsayılan geçişini kapatmak için:

CSS:
/* Tüm geçişleri 0.5 saniyeye ayarla */
::view-transition-group(*) {
    animation-duration: 0.5s;
}

/* Sadece adlandırılmış elemanlar animasyonlu kalsın */
::view-transition-group(root) {
    animation: none;
}

Adlandırılmış her grubun içi

Her grubun içinde ::view-transition-image-pair(ad) var, onun da içinde eski ve yeni anlık görüntüyü temsil eden ::view-transition-old(ad) ile ::view-transition-new(ad) duruyor. Sonraki hata ayıklamaların hepsi bu iki parçayı düzeltmekten ibaret.

konu-9f9bf2927d.jpg

3. Adım: Başlığı view-transition-name ile İki Sayfa Arasında Taşımak

Eşleştirmek istediğiniz elemana iki sayfada da aynı view-transition-name değerini veriyorsunuz. Başlıklar iki sayfada da id="title" taşıdığı için tek kural yetiyor:

CSS:
#title {
    view-transition-name: title;
}

/* Eski başlık, yenisiyle üst üste binmesin */
::view-transition-old(title) {
    opacity: 0;
}

Dikkat edin: aynı sayfada aynı view-transition-name değerine sahip iki eleman olursa geçiş iptal olur. İsimler sayfa başına tekil olmalı.

4. Adım: Görseli Listeden Kapak Alanına Büyüterek Taşımak ve Bozulmaları Düzeltmek

Görsellerin kimlikleri farklı (#story-image ve #hero-image) ama ikisine de aynı geçiş adını vererek eşleştirebilirsiniz. Varsayılan hâlde eski ve yeni görüntü üst üste solarak karışıyor, yeni görüntü de gerilip bozuluyor. Çözüm, yerleşik animasyonu kapatıp iki görüntüyü aynı boyuta ve köşe yuvarlaklığına getirmek.

CSS:
#story-image,
#hero-image {
    view-transition-name: picture;
}

::view-transition-old(picture),
::view-transition-new(picture) {
    animation: none;
    mix-blend-mode: normal;
    height: 100%;
    border-radius: 0 0 30px 30px;
}

/* Detay sayfasına giderken yeni görüntü gerilmesin */
#to::view-transition-new(picture) {
    object-fit: cover;
    overflow: hidden;
}

/* Geri dönerken */
#from::view-transition-new(picture) {
    object-fit: contain;
}
#from::view-transition-old(picture) {
    object-fit: cover;
    overflow: hidden;
    border-radius: 20px;
}

Burada #to ve #from seçicileri az önce html etiketine verdiğiniz kimliklerdir. Böylece aynı pseudo-element, hangi sayfadan geldiğine göre farklı davranıyor. Geri dönüş yönünde object-fit değerlerini kendi görselinizin oranına göre denemeniz gerekebilir; bu kısım tamamen gözle ayar.

konu-2b26221ab6.jpg

5. Adım: Karşılığı Olmayan Bir Elemanı (Koyu Katman) Keyframes ile İçeri Almak

Detay sayfasındaki koyu katman ve içindeki yazılar from.html sayfasında yok, bu yüzden ekrana aniden beliriyor. Katmana #overlay üzerinden bir ad verirseniz, giderken yalnızca ::view-transition-new(overlay), geri dönerken yalnızca ::view-transition-old(overlay) oluşur. Karşılığı olmayan tarafın görüntüsü hiç yaratılmıyor, bu normal.

CSS:
#overlay {
    view-transition-name: overlay;
}

@keyframes fade-in {
    from { opacity: 0; transform: translateY(50px); }
}
@keyframes fade-out {
    to { opacity: 0; }
}

/* Görsel yerine oturduktan sonra aşağıdan süzülerek gelsin */
::view-transition-new(overlay) {
    animation: 250ms cubic-bezier(0, 0, 0.3, 1) both fade-in;
    animation-delay: 0.5s;
}
::view-transition-old(overlay) {
    animation: 50ms cubic-bezier(0.3, 0, 1, 1) both fade-out;
}

/* Geçiş sırasında görünen siyah şeridi gizle */
::view-transition-group(overlay) {
    overflow: hidden;
}

animation-delay: 0.5s değeri, ikinci adımda koyduğunuz 0.5 saniyelik süreye denk geliyor; görsel yerine oturmadan katman gelmesin diye. Süreyi değiştirirseniz gecikmeyi de değiştirin.

6. Adım: Sayfa İçi Değişiklikte document.startViewTransition ile Yeni Kart Eklemek

JavaScript ile DOM'a eklenen bir kart CSS tarafından yakalanamaz. Bu durumda değişikliği document.startViewTransition() içine alıyorsunuz: tarayıcı önce mevcut görüntüyü alıyor, sizin DOM güncellemenizi çalıştırıyor, sonra iki hâl arasını canlandırıyor. Düğme için olay dinleyiciyi addEventListener ile bağlıyoruz.

JavaScript:
const dugme = document.querySelector(".new-story-btn");
const kapsayici = document.querySelector(".stories-container");

function kartHazirla(veri) {
    const sablon = document.querySelector(".story-card");
    if (!sablon) return null;
    const kart = sablon.cloneNode(true);

    const resim = kart.querySelector("img");
    resim.setAttribute("src", veri.image); // src olmalı
    resim.removeAttribute("id"); // klonda kimlik çakışmasın

    kart.querySelector(".story-tag").textContent = veri.tag;
    kart.querySelector(".story-title").textContent = veri.title;
    kart.querySelector(".story-description").textContent = veri.description;
    return kart;
}

async function kartEkle() {
    const kart = kartHazirla({
        tag: "Fantasy",
        title: "Sky Kingdoms",
        description: "Havada süzülen adalar ve onları koruyan kahramanlar.",
        image: "./assets/image-5.jpg",
    });
    if (!kart) return;

    // Tarayıcı desteklemiyorsa animasyonsuz ekle
    if (!document.startViewTransition) {
        kapsayici.appendChild(kart);
        return;
    }

    kart.style.viewTransitionName = "targeted-card";
    const gecis = document.startViewTransition(() => {
        kapsayici.appendChild(kart);
    });
    await gecis.finished;
    kart.style.viewTransitionName = ""; // adı temizle
}

dugme.addEventListener("click", kartEkle);

Önemli satırlar: setAttribute("src", ) doğru öznitelik; resmi değiştirirken "img" diye bir öznitelik yazmak çalışmaz. Klonlanan kartta id tekrar edeceği için görselin kimliğini kaldırıyoruz, çünkü sayfadaki CSS kuralları kimlikle çalışıyor. viewTransitionName değerini geçiş bitince boşaltmak, kartın sonradan taşınırken istenmeyen animasyon almasını engelliyor.

konu-efcc06e521.jpg

7. Adım: React ve Next.js'te Deneysel Bayrakları Açmak

React tarafında ViewTransition bileşeni hâlâ deneysel. Kararlı sürümde yok; react@experimental ve react-dom@experimental paketlerine geçmeniz gerekiyor. Adı sürüme göre unstable_ViewTransition ya da ViewTransition olabilir, kurduğunuz sürümün belgesine bakın.

JavaScript:
import { unstable_ViewTransition as ViewTransition } from "react";

export default function Kart() {
    return (
        <ViewTransition>
            <div></div>
        </ViewTransition>
    );
}

Next.js'te ise next.config.js içinde deneysel bayrağı açıyorsunuz:

JavaScript:
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    viewTransition: true,
  },
};

module.exports = nextConfig;

Bunların ikisi de API'si değişebilen özellikler. Üretim projesinde sürümü sabitleyin.

8. Adım: Canlıya Almadan Önce Kontrol Listesi ve Pratik İpuçları

Destek durumu tarayıcıdan tarayıcıya ve sürümden sürüme değişiyor. Sayfalar arası geçiş Chromium tarafında yerleşik; diğer tarayıcılarda sürüm sürüm ilerliyor. Yayına almadan önce güncel uyumluluk tablosuna bakın. Destek olmayan tarayıcıda CSS kuralı yok sayılır ve sayfa normal şekilde açılır; bozulan bir şey olmaz. JavaScript tarafında ise document.startViewTransition var mı diye kontrol etmeyi unutmayın.

  1. Hareketi azaltmak isteyen kullanıcılar için geçişi kapatın.
  2. Aynı sayfada aynı view-transition-name değerini iki elemana vermeyin.
  3. Geçiş süresini kısa tutun; 0.3 ile 0.5 saniye arası çoğu sayfa için yeterli.
  4. Büyük görsellerde geçiş takılıyorsa görseli önceden yükleyin ve boyutunu optimize edin.
  5. İki sayfanın aynı origin'de olduğunu ve ikisinde de @view-transition kuralının bulunduğunu doğrulayın.

Hareket azaltma tercihi için şu kural yeterli:

CSS:
@media (prefers-reduced-motion: reduce) {
    ::view-transition-group(*),
    ::view-transition-old(*),
    ::view-transition-new(*) {
        animation: none;
    }
}

Kendi sitenizde en çok işe yarayacak yer genellikle liste-detay geçişi; önce başlıkla başlayın, sonra görseli ekleyin. Takıldığınız yerleri ya da farklı tarayıcılarda gördüğünüz tuhaflıkları konunun altına yazabilirsiniz, birlikte bakarız.

Sıkça Sorulan Sorular (SSS)
Soru 1: Paylaşılan CSS örneği canlı (production) ortamda kullanılabilir mi?
Evet. Konudaki kod bloğu bellek güvenliği, hata yakalama ve performans kriterleri gözetilerek hazırlanmıştır; kendi proje mimarinize uyarlayarak doğrudan kullanabilirsiniz.

Soru 2: View Transition API ile Sayfa Geçişlerini Canlandırmak: Tek Satır CSS ile Sayfalar Arası Geçiş ve startViewTransition ile Kart Ekleme uygulamasında en sık yapılan hata nedir?
Girdi doğrulamasını (validation) ve zaman aşımı/kaynak sınırlarını varsayılan değerlerde bırakmaktır. Rehberdeki yapılandırma adımlarını eksiksiz uygulayarak olası darboğazları önleyebilirsiniz.
 
Community platform by XenForo® © 2010-2026 XenForo Ltd.
© 2020-2026 Metin2Games - Tüm Hakları Saklıdır.
Geri
Üst