Transitions Svelte — Svelte

Svelte memiliki built-in transitions untuk animasi elemen masuk dan keluar DOM. Transition Dasar import { fade } from "svelte/transition" let visible = true…

Transisi adalah animasi yang Svelte jalankan saat sebuah elemen masuk ke DOM atau keluar dari DOM, misalnya toast "Nasi Goreng masuk keranjang" yang muncul perlahan lalu memudar. Bayangin pelayan Warung Bu Sri mengantar piring. Piringnya gak tiba-tiba ada di meja: tangan pelayan membawanya masuk dari samping. Waktu diangkat, piringnya dibawa keluar pelan-pelan juga. Tapi kalau lauknya ditambah, piringnya gak diantar ulang. Transisi Svelte sama: jalan saat elemen datang dan pergi, bukan saat isinya berubah.

🧪 Tebakan cepat: toast <div transition:fade> ada di dalam {#if tampil}, dan blok itu ada di dalam {#if panelBuka}. Pembeli menutup panelnya saat toast sedang tampil. Toast-nya memudar 400 ms, atau langsung hilang? Jawabannya ada di bagian "Lokal dan |global".

transition:fade

<script>
  import { fade } from "svelte/transition"

  let tampil = false
</script>

<button on:click={() => (tampil = true)}>Tambah Nasi Goreng</button>

{#if tampil}
  <div class="toast" transition:fade>
    Nasi Goreng masuk keranjang
    <button on:click={() => (tampil = false)}>Tutup</button>
  </div>
{/if}
Kejadian Yang terjadi
Klik Tambah Nasi Goreng <div> dipasang, opacity naik dari 0 ke 1 selama 400 ms
Klik Tutup opacity turun dari 1 ke 0 selama 400 ms, baru setelah itu <div> dilepas dari DOM

Parameter: durasi, jeda, arah

Tiap transisi menerima objek parameter. Kurung kurawal luarnya milik Svelte, yang dalam adalah objek JavaScript:

<div class="toast" transition:fly={{ y: -20, duration: 300, delay: 100 }}>
  Nasi Goreng masuk keranjang
</div>
Transisi Nilai bawaannya
fade duration: 400, delay: 0, easing linear
fly duration: 400, delay: 0, x: 0, y: 0, opacity: 0, easing cubicOut
slide duration: 400, axis: "y", easing cubicOut
scale duration: 400, start: 0, easing cubicOut

in: dan out: terpisah

<div class="toast" in:fly={{ y: -20, duration: 300 }} out:fade={{ duration: 200 }}>
  Nasi Goreng masuk keranjang
</div>

Lokal dan |global

{#if panelBuka}
  <section class="panel">
    {#if tampil}
      <div class="toast" transition:fade>Nasi Goreng masuk keranjang</div>
    {/if}
  </section>
{/if}

📌 Intro saat halaman pertama dibuka

Elemen yang sudah ada saat komponen pertama kali dipasang gak menjalankan intro. let tampil = true membuat toast langsung tampil, tanpa memudar masuk. Itu sebabnya paragraf di latihan langsung terlihat. new App({ target, intro: true }) di main.js memutar intro di render pertama, tapi di Svelte 4 cuma untuk transisi |global.

📌 Easing dan gerakan yang dikurangi

easing adalah function yang mengubah kemajuan animasi dari 0 sampai 1 jadi kurva gerak. Svelte menyediakannya di "svelte/easing", misalnya cubicOut dan elasticOut, dan kamu boleh menulis sendiri: easing: (t) => t * t mulai pelan lalu makin cepat.

Sebagian pengguna menyalakan setelan "kurangi gerakan" di perangkatnya. Svelte gak membacanya otomatis, jadi baca sendiri:

const kurangiGerak = window.matchMedia("(prefers-reduced-motion: reduce)").matches
// lalu: transition:fly={{ y: kurangiGerak ? 0 : -20, duration: kurangiGerak ? 0 : 300 }}

Di SvelteKit, yang juga merender di server, baca nilainya di onMount. Svelte 5 menyediakan prefersReducedMotion.current dari "svelte/motion".

Latihan: fade dan fly

Latihan pertama cukup menambah import dan directive-nya ke kode awal: import { fade } from "svelte/transition" dan <p transition:fade>Teks dengan fade</p>. Latihan kedua ditulis lengkap:

<script>
  import { fly } from "svelte/transition"
  let visible = true
</script>

<button on:click={() => (visible = !visible)}>Toggle</button>

{#if visible}
  <p transition:fly={{ y: -50, duration: 400 }}>Terbang dari atas!</p>
{/if}

Penguji menekan tombol bertulisan Toggle, lalu memeriksa bahwa <p> sudah gak ada di halaman. Dia menunggu sekitar satu detik, jadi outro 400 ms sempat selesai.

Svelte 5

transition:, in:, out:, |global, dan semua fungsi di "svelte/transition" sama di Svelte 5. Bedanya cuma di sekitarnya: let visible = $state(true) dan onclick.

⚠️ Jebakan yang sering ketemu

TL;DR: Transisi jalan saat elemen dipasang atau dilepas lewat {#if} atau {#each}, bukan saat isinya berubah. Impor dari "svelte/transition" (fade, fly, slide, scale, blur, draw), lalu pasang transition:fade untuk masuk dan keluar, atau in:fly dan out:fade terpisah. Parameternya objek dalam kurung kurawal ganda, misalnya {{ y: -20, duration: 300, delay: 100 }}; fade dan fly berjalan 400 ms kalau gak diatur. transition: bisa berbalik di tengah jalan, in: dan out: gak. Di Svelte 4 transisi itu lokal: gak jalan saat blok luar yang menutup, kecuali |global, dan gak jalan di render pertama. Untuk pengguna yang mengurangi gerakan, baca prefers-reduced-motion dan pakai duration: 0. Latihannya: <p transition:fade>Teks dengan fade</p>, dan tombol Toggle dengan <p transition:fly={{ y: -50, duration: 400 }}>Terbang dari atas!</p> di dalam {#if visible}.

Yang akan kamu pelajari