Stimulus — легковесный JavaScript-фреймворк, ориентированный на управление поведением элементов через декларативные контроллеры. Встроенные механизмы анимаций и переходов отсутствуют, однако управление классами позволяет реализовать сложные визуальные эффекты, плавные переходы и динамическое изменение стилей.
Контроллер в Stimulus представляет собой класс, связанный с
DOM-элементом через атрибут data-controller. Для работы с
анимациями ключевым является механизм действий (actions) и
целевых элементов (targets).
<div data-controller="fade" data-action="click->fade#toggle">
<p data-fade-target="box" class="box hidden">Контент для анимации</p>
</div>
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["box"]
toggle() {
this.boxTarget.classList.toggle("hidden")
this.boxTarget.classList.toggle("visible")
}
}
В данном примере происходит смена классов при клике, что позволяет запускать CSS-анимацию или переход.
CSS предоставляет свойства transition и
animation для управления плавностью и временем анимации.
Важно отделять состояния элемента через отдельные классы.
.box {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.4s ease, transform 0.4s ease;
}
.box.visible {
opacity: 1;
transform: translateY(0);
}
.box.hidden {
opacity: 0;
transform: translateY(20px);
}
Такой подход позволяет через только смену классов добиться плавного появления и скрытия элементов без необходимости управлять стилями напрямую через JavaScript.
Stimulus контроллеры позволяют реализовать цепочки анимаций. Для
этого можно использовать setTimeout или события перехода
CSS (transitionend).
toggle() {
this.boxTarget.classList.remove("visible")
this.boxTarget.classList.add("hidden")
this.boxTarget.addEventListener("transitionend", () => {
this.boxTarget.textContent = "Новый контент"
this.boxTarget.classList.remove("hidden")
this.boxTarget.classList.add("visible")
}, { once: true })
}
Ключевой момент: добавление обработчика с
{ once: true } предотвращает накопление событий и утечки
памяти.
Stimulus поддерживает массив целевых элементов, что упрощает одновременную анимацию нескольких элементов:
<div data-controller="fade">
<p data-fade-target="box" class="box hidden">Элемент 1</p>
<p data-fade-target="box" class="box hidden">Элемент 2</p>
</div>
toggle() {
this.boxTargets.forEach((el, index) => {
setTimeout(() => {
el.classList.toggle("hidden")
el.classList.toggle("visible")
}, index * 150)
})
}
Такой подход позволяет создавать поэтапное появление элементов с задержкой.
Stimulus предоставляет удобный способ динамически изменять классы
через свойства classList. Кроме toggle
доступны методы:
add — добавление классаremove — удаление классаreplace — замена одного класса другимthis.boxTarget.classList.add("highlighted")
this.boxTarget.classList.remove("hidden")
this.boxTarget.classList.replace("old-class", "new-class")
Эти методы дают полный контроль над визуальным состоянием элементов без изменения CSS напрямую через JS.
Для гибкости часто используют data-* атрибуты для
хранения параметров анимации:
<p data-fade-target="box" data-fade-duration="600" class="box hidden">Контент</p>
toggle() {
const duration = this.boxTarget.dataset.fadeDuration || 400
this.boxTarget.style.transitionDuration = `${duration}ms`
this.boxTarget.classList.toggle("hidden")
this.boxTarget.classList.toggle("visible")
}
Таким образом можно на лету изменять скорость анимации без дублирования CSS-классов.
Stimulus легко интегрируется с CSS-фреймворками и библиотеками анимаций, такими как Animate.css или Tailwind Transition Utilities. Контроллер просто управляет классами, а визуальная часть полностью делегируется стилям.
hidden, visible), избегая прямого управления
стилями в JS.transitionend
вместо setTimeout — это повышает стабильность на разных
устройствах.data-* атрибутах для
гибкой настройки.forEach и задержки.{ once: true } для предотвращения утечек памяти.Stimulus через управление классами предоставляет полностью декларативный и предсказуемый способ анимации, объединяя мощь CSS-переходов и структурированную логику контроллеров.