Я часто вижу, как дизайнеры создают красивые прототипы, но теряются, когда нужно объяснить логику интерактивности разработчикам. Если ты не разбираешься в верстке, но хочешь понимать, как сайт реагирует на действия пользователя — эта статья для тебя. Я расскажу про основные события вроде click или change, объясню, к каким элементам они привязаны и как это влияет на UX. Ты сможешь проектировать осознаннее и говорить с верстальщиками на одном языке — даже без знания JS.
1. События, которые ты точно встречал
Если ты проектируешь интерфейсы, ты де-факто уже работаешь с событиями — просто не называешь их так. Давай разберём 5 самых популярных событий, которые отвечают за базовую интерактивность.
1.1. click — «Кликнули? Делаем что-то!»
Где встречается
Кнопки (<button>), ссылки (<a>), карточки товаров, иконки.
Как работает
Срабатывает, когда пользователь кликает кнопкой мыши (или тапает на тачпаде или Enter при фокусе) по элементу на странице.
Типичный пример
Кнопка «Добавить в корзину» — событие срабатывает при любом клике (мышь, тап, Enter при фокусе).
- После отпускания кнопки мыши/тача (не при нажатии!).
- При нажатии Enter/Space на элементе с фокусом (если это
<button>или элемент с атрибутомrole="button").
- Клик на лейбл (
<label>)— переводит фокус на связанное поле ввода (<input>), ноclickсработает и на самом лейбле. - Клик на SVG-иконке внутри кнопки — событие «всплывает» до родительской кнопки.
- Клик правой кнопкой мыши — тоже триггерит
click(но обычно это перехватывают черезcontextmenu).
Пример из жизни Если в твоём макете есть карточка, которая должна вести на страницу товара, лучше обернуть её в <a>, а не назначать click на <div>.
1.2. change — «Значение изменилось? Обновляем!»
Где встречается Поля ввода (<input>), выпадающие списки (<select>), чекбоксы, другие контролы форм.
Как работает Срабатывает, когда пользователь изменил значение.
Типичный пример
Выбор страны в <select> — событие срабатывает только после завершения взаимодействия (например, закрытие выпадающего списка).
- Для
<input type="text">— при потере фокуса (blur), если значение изменилось. - Для
<input type="checkbox">— мгновенно при переключении. - Для
<select>— после выбора пункта (даже если тот же пункт выбран повторно).
<input type="file">— при выборе файла (даже если отменили диалог и выбрали тот же файл).<input type="range">— только после отпускания ползунка (в отличие отoinput).<textarea>— работает так же, как текстовыйinput, но дизайнеры часто забывают.
- Идеален для фильтров, форм и любых динамических данных — например, обновление цены при выборе варианта товара.
- Не путай с
input(реагирует на каждое нажатие клавиши).
Пример из жизни В Figma ты проектируешь селект с выбором страны. change сработает только после выбора, а не во время прокрутки списка.
1.3. focus / blur — «Куда нажали? Куда ушли?»
Где встречается Поля ввода (<input>), текстовые области (<textarea>).
focus— когда пользователь тапнул/кликнул в поле,blur— когда фокус потерялся (тапнул/кликнул в другое место).
Типичный пример
Поле ввода email — focus при клике внутрь, blur при клике вне поля.
<div contenteditable="true">— элемент с режимом редактирования тоже получает фокус, как поле ввода.focusна ссылке (<a>) — срабатывает при переходе по Tab, но игнорируется в большинстве интерфейсов.blurдля<select>— если раскрыли список, но передумали и кликнули вне его.
Пример из жизни В макете формы входа ты добавляешь анимацию лейбла при фокусе — это как раз focus.
1.4. load — «Всё загрузилось? Показываем!»
Где встречается Изображения (<img>), вся страница (<body>), iframe.
Как работает Срабатывает, когда контент полностью загрузился.
Типичный пример
Изображение в галерее — событие срабатывает, когда весь контент (включая внешние ресурсы) загружен.
- Для изображений
<img>— после полной загрузки изображения (даже если оно в кеше браузера). - Для скриптов
<script>— после выполнения скрипта. - Для
<iframe>— когда загружена вся вложенная страница.
<link rel="stylesheet">—loadсработает после загрузки CSS.- SVG, встроенный через
<object>— событие для SVG-документа. - Видео (
<video>) — но чаще используютcanplay(когда можно начать воспроизведение).
- Критично для лоадеров и «ленивой» загрузки — например, чтобы анимировать появление изображений.
- Не перегружай страницу тяжёлыми скриптами в
load— это замедлит отрисовку.
Пример из жизни: Ты делаешь лендинг с фоновым видео. load поможет запустить его только после загрузки, чтобы не ломать верстку.
1.5. submit — «Форма отправлена? Проверяем!»
Где встречается Формы (<form>)
Как работает Срабатывает при нажатии на кнопку отправки формы (<button type="submit"> или <input type="submit">) или Enter в поле.
Типичный пример
Форма входа — событие срабатывает перед отправкой данных на сервер.
- При клике на
<button type="submit">или<input type="submit">. - При нажатии Enter в любом поле формы (если нет кнопки
type="button"). - До фактической отправки — можно отменить через
e.preventDefault().
- Форма без кнопки — сработает при Enter в любом
input. - Динамическая форма, созданная через JS —
submitработает так же, как для обычной. <form method="dialog">— для модальных окон в HTML5.
- Обязателено для валидации перед отправкой данных — например, проверка email.
- Не забудь отменить стандартное поведение (
e.preventDefault()), если страница не должна перезагружаться.
Пример из жизни В твоём макете есть форма подписки. submit — это момент, когда можно показать анимацию «Спасибо».
Как это пригодится тебе?
Теперь, когда ты знаешь эти события, ты можешь:
- Осознанно проектировать интерактивность — например, не требовать анимацию при
clickдля<div>. - Говорить с разработчиками на их языке — «Здесь нужен
change, а неoinput». - Избегать «невозможных» решений — если в твоём прототипе 10 событий
mousemove, это может тормозить.
2. Что происходит с формами? События, которые управляют данными
Если ты проектируешь формы, тебе нужно понимать не только визуальные состояния (вроде «ошибка» или «успех»), но и какие события запускают эти изменения. Вот главные «триггеры», которые влияют на поведение полей ввода, чекбоксов и других элементов форм.
2.1. input — реакция на каждое нажатие
Типичный пример
Поле поиска с подсказками, где результаты обновляются по мере ввода.
- При каждом изменении значения (ввод символа, удаление, вставка из буфера).
- Не ждёт потери фокуса — работает мгновенно.
change= «значение изменилось и подтверждено» (например, уход из поля).input= «значение меняется прямо сейчас».
- Счётчик символов под полем комментария (обновляется при каждом нажатии).
- Динамическая валидация пароля (показывает силу пароля в реальном времени).
- Кастомные числовые поля (например, расчёт суммы при вводе цифр).
Совет для дизайнера
Если делаешь поле с мгновенной проверкой (например, поиск по базе), указывай в ТЗ:
«Использоватьinput, а неchange— подсказки должны появляться сразу при вводе».
2.2. invalid — когда форма не отправляется
Типичный пример
Поле email с валидацией, которое подсвечивает ошибку, если введён некорректный адрес.
- При попытке отправить форму (
submit), если поле не проходит встроенную HTML-валидацию (например,requiredилиtype="email"). - Можно кастомизировать стандартное сообщение браузера.
Ограничение
Не работает, если валидация написана на JavaScript (только нативные проверки HTML5).
- Поле с ограничением по длине (
minlength/maxlength). - Числовое поле с
min="0"(покажет ошибку при отрицательном значении). - Кастомные стили ошибок — браузер показывает сообщение, но дизайн можно переопределить CSS.
2.3. reset — когда форма очищается
Типичный пример
Кнопка «Очистить форму» в фильтрах или настройках.
- Только при клике на
<button type="reset">или вызовеform.reset(). - Не срабатывает при ручной очистке поля (например, удалении текста).
- Многостраничная форма (например, анкета), где можно сбросить все введённые данные.
- Динамически создаваемые поля — если их добавили после загрузки страницы,
resetтоже их очистит. - Сброс фильтров в интернет-магазине без перезагрузки страницы.
Совет для дизайнера
Если в твоём макете есть кнопка «Очистить», уточни в ТЗ:
«Использоватьreset, если нужно сбросить всю форму, илиclickс ручным очищением полей, если только часть».
Как это пригодится тебе?
- Для мгновенной реакции (поиск, подсчёт символов) →
input. - Для валидации при отправке →
invalid+submit. - Для сброса формы →
reset.
Что дальше?
В следующей части я расскажу про события для сложных интерфейсов:
- Как сделать анимацию при наведении (
mouseover). - Как реагировать на прокрутку (
scroll). - Почему
dblclick— это почти всегда плохая идея.
3. События для сложных интерфейсов: hover, скролл и опасные кейсы
Теперь разберём события, которые оживляют современные интерфейсы — от плавных hover-эффектов до анимаций при прокрутке. Я объясню, как они работают, когда их стоит использовать, а когда лучше избегать.
3.1. mouseover / mouseout — «Навели курсор? Показываем подсказку!»
Типичный пример
Кнопка с выпадающей подсказкой при наведении.
mouseover— когда курсор впервые попадает на элемент.mouseout— когда курсор полностью покидает элемент (даже если перешёл на дочерний элемент!).
- На мобильных устройствах нет состояния наведения, поэтому такие эффекты должны дублироваться для тапов.
- Если внутри элемента есть другие вложенные элементы,
mouseoutсработает при переходе на них (это можно исправить черезmouseleave).
- Интерактивная карта — подсветка регионов при наведении.
- Анимация иконки (например, вращение шестерёнки в настройках).
- Кастомные тултипы без использования CSS
:hover.
Совет для дизайнера:
Если делаешь эффект наведения, продумай альтернативу для мобильных устройств:
«Использоватьmouseoverдля десктопа, но добавитьclickдля мобильных».
3.2. scroll — «Прокрутили страницу? Запускаем анимацию!»
Типичный пример
Появление блоков с текстом или изображениями по мере скролла (эффект «параллакс»).
- При любом перемещении скроллбара (включая инерцию на тач-устройствах).
- Можно отлавливать прокрутку конкретного элемента (например, боковой панели), а не всей страницы.
- Слишком частые вызовы
scrollмогут тормозить страницу (например, если внутри тяжёлые вычисления). - На iOS события скролла иногда срабатывают с задержкой.
- Бесконечная лента — подгрузка контента при достижении низа страницы.
- Фиксированное меню, которое меняет стиль после прокрутки на 100px.
- Кастомный скроллбар с анимацией.
Совет для дизайнера
Если хочешь анимацию при скролле, укажи в ТЗ:
«Оптимизироватьscroll, чтобы не нагружать процессор (например, использоватьthrottling)».
3.3. dblclick — «Двойной клик? Почти никто не использует!»
Типичный пример
Редактор изображений, где двойной клик открывает полную версию.
- 95% пользователей не ожидают двойного клика в интерфейсах.
- На мобильных устройствах его почти невозможность.
- Конфликтует с
oclick(оба события сработают).
- Переименование файла в файловом менеджере (как в Windows).
- Открытие превью в админ-панели.
- Выделение текста — но это нативное поведение браузера.
Совет для дизайнера
Замени dblclick на:
- Однократный клик + иконку действия (например, карандаш для редактирования).
- Долгое нажатие (
touchstart) для мобильных интерфейсов.
3.4. resize — «Изменили размер окна? Адаптируем макет!»
Типичный пример
Адаптивное меню, которое меняет layout при сужении экрана.
- При изменении размеров окна браузера (ручное растягивание, поворот устройства).
- Не срабатывает при программном изменении размеров элемента (например, через JS).
- Событие вызывается многократно при резизовом окне (нужен
debounce). - На мобильных устройствах срабатывает при повороте экрана, но не при появлении/скрытии клавиатуры.
- Динамические диаграммы, которые пересчитывают размеры.
- Кастомные сетки с изменяемым количеством колонок.
- Отключение анимаций на узких экранах.
Совет для дизайнера
Если твой дизайн чувствителен к размерам экрана, добавь в ТЗ:
«Использоватьresizeс задержкой (debounce200ms), чтобы избежать лагов».
Итог для дизайнера
- Hover-эффекты →
mouseover/mouseout(но продумай мобильную версию). - Анимации при скролле →
scroll(с оптимизацией!). - Двойной клик → лучше не использовать (
dblclick). - Адаптация под размер экрана →
resize(сdebounce).
Ошибка, которую можно избежать
Не назначать scroll на тяжёлые операции (например, пересчёт позиций десятков элементов) — это приведёт к тормозам.
4. События для мобильных устройств: тапы, свайпы и особенности touch-интерфейсов
Если ты проектируешь мобильные приложения или адаптивные сайты, стандартные события вроде click и mouseover работают иначе — или не работают вообще. В этой главе я объясню, какие события заменяют привычные клики и ховеры на сенсорных экранах, и как это влияет на UX.
4.1. touchstart / touchend — аналог click, но для пальцев
Типичный пример
Кнопка, которая должна реагировать на касание, а не на клик.
touchstart— в момент первого касания экрана (аналогmousedown).touchend— когда палец отпускает экран (аналогmouseup).
clickна мобильных имеет задержку ~300 мс (браузер ждёт, не будет ли двойного тапа).touchstartсрабатывает мгновенно, но не поддерживает hover-эффекты.
- Игры (например, прыжок персонажа при касании).
- Интерактивные карты — выделение зоны при касании.
- Кастомные свайпы (но для них лучше использовать
touchmove).
Совет для дизайнера:
Если нужна мгновенная реакция на тап, укажи в ТЗ:
«Использоватьtouchstart+touchendвместоclickдля мобильных».
4.2. touchmove — отслеживание движения пальца
Типичный пример
Галерея с горизонтальным свайпом.
- При движении пальца по экрану после
touchstart. - Можно получить координаты касания (
event.touches[0].clientX).
- Событие срабатывает очень часто (нужна оптимизация, чтобы избежать лагов).
- Не работает при попытке свайпать скролл страницы.
- Рисование пальцем (как в графических редакторах).
- Перетаскивание элементов (drag-and-drop).
- Управление громкостью (вертикальный свайп).
Совет для дизайнера:
Если делаешь интерфейс со свайпами, продумай:
«Добавить визуальную подсказку (например, точки для свайпа в галерее), так как не все пользователи ожидают этого жеста».
4.3. gesturestart / gesturechange — масштабирование и поворот
Типичный пример
Изображение, которое можно увеличить двумя пальцами (пинч-зум).
- При мультитач-жестах (двумя и более пальцами).
- Позволяет отслеживать масштаб (
event.scale) и угол поворота (event.rotation).
- Работает только на iOS и некоторых Android-устройствах.
- Требует отмены стандартного поведения (
event.preventDefault()), иначе браузер будет масштабировать всю страницу.
Совет для дизайнера:
Если проектируешь пинч-зум, укажи:
«Заблокировать стандартное масштабирование страницы через <meta name="viewport" content="user-scalable=no">».
4.4. orientationchange — поворот экрана
Типичный пример
Видеоплеер, который переключается между портретным и ландшафтным режимом.
- Только при изменении ориентации устройства (не при программном повороте элемента).
- Можно проверить новое положение через
window.orientation.
- Не срабатывает на ПК (только мобильные устройства).
- На iOS иногда игнорируется, если страница загружена в iframe.
- Карусели, которые меняют количество слайдов при повороте.
- Адаптивные таблицы, преобразующиеся в карточки.
- Игры с разным управлением в портрете/ландшафте.
Совет для дизайнера
Всегда тестируй интерфейс в обоих ориентациях:
«При повороте экрана (orientationchange) перестраивать сетку галереи с 2 на 4 колонки».
Итог для дизайнера
- Быстрые тапы →
touchstart/touchend. - Свайпы →
touchmove(но избегай лагов). - Пинч-зум →
gesturechange(только для iOS/Android). - Поворот экрана →
orientationchange.
Ошибка, которую можно избежать
Не полагаться только на click для мобильных — это вызовет задержку 300 мс.
5. Специальные события: жесты, анимации и неочевидные сценарии
Теперь разберём события, которые оживляют интерфейсы — от сложных жестов до анимаций и работы с мультимедиа. Эти знания помогут тебе проектировать по-настоящему динамичные интерфейсы, не нарушая UX.
5.1. animationstart / animationend — контроль CSS-анимаций
Типичный пример
Кнопка, которая плавно исчезает после отправки формы.
animationstart— в первый кадр анимации (даже если она на паузе).animationend— когда анимация полностью завершена (или отменена).
- Не путай с
transitionend(для CSS-переходов). - Если анимация прервана (например, удалён класс),
animationendне сработает.
- Каскадные анимации — когда завершение одной запускает другую.
- Скрытие элемента только после окончания анимации.
- Счётчик повторов анимации через
animationiteration.
Совет для дизайнера
Если анимация критична для UX, укажи:
«Элемент должен стать кликабельным только после animationend».
5.2. fullscreenchange — вход/выход в полноэкранный режим
Типичный пример
Видеоплеер с кнопкой полноэкранного режима.
- При любом изменении состояния: как при входе в fullscreen, так и при выходе.
- Работает для видео, карт, игр и даже отдельных div-блоков.
- Презентации с полноэкранными слайдами.
- Фотогалереи без интерфейса в fullscreen.
- Скрытие панели инструментов при максимальном размере.
Совет для дизайнера
Всегда предусматривай кнопку выхода:
«При fullscreenchange показывать overlay с крестиком в углу».
5.3. beforeunload — «Точно хотите уйти?»
Типичный пример
Предупреждение при попытке закрыть страницу с несохранёнными данными.
- При закрытии вкладки, переходе по ссылке или обновлении страницы.
- Можно кастомизировать стандартное браузерное сообщение.
- Современные браузеры показывают только дефолтный текст (нельзя вставить свою верстку).
- Не работает в мобильных браузерах.
Совет для дизайнера
Не злоупотребляй этим событием:
«Использовать beforeunload только для критичных данных (например, незавершённый заказ)».
5.4. error — когда что-то пошло не так
Типичный пример
Запасное изображение, если основное не загрузилось.
- Для
<img>— при ошибке загрузки (неверный URL, 404). - Для
<script>— если скрипт не удалось выполнить. - Для
window— при необработанных ошибках JavaScript.
- Кастомные прелоадеры для видео (
<video onerror=...>). - Аналитика ошибок через отправку данных на сервер.
- Резервный шрифт при проблемах с загрузкой основного.
Совет для дизайнера
Продумай fallback-состояния:
«Для всех изображений добавить error с заменой на placeholder».
Итог для дизайнера
- Анимации →
animationstart/animationend. - Fullscreen →
fullscreenchange(но тестируй на iOS). - Предупреждения при уходе →
beforeunload(экономно!). - Обработка ошибок →
error+ fallback-дизайн.
Ошибка, которую можно избежать:
Не назначать beforeunload для тривиальных действий (например, «Точно хотите уйти?») — это раздражает пользователей.