Переходы (transitions) в экосистеме SvelteKit представляют собой декларативный механизм управления появлением, исчезновением и изменением состояния DOM-элементов. В отличие от классических подходов через CSS или сторонние анимационные библиотеки, Svelte предоставляет встроенную систему, тесно интегрированную с реактивностью.
UI-библиотеки, построенные поверх SvelteKit, расширяют этот механизм, предлагая готовые transition-компоненты, абстракции и шаблоны анимации.
В основе лежат три ключевых типа:
Пример:
<script>
import { fade } from 'svelte/transition';
let visible = false;
</script>
<button on:click={() => visible = !visible}>
toggle
</button>
{#if visible}
<div in:fade out:fade>
content
</div>
{/if}
Ключевая особенность — автоматическое управление жизненным циклом элемента. Svelte откладывает удаление DOM-узла до завершения анимации.
Svelte поставляется с набором стандартных функций:
fadeflyslidescaleblurcrossfadeКаждая функция возвращает конфигурацию CSS-анимации.
<div in:fly={{ y: 50, duration: 300 }}>
элемент
</div>
Параметры:
x, y — смещениеduration — длительностьdelayeasingUI-библиотеки (например, Skeleton, Flowbite-Svelte, Melt UI) инкапсулируют transitions в отдельные компоненты:
<Transition type="fade" duration={200}>
<Card />
</Transition>
Такая обёртка решает несколько задач:
Переход можно определить вручную:
export function custom(node, params) {
return {
duration: 400,
css: t => `
opacity: ${t};
transform: scale(${0.8 + t * 0.2});
`
};
}
Где:
t — прогресс (0 → 1)u = 1 - t — обратный прогрессИспользование:
<div in:custom>
элемент
</div>
Svelte использует easing из svelte/easing:
import { cubicInOut, elasticOut } from 'svelte/easing';
Пример:
<div in:fly={{ y: 100, easing: elasticOut }}>
Популярные easing:
linearcubicIncubicOutcubicInOutbounceOutelasticOutИспользуется для анимации перемещения элементов между списками.
import { crossfade } from 'svelte/transition';
const [send, receive] = crossfade({
duration: 300
});
<div out:send={{ key: item.id }}>
<div in:receive={{ key: item.id }}>
Особенности:
В сложных UI необходимо синхронизировать несколько элементов.
function stagger(delay, index) {
return delay * index;
}
{#each items as item, i}
<div in:fly={{ delay: i * 50 }}>
{/each}
Типовые примеры:
<Modal>
<div in:scale={{ duration: 150 }}>
Переходы тесно связаны с реактивными блоками:
$: if (open) {
// запускается transition
}
Особенности:
SvelteKit выполняет SSR, но:
onMountimport { onMount } from 'svelte';
let mounted = false;
onMount(() => {
mounted = true;
});
Ключевые практики:
transform и opacityПлохой пример:
height: ${t * 100}px;
Хороший:
transform: scaleY(${t});
Transitions часто используются как часть state machine:
Некоторые UI-библиотеки реализуют это через store:
import { writable } from 'svelte/store';
export const state = writable('idle');
UI-библиотеки часто комбинируют:
Пример:
<div
class="transition-opacity duration-200"
class:opacity-0={!visible}
class:opacity-100={visible}
>
Сравнение:
| Подход | Особенность |
|---|---|
| Svelte transitions | декларативный, lifecycle-aware |
| CSS transitions | проще, но без контроля удаления DOM |
В SvelteKit можно реализовать анимации маршрутов:
{#key $page.url.pathname}
<div in:fade out:fade>
<slot />
</div>
{/key}
Особенности:
Используются для:
Решения:
animate:flip<div animate:flip>
FLIP:
Иногда требуется дождаться завершения:
import { tick } from 'svelte';
await tick();
Или использовать callbacks:
<div
out:fade
on:outroend={() => console.log('done')}
>
Переходы должны учитывать:
@media (prefers-reduced-motion: reduce) {
* {
transition: none;
}
}
Современные библиотеки добавляют:
svelte/motion)import { spring } from 'svelte/motion';
{#if}1. Reveal on mount
{#if mounted}
<div in:fade>
2. Conditional UI
{#if loading}
<Spinner in:fade />
{:else}
<Content in:fade />
{/if}
3. Animated lists
{#each items as item (item.id)}
<div in:fly out:fade>
В UI-библиотеках переходы становятся частью дизайн-токенов:
Пример:
export const motion = {
fast: 150,
normal: 250,
slow: 400
};
Можно комбинировать:
<div
in:fly={{ y: 20 }}
in:fade
>
Svelte объединяет эффекты.
Через JS можно управлять:
css: (t, u) => `
transform: translateY(${u * 20}px);
opacity: ${t};
`
Transitions активно применяются в:
Они обеспечивают:
import { derived } from 'svelte/store';
Transitions могут зависеть от store:
{#if $isOpen}
<Panel in:slide />
{/if}
В крупных проектах:
// transitions.js
export { fade, fly };
Хорошая UI-библиотека:
Transitions становятся не просто эффектом, а частью архитектуры интерфейса.