Анимации и переходы

Встроенные переходы добавляют анимацию появления и исчезновения элементов одной директивой transition:.

«Хорошая анимация незаметна, но её отсутствие заметно сразу.» Svelte встраивает плавные переходы прямо в синтаксис.

Когда элемент появляется или исчезает по условию, резкий скачок выглядит грубо. Svelte решает это встроенными переходами. Импортируйте функцию перехода из svelte/transition и навесьте её директивой transition:, in: или out:. Готовые переходы: fade, fly, slide, scale, blur, draw.

Переходы автоматически срабатывают, когда элемент добавляется или удаляется из DOM — например, через {#if}. Вам не нужно вручную управлять таймингами анимации: вы декларируете желаемый эффект, а Svelte проигрывает его в обе стороны.

<script>
  import { fade, fly } from 'svelte/transition';
  let visible = $state(true);
</script>

<button onclick={() => visible = !visible}>Переключить</button>

{#if visible}
  <p transition:fade>Плавное появление и исчезновение</p>
  <div in:fly={{ y: 20, duration: 300 }} out:fade>Разные переходы для входа и выхода</div>
{/if}

Можно настраивать параметры: длительность, задержку, дистанцию полёта, функцию плавности. Директива transition: применяется и на вход, и на выход; если эффекты должны различаться, используйте отдельные in: и out:. Для перестановок элементов в списке есть animate:flip, дающий плавное перемещение.

Как это работает под капотом

Функция перехода возвращает описание анимации: длительность и функцию, которая по прогрессу от 0 до 1 выдаёт стиль. Svelte вызывает эту функцию на каждом кадре. Смоделируем суть перехода fade на чистом JS.

// Суть перехода: прогресс 0..1 -> стиль на каждом кадре
function fade(duration) {
  return (t) => ({ opacity: t }); // t: 0 (нет) -> 1 (виден)
}

const fn = fade(300);
// имитируем кадры анимации появления
[0, 0.25, 0.5, 0.75, 1].forEach(t => {
  const style = fn(t);
  console.log('прогресс', t, '-> opacity', style.opacity);
});
// исчезновение — те же кадры в обратном порядке (1 -> 0)

Попробуй сам ▶ — вставь код в консоль браузера (F12 → Console) и нажми Enter, чтобы увидеть вывод.

  {#if visible}  ->  элемент добавлен  ->  in-переход (0 -> 1)
  {/if}
      |
  visible = false -> элемент удаляется -> out-переход (1 -> 0) -> затем убрать узел

Частые ошибки

  • Забыть импорт из svelte/transition. Переходы не встроены глобально.
  • Ждать перехода без изменения присутствия элемента. Они срабатывают на добавление/удаление из DOM.
  • Перегружать интерфейс анимациями. Избыток отвлекает и замедляет восприятие.

Best practices

  • Используйте короткие переходы (150–300 мс) — они ощущаются отзывчивыми.
  • Применяйте animate:flip для плавной перестановки элементов списка.
  • Уважайте настройку «уменьшить движение» у пользователя для доступности.

Анимация как часть UX, а не украшение

Переходы легко принять за косметику, но их настоящая роль глубже — они помогают пользователю понять, что происходит на экране. Когда элемент резко исчезает, мозг на долю секунды теряет нить: куда он делся, появится ли снова. Плавное затухание или сдвиг подсказывают, что элемент именно ушёл, а новый именно пришёл, и удерживают внимание на месте действия. Поэтому переходы стоит применять осознанно: подсвечивать появление уведомления, мягко открывать модальное окно, плавно перестраивать список при сортировке через animate:flip. Но мера здесь критична. Слишком долгие или вездесущие анимации раздражают и создают ощущение, что интерфейс тормозит. Держитесь коротких длительностей, анимируйте значимые изменения, а не каждую мелочь. И обязательно уважайте системную настройку «уменьшить движение»: для части пользователей избыток анимации — не эстетический вопрос, а причина дискомфорта вплоть до тошноты. Хорошая анимация незаметна, плохая — мешает.

Итог: переходы Svelte анимируют появление и исчезновение элементов через директивы transition:, in:, out:. Вы декларируете эффект, а Svelte проигрывает его на добавление и удаление узлов.

Проверьте себя
1. Когда автоматически срабатывают переходы Svelte (transition:)?
AПо таймеру каждую секунду
BПри добавлении элемента в DOM и удалении из него (например, через {#if})
CТолько при загрузке страницы
DПри наведении мыши
2. Откуда импортируются встроенные переходы вроде fade и fly?
AИз 'svelte'
BИз 'svelte/transition'
CИз '@sveltejs/kit'
DОни доступны глобально без импорта