View Transitions API: Bikin Animasi Halaman Tanpa Library JavaScript (2026)

Developer 30 Mei 2026 · OTPZap Team

Tahun 2025 Chrome ship View Transitions API untuk multi-page navigation. Tahun 2026 Firefox dan Safari finally support juga. Ini perubahan besar yang underrated: animation page transition yang dulu butuh framework heavy (Framer Motion, GSAP, Lenis) sekarang bisa pure browser native.

Result: bundle size kecil, performance lebih bagus, dan UX yang akhirnya feels seperti native app. Tapi banyak developer belum tau API ini exist atau gimana pakainya.

Artikel ini panduan praktis View Transitions API dari basic sampai advanced pattern.

Apa Itu View Transitions API

API browser yang allow seamless transition antara different state UI dengan animation. 2 mode:

Same-Document Transitions

Dalam SPA, saat lo update DOM (route change, modal open, list item add/remove), browser bisa animate transition antara state lama dan state baru.

Cross-Document Transitions (MPA)

Antara different page navigation (multi-page app). Click link, browser animate transition antara halaman tanpa page reload yang jarring.

Kedua mode pakai underlying mechanism yang sama: browser snapshot old DOM, render new DOM, animate antara mereka via CSS.

Basic Same-Document Transition

Implementasi paling sederhana, untuk SPA:

// JavaScript: trigger transition
function navigate(newUrl) {
  if (!document.startViewTransition) {
    // Fallback untuk browser yang ngga support
    updateContent(newUrl);
    return;
  }
  
  document.startViewTransition(() => {
    updateContent(newUrl);
  });
}

function updateContent(url) {
  // Update DOM seperti biasa
  document.querySelector('main').innerHTML = newContent;
}

Default-nya browser akan apply cross-fade animation antara old dan new state. Tanpa CSS apa apa, lo udah dapat smooth fade transition.

Customize dengan CSS

Default cross-fade boring. Customize via CSS:

/* Animasi old state keluar */
::view-transition-old(root) {
  animation: 300ms cubic-bezier(0.4, 0, 0.2, 1) both fade-out;
}

/* Animasi new state masuk */
::view-transition-new(root) {
  animation: 300ms cubic-bezier(0.4, 0, 0.2, 1) both fade-in;
}

@keyframes fade-out {
  to { opacity: 0; transform: translateX(-30px); }
}

@keyframes fade-in {
  from { opacity: 0; transform: translateX(30px); }
}

Slide-in dari kiri, slide-out ke kiri. Mirip native iOS navigation.

Advanced: Element-Specific Transitions

Untuk transition antara element yang sama di 2 page (kayak hero image yang stay, navbar yang move position), pakai view-transition-name:

/* CSS: kasih nama unik per element yang mau di-track */
.hero-image {
  view-transition-name: hero-photo;
}

.user-avatar {
  view-transition-name: avatar;
}

Browser akan track element dengan name yang sama di old dan new state, animate transition antara mereka. Kayak shared element transition di Android.

Use case populer: photo grid → photo detail. Photo expand smooth dari thumbnail ke full size.

Cross-Document Transitions (MPA)

Untuk multi-page app (kayak server-rendered, MPA tradisional), tambahkan ke CSS:

@view-transition {
  navigation: auto;
}

Done. Browser otomatis enable transition saat user navigate antara page di same origin. No JavaScript needed.

Plus customize per route:

/* Specific transition untuk certain page */
[data-page="home"]::view-transition-new(root) {
  animation: 400ms ease-out forwards slide-up;
}

@keyframes slide-up {
  from { transform: translateY(20px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

Use Case Real Yang Sangat Berguna

1. Modal Open/Close

Tanpa Framer Motion, smooth modal animation:

function openModal() {
  if (!document.startViewTransition) return showModal();
  
  document.startViewTransition(() => {
    document.querySelector('.modal').style.display = 'block';
  });
}

/* CSS */
.modal {
  view-transition-name: main-modal;
}

::view-transition-old(main-modal),
::view-transition-new(main-modal) {
  animation-duration: 200ms;
}

2. List Item Animation

Add/remove item dari list dengan smooth animation:

function addItem(item) {
  document.startViewTransition(() => {
    const li = document.createElement('li');
    li.style.viewTransitionName = `item-${item.id}`;
    li.textContent = item.name;
    list.appendChild(li);
  });
}

/* CSS untuk delete animation */
::view-transition-old(item-*) {
  animation: 200ms ease-out forwards slide-out-right;
}

@keyframes slide-out-right {
  to { transform: translateX(100%); opacity: 0; }
}

3. Tab Switching

Smooth content swap saat user click tab. Sebelumnya butuh framework atau library, sekarang native.

4. Theme Switching

Light/dark mode toggle dengan smooth color transition. Kombinasi dengan CSS variable.

5. Full Page Transitions di MPA

Server-rendered apps (Rails, Django, PHP, Laravel) yang historically clunky transition antara page, sekarang bisa smooth tanpa migrate ke SPA.

Browser Support Status 2026

Coverage cukup untuk production. Untuk older browser, fallback ke standard navigation (no animation, but still works).

Performance Considerations

1. Transitions Cost CPU/GPU

Browser snapshot DOM dan animate. Untuk page yang sangat complex (1000+ DOM node), transition bisa janky di low-end device.

Solusi: limit transition scope. Pakai view-transition-name hanya untuk element yang penting, biar browser ngga snapshot whole page.

2. Animation Duration

Default 250ms. Untuk page transition, 300-400ms biasanya sweet spot. Lebih lama = feels sluggish. Lebih singkat = ngga ke-perceive.

3. Reduced Motion

Honor user preference:

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

Pitfalls Common

1. Async Update di startViewTransition

Callback di startViewTransition harus synchronous DOM update atau return Promise:

// Salah - async tanpa await
document.startViewTransition(() => {
  fetch('/api/data').then(r => updateDOM(r));
});

// Benar - return promise
document.startViewTransition(async () => {
  const data = await fetch('/api/data').then(r => r.json());
  updateDOM(data);
});

2. View Transition Name Collision

Ngga boleh ada 2 element dengan view-transition-name yang sama at the same time. Kalau collision, transition ngga jalan untuk element tersebut.

3. Z-index dan Stacking Context

Transition bikin temporary stacking context. Element dengan z-index tinggi mungkin behave weird selama animation. Test edge case.

4. Form State Loss

Saat transition replace DOM, form state bisa hilang. Untuk form yang user lagi isi, save state ke localStorage atau handle preservation manual.

Comparison dengan Alternative

vs Framer Motion

vs GSAP

vs Custom CSS Transitions

Migration Strategy

Kalau lo udah pakai animation library, ngga perlu rip-and-replace. Strategy:

  1. Identify animation simple yang library overkill (page transition, basic fade)
  2. Replace one-by-one dengan VT API
  3. Keep library untuk complex animation yang VT API ngga handle
  4. Bundle size shrink, performance improve gradually

Penutup

View Transitions API adalah salah satu addition browser yang paling impactful di 2024-2026 tapi underrated. Bukan revolution dari sisi capability, tapi simplification masive dari sisi developer effort untuk UX yang udah common di native app.

Bagi web developer di 2026: spend 2-3 jam belajar API ini. Pattern-nya straightforward, browser support mature, dan bisa langsung apply ke project existing tanpa migrate framework. ROI sangat tinggi.

Yang ngga perlu: tetep pakai Framer Motion atau GSAP untuk every animation. Modern web dev workflow di 2026 mostly pakai VT API untuk page transition + sedikit library specific untuk complex case.