Tailwind

Анімації, трансформації та 3D у Tailwind v4

Вичерпний посібник з анімацій у Tailwind CSS v4: transition, animation, вбудовані keyframes, кастомні @keyframes. Повна система трансформацій: scale, rotate, translate, skew. Нові 3D-трансформації v4: perspective, rotate-x/y/z, backface-visible. Мікроанімації для UI.

Анімації, трансформації та 3D у Tailwind v4

Вступ: чому анімації — це не прикраса, а комунікація

Анімації у веб-інтерфейсі — це не «гарні ефекти заради ефектів». Кожна добре спроєктована мікроанімація несе функціональне навантаження:

  • Hover-ефект на кнопці підтверджує, що елемент інтерактивний
  • Плавна поява модального вікна дає мозку час «зрозуміти», що відбулося
  • Анімація завантаження знімає тривогу очікування
  • 3D-перекид картки розкриває прихований вміст із просторовим контекстом

Поганий дизайн анімацій — це анімації заради анімацій: занадто повільні, занадто складні, або такі, що відволікають. Хороший дизайн — непомітний, але відчутний. Ви не думаєте «о, яка гарна анімація» — ви просто почуваєтеся комфортно, користуючись інтерфейсом.

У цій статті ми розберемо всю систему анімацій та трансформацій Tailwind v4: від базових transition до нових 3D-трансформацій, що з'явилися у четвертій версії.

Частина матеріалу (зокрема, hover:, focus: та інші варіанти) детально розглянута у статті 06. Тут ми зосереджуємося на анімаційній та трансформаційній складовій, не повторюючи варіантний синтаксис.

Частина І. Transitions: плавність у кожній взаємодії

1.1. Що таке CSS Transition і як Tailwind його реалізує

CSS Transition — механізм плавної зміни CSS-властивостей з часом. Без transition зміна стилю миттєва. З transition — відбувається за вказану тривалість за вказаною функцією плавності.

Базова модель:

transition: {властивість} {тривалість} {функція-плавності} {затримка}

Tailwind розбиває це на окремі утиліти:

ГрупаУтилітаCSS
Щоtransition, transition-colors, transition-transform, transition-opacity, transition-shadow, transition-all, transition-nonetransition-property
Скількиduration-75, duration-100, ..., duration-1000transition-duration
Якease-linear, ease-in, ease-out, ease-in-outtransition-timing-function
Колиdelay-0, delay-75, ..., delay-1000transition-delay

1.2. Клас transition: що він робить насправді

Клас transition — не просто «увімкнути переходи». Він задає конкретний список властивостей, що будуть анімуватися:

/* Що генерує клас transition */
.transition {
    transition-property: color, background-color, border-color,
                         text-decoration-color, fill, stroke,
                         opacity, box-shadow, transform, filter,
                         backdrop-filter;
    transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    transition-duration: 150ms;
}

Це не transition: all — це ретельно відібраний набір властивостей, що охоплює 99% UI-потреб і при цьому не навантажує GPU зайвими обчисленнями.

Порівняємо всі transition-* класи:

<!-- transition — кольори + тіні + трансформації (рекомендований) -->
<button class="transition hover:bg-indigo-700 hover:shadow-lg hover:scale-105">

<!-- transition-colors — ТІЛЬКИ кольорові властивості -->
<button class="transition-colors hover:bg-indigo-700 hover:text-white">
<!-- Корисно: hover:scale-105 НЕ буде анімуватися — немає зайвих обчислень -->

<!-- transition-transform — ТІЛЬКИ transform -->
<div class="transition-transform hover:scale-110 hover:rotate-3">
<!-- hover:bg-*  НЕ буде анімуватися -->

<!-- transition-opacity — ТІЛЬКИ opacity -->
<div class="transition-opacity hover:opacity-50">

<!-- transition-shadow — ТІЛЬКИ box-shadow -->
<div class="transition-shadow hover:shadow-2xl">

<!-- transition-all — ВСЕ (обережно! дорого для GPU) -->
<div class="transition-all hover:bg-red-500 hover:scale-110 hover:rounded-full">

<!-- transition-none — вимкнути transition (перевизначити батьківський) -->
<button class="transition-none">
transition-all анімує кожну властивість, що змінилася. Браузер вимушений перевіряти всі властивості на кожному кадрі — це дорого. Для складних компонентів використовуйте transition (вибіркові властивості) або спеціалізовані класи (transition-colors, transition-transform).

1.3. Duration та Timing Function: швидкість і характер

Тривалість (duration-*) визначає, скільки часу займає перехід:

<!-- Шкала duration: 75ms, 100ms, 150ms, 200ms, 300ms, 500ms, 700ms, 1000ms -->
<button class="transition duration-75">  <!-- блискавично — 75ms -->
<button class="transition duration-150"> <!-- стандарт — 150ms (default) -->
<button class="transition duration-300"> <!-- плавно — 300ms -->
<button class="transition duration-700"> <!-- повільно — 700ms -->
<button class="transition duration-1000"><!-- дуже повільно — 1s -->

<!-- Довільна тривалість -->
<button class="transition duration-[350ms]">

Функції плавності (ease-*) визначають характер руху:

<!-- ease-linear: рівномірно (механічний) -->
<div class="transition ease-linear duration-300 hover:translate-x-4">

<!-- ease-in: повільний старт, швидкий фінал (елемент "вилітає") -->
<div class="transition ease-in duration-300 hover:opacity-0">

<!-- ease-out: швидкий старт, повільний фінал (елемент "прилітає") -->
<div class="transition ease-out duration-300 hover:translate-y-0">

<!-- ease-in-out: повільний старт і фінал (природний) — DEFAULT -->
<div class="transition ease-in-out duration-300 hover:scale-105">
Правило великого пальця для timing functions:
  • Елементи, що з'являютьсяease-out (швидко з'являється, плавно зупиняється)
  • Елементи, що зникаютьease-in (починає повільно, прискорюється і зникає)
  • Загальні UI-зміни → ease-in-out (природне відчуття)
  • Прогрес-бари, лоадери → ease-linear (рівномірний рух)

Кастомні timing functions через довільні значення:

<!-- Spring-ефект через cubic-bezier -->
<div class="transition ease-[cubic-bezier(0.34,1.56,0.64,1)] duration-500 hover:scale-110">
<!-- cubic-bezier(0.34,1.56,0.64,1) = "spring" — значення > 1 дає "перестрибок" -->

<!-- Більш різкий вхід -->
<div class="transition ease-[cubic-bezier(0.25,0.46,0.45,0.94)] duration-300">

1.4. Практичні патерни transitions

Живий приклад — колекція типових UI-transitions:

🔒localhost:3000

1.5. Transition з will-change

Для компонентів із частими анімаціями (нескінченні, або що починаються одразу при завантаженні) варто підказати браузеру наперед виділити GPU-ресурси через will-change:

<!-- Підказка браузеру: цей елемент буде трансформуватися -->
<div class="will-change-transform transition-transform duration-300 hover:scale-105">

<!-- Підказка для opacity -->
<div class="will-change-[opacity] transition-opacity duration-500">

<!-- Підказка для кількох властивостей -->
<div class="will-change-[transform,opacity] transition duration-300">

<!-- Скасувати will-change після анімації (через JS або після навантаження) -->
<!-- Tailwind: will-change-auto -->
<div class="will-change-auto">
will-change — інструмент оптимізації, не панацея. Зловживання (наприклад, will-change: transform на кожному елементі) збільшує споживання пам'яті GPU. Застосовуйте тільки до елементів, що дійсно активно анімуються, і знімайте після завершення анімації.

Частина ІІ. Transforms: рух, масштаб, поворот

2.1. Як Tailwind компонує трансформації

У Tailwind трансформації реалізовані через CSS Custom Properties, що дозволяє комбінувати різні transform-операції у одному класі transform:

/* Внутрішня реалізація: transform складається з CSS-змінних */
.scale-110 {
    --tw-scale-x: 1.1;
    --tw-scale-y: 1.1;
    transform: var(--tw-rotate-x) var(--tw-rotate-y) var(--tw-rotate-z)
               var(--tw-scale-x) var(--tw-scale-y) var(--tw-scale-z)
               translate(var(--tw-translate-x), var(--tw-translate-y));
}

Завдяки цьому можна комбінувати будь-які трансформації в одному класовому рядку без конфліктів:

<!-- Всі трансформації разом — коректно поєднуються -->
<div class="hover:scale-105 hover:rotate-3 hover:-translate-y-2 transition-transform duration-300">
    Масштаб + поворот + підйом
</div>

2.2. Scale: масштабування

<!-- Однакове по X та Y -->
<div class="scale-0">   <!-- 0% — невидимий -->
<div class="scale-50">  <!-- 50% -->
<div class="scale-75">  <!-- 75% -->
<div class="scale-90">  <!-- 90% -->
<div class="scale-95">  <!-- 95% — тонке зменшення (active state) -->
<div class="scale-100"> <!-- 100% — нормальний -->
<div class="scale-105"> <!-- 105% — тонке збільшення (hover) -->
<div class="scale-110"> <!-- 110% -->
<div class="scale-125"> <!-- 125% -->
<div class="scale-150"> <!-- 150% -->

<!-- Незалежно по осях -->
<div class="scale-x-50">  <!-- Тільки по горизонталі -->
<div class="scale-y-125"> <!-- Тільки по вертикалі -->
<div class="scale-x-[-1]"><!-- Горизонтальне дзеркало -->
<div class="scale-y-[-1]"><!-- Вертикальне дзеркало (flip) -->

<!-- Довільні значення -->
<div class="scale-[1.02]"> <!-- Дуже тонке збільшення -->
<div class="hover:scale-[1.015] transition-transform duration-200">

Практичне застосування scale:

<!-- Active (натискання) — scale 95 -->
<button class="active:scale-95 transition-transform duration-100">Натисни</button>

<!-- Hover — scale 105 -->
<img class="hover:scale-105 transition-transform duration-300 overflow-hidden rounded-xl">

<!-- Reveal анімація — від 0 до 100 -->
<div class="scale-0 animate-[scale-in_0.3s_ease-out_forwards]">

2.3. Rotate: обертання

<!-- Позитивні значення — за годинниковою стрілкою -->
<div class="rotate-0">   <!-- 0deg -->
<div class="rotate-1">   <!-- 1deg — ледь помітний нахил -->
<div class="rotate-2">   <!-- 2deg -->
<div class="rotate-3">   <!-- 3deg -->
<div class="rotate-6">   <!-- 6deg -->
<div class="rotate-12">  <!-- 12deg -->
<div class="rotate-45">  <!-- 45deg -->
<div class="rotate-90">  <!-- 90deg -->
<div class="rotate-180"> <!-- 180deg — перевернутий -->

<!-- Негативні значення — проти годинникової -->
<div class="-rotate-1">
<div class="-rotate-45">
<div class="-rotate-90">

<!-- Довільні значення -->
<div class="rotate-[33deg]">
<div class="hover:rotate-[360deg] transition-transform duration-700">
    <!-- Повне обертання при hover! -->
</div>

Практичні патерни:

<!-- Іконка стрілки при розкритті accordion -->
<svg class="rotate-0 transition-transform duration-200 group-open:rotate-180">

<!-- Декоративний нахил карток -->
<div class="rotate-2 hover:rotate-0 transition-transform duration-300">

<!-- Спіннер через анімацію (у CSS) -->
<div class="animate-spin border-2 border-indigo-600 border-t-transparent
            rounded-full size-5">

2.4. Translate: переміщення

<!-- По горизонталі (translate-x) -->
<div class="translate-x-0">   <!-- 0 -->
<div class="translate-x-1">   <!-- 4px (0.25rem) -->
<div class="translate-x-4">   <!-- 16px (1rem) -->
<div class="translate-x-full"> <!-- 100% ширини елемента -->
<div class="translate-x-1/2">  <!-- 50% ширини — для центрування -->
<div class="-translate-x-1">  <!-- -4px -->
<div class="-translate-x-full"><!-- -100% — виїзд за ліву межу -->

<!-- По вертикалі (translate-y) -->
<div class="translate-y-0">
<div class="-translate-y-1">  <!-- -4px — підйом вверх -->
<div class="-translate-y-px"> <!-- -1px — pixel-perfect підйом -->
<div class="translate-y-full"> <!-- 100% висоти — виїзд вниз -->

<!-- Одночасно по обох осях (v4) -->
<div class="translate-x-4 translate-y-2">

<!-- Довільні значення -->
<div class="translate-x-[calc(-50%+1rem)]"> <!-- Точне позиціонування -->
<div class="-translate-y-[3px]">            <!-- Pixel-perfect -->

Типові UI-патерни:

<!-- Toast notification: виїжджає з правого краю -->
<div class="translate-x-full transition-transform duration-300 ease-out"
     id="toast">
    Повідомлення
</div>
<!-- При появі: js → classList.remove('translate-x-full') -->

<!-- Tooltip: з'являється знизу елемента -->
<div class="opacity-0 translate-y-2 transition-all duration-200
            group-hover:opacity-100 group-hover:translate-y-0">
    Підказка
</div>

<!-- Hover lift effect -->
<div class="hover:-translate-y-1 hover:shadow-lg transition-all duration-200">
    Картка підіймається
</div>

<!-- Абсолютне центрування через translate -->
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
    Точно в центрі батька
</div>

2.5. Skew: нахил (skew)

<!-- По горизонталі -->
<div class="skew-x-0">  <!-- 0deg -->
<div class="skew-x-1">  <!-- 1deg -->
<div class="skew-x-2">  <!-- 2deg -->
<div class="skew-x-3">  <!-- 3deg -->
<div class="skew-x-6">  <!-- 6deg -->
<div class="skew-x-12"> <!-- 12deg -->
<div class="-skew-x-6"> <!-- -6deg — нахил у протилежний бік -->

<!-- По вертикалі -->
<div class="skew-y-3">
<div class="-skew-y-6">

<!-- Довільні значення -->
<div class="skew-x-[15deg]">

Skew рідко використовується для анімацій — частіше для декоративних діагональних розділювачів секцій:

<!-- Діагональний розділювач між секціями -->
<div class="relative h-24 bg-indigo-600 -skew-y-3 -mt-12 -mb-12"></div>

2.6. Transform Origin: точка обертання

За замовчуванням всі трансформації відбуваються відносно центру елемента. Клас origin-* змінює цю точку:

<!-- Стандартна шкала origin -->
<div class="origin-center">   <!-- центр (default) -->
<div class="origin-top">      <!-- верхній центр -->
<div class="origin-top-right"><!-- верхній правий кут -->
<div class="origin-right">    <!-- правий центр -->
<div class="origin-bottom-right">
<div class="origin-bottom">
<div class="origin-bottom-left">
<div class="origin-left">
<div class="origin-top-left">

<!-- Довільна точка -->
<div class="origin-[33%_75%]">

Практичне застосування:

<!-- Розкриття зверху вниз (як dropdown) -->
<div class="scale-y-0 origin-top transition-transform duration-200 group-open:scale-y-100">
    Контент dropdown
</div>

<!-- Поворот із нижнього лівого кута (як сторінка книги) -->
<div class="rotate-0 hover:-rotate-12 origin-bottom-left transition-transform duration-300">

<!-- Zoom із лівого краю (camera pan effect) -->
<img class="scale-100 hover:scale-110 origin-left transition-transform duration-700">
🔒localhost:3000

Частина ІІІ. Keyframe-анімації: animate-*

3.1. Вбудовані анімації Tailwind

Tailwind постачається з невеликим, але практичним набором вбудованих keyframe-анімацій:

КласОписВикористання
animate-spinНескінченне обертання (360°)Spinner, лоадер
animate-pingПульсуючий розширюючийся ringNotification badge, статус «онлайн»
animate-pulseПлавне мерехтіння opacity 100%→50%Skeleton loader
animate-bounceПідстрибування вгору-внизScroll-down стрілка, attention-getter
animate-noneВідключити анімаціюПеревизначення
<!-- Spinner: обертання -->
<div class="animate-spin size-6 border-2 border-indigo-600 border-t-transparent rounded-full">
</div>

<!-- Ping: пульсуючий badge -->
<span class="relative flex size-3">
    <span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
    <span class="relative inline-flex rounded-full size-3 bg-emerald-500"></span>
</span>

<!-- Pulse: skeleton loader -->
<div class="animate-pulse flex space-x-4">
    <div class="rounded-full bg-slate-200 size-10"></div>
    <div class="flex-1 space-y-2 py-1">
        <div class="h-4 bg-slate-200 rounded w-3/4"></div>
        <div class="h-4 bg-slate-200 rounded w-1/2"></div>
    </div>
</div>

<!-- Bounce: scroll indicator -->
<div class="animate-bounce flex items-center justify-center size-8 rounded-full bg-white shadow-md">
</div>

Живий приклад всіх вбудованих анімацій:

🔒localhost:3000

3.2. Управління анімацією: duration, delay, iteration, direction

Анімації можна налаштовувати так само, як переходи:

<!-- Тривалість (за замовчуванням: 1s для більшості) -->
<div class="animate-spin duration-[2000ms]">  <!-- повільний спін -->
<div class="animate-spin duration-500">        <!-- швидкий спін -->

<!-- Затримка перед стартом -->
<div class="animate-bounce delay-150">
<div class="animate-bounce delay-300">
<div class="animate-bounce delay-500">
<!-- Ефект: три крапки bouncing з зміщенням (typing indicator) -->

<!-- Пауза/зупинка анімації -->
<div class="animate-spin [animation-play-state:paused] hover:[animation-play-state:running]">
    <!-- Запуск анімації тільки при hover -->
</div>

<!-- Одноразова (forwards зберігає фінальний стан) -->
<div class="animate-[fade-in_0.5s_ease-out_forwards]">

<!-- Зворотна анімація -->
<div class="[animation-direction:reverse] animate-bounce">

<!-- Кількість повторень -->
<div class="[animation-iteration-count:3] animate-bounce">  <!-- 3 рази -->
<div class="[animation-iteration-count:infinite] animate-bounce"> <!-- нескінченно -->

Typing indicator (три bouncing крапки з delay):

🔒localhost:3000

3.3. Кастомні @keyframes у Tailwind v4

У Tailwind v4 кастомні keyframe-анімації визначаються прямо у CSS-файлі — без конфігурації JavaScript:

src/styles/main.css
@import 'tailwindcss';

/* === Визначення keyframes === */

@keyframes fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes fade-in-up {
    from {
        opacity: 0;
        transform: translateY(16px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes fade-in-down {
    from {
        opacity: 0;
        transform: translateY(-16px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes scale-in {
    from {
        opacity: 0;
        transform: scale(0.92);
    }
    to {
        opacity: 1;
        transform: scale(1);
    }
}

@keyframes slide-in-right {
    from { transform: translateX(100%); }
    to   { transform: translateX(0); }
}

@keyframes slide-out-right {
    from { transform: translateX(0); }
    to   { transform: translateX(100%); }
}

@keyframes shake {
    0%, 100% { transform: translateX(0); }
    10%, 50%, 90% { transform: translateX(-6px); }
    30%, 70% { transform: translateX(6px); }
}

@keyframes pop {
    0%   { transform: scale(1); }
    50%  { transform: scale(1.18); }
    100% { transform: scale(1); }
}

/* === Реєстрація у @theme для використання через animate-* === */

@theme {
    --animate-fade-in:        fade-in 0.4s ease-out;
    --animate-fade-in-up:     fade-in-up 0.5s ease-out;
    --animate-fade-in-down:   fade-in-down 0.5s ease-out;
    --animate-scale-in:       scale-in 0.3s ease-out;
    --animate-slide-in-right: slide-in-right 0.35s ease-out;
    --animate-slide-out-right:slide-out-right 0.35s ease-in forwards;
    --animate-shake:          shake 0.5s ease-in-out;
    --animate-pop:            pop 0.25s ease-in-out;
}

Після реєстрації у @theme класи стають доступними:

<!-- Елемент з'являється знизу -->
<div class="animate-fade-in-up">Контент</div>

<!-- Модальне вікно масштабується при відкритті -->
<div class="animate-scale-in">Модальне вікно</div>

<!-- Toast виїжджає справа -->
<div class="animate-slide-in-right">Повідомлення</div>

<!-- Форма трясеться при помилці -->
<form class="animate-shake" id="login-form">

<!-- Лайк «pop» -->
<button onclick="this.classList.add('animate-pop')" 
        onanimationend="this.classList.remove('animate-pop')">
    ❤️
</button>
🔒localhost:3000

Довільні анімації без реєстрації — через синтаксис animate-[...]:

<!-- Пряме використання без @theme -->
<div class="animate-[fade-in-up_0.4s_ease-out]">
<div class="animate-[slide-in-right_0.3s_ease-out_forwards]">

<!-- Тільки один раз (forwards) -->
<div class="animate-[scale-in_0.3s_ease-out_forwards]">

Частина IV. 3D-трансформації: нові можливості v4

4.1. Що нового у v4: повна підтримка 3D

Tailwind v4 додав повноцінну підтримку 3D-трансформацій — те, що раніше вимагало написати [style="transform: rotateX(45deg)"] або окремий CSS-клас, тепер реалізується через стандартні утиліти.

Новий набір 3D-утиліт:

УтилітаCSSОпис
perspective-{n}perspective: {n}pxГлибина перспективи
perspective-origin-*perspective-originТочка зору
rotate-x-{deg}rotateX({deg}deg)Поворот по осі X
rotate-y-{deg}rotateY({deg}deg)Поворот по осі Y
rotate-z-{deg}rotateZ({deg}deg)Поворот по осі Z (= rotate-*)
scale-z-{n}scaleZ({n})Масштаб по осі Z
translate-z-{n}translateZ({n})Переміщення по осі Z
transform-style-3dtransform-style: preserve-3dЗберегти 3D-простір для нащадків
transform-style-flattransform-style: flatСкасувати 3D для нащадків
backface-visiblebackface-visibility: visibleЗворотній бік видимий
backface-hiddenbackface-visibility: hiddenЗворотній бік прихований

4.2. Perspective: налаштування глибини

perspective — ключ до реалістичного 3D. Він визначає відстань від спостерігача до площини Z=0. Чим менше значення — тим «ближчий» спостерігач, тим більш драматична перспектива:

<!-- perspective застосовується до БАТЬКА, а трансформація — до НАЩАДКА -->
<div class="perspective-[500px]">       <!-- близька перспектива — драматична -->
    <div class="rotate-y-45">Картка</div>
</div>

<div class="perspective-[800px]">       <!-- середня — збалансована -->
    <div class="rotate-y-45">Картка</div>
</div>

<div class="perspective-[1200px]">      <!-- далека — тонка -->
    <div class="rotate-y-45">Картка</div>
</div>

<!-- Вбудована шкала perspective -->
<div class="perspective-dramatic">   <!-- 100px — дуже близько -->
<div class="perspective-near">       <!-- 300px -->
<div class="perspective-normal">     <!-- 500px -->
<div class="perspective-midrange">   <!-- 800px -->
<div class="perspective-distant">    <!-- 1200px -->

4.3. Класичний 3D card flip

Card flip (перекидання картки) — найпоширеніший 3D-ефект в UI. Реалізується через rotate-y-180 та backface-hidden:

<!-- Обгортка: встановлює perspective та відстежує hover -->
<div class="perspective-[800px] group w-64 h-40 cursor-pointer">

    <!-- Внутрішній контейнер: обертається при hover -->
    <!-- transform-style-3d: дочірні елементи живуть у 3D-просторі -->
    <div class="relative w-full h-full transition-transform duration-700 ease-in-out
                transform-style-3d group-hover:rotate-y-180">

        <!-- Лицьова сторона -->
        <div class="absolute inset-0 rounded-2xl bg-indigo-600 text-white
                    flex items-center justify-center font-bold text-lg
                    backface-hidden">
            Лицьова
        </div>

        <!-- Зворотня сторона: вже повернута на 180° -->
        <div class="absolute inset-0 rounded-2xl bg-violet-600 text-white
                    flex items-center justify-center font-bold text-lg
                    backface-hidden rotate-y-180">
            Зворотня
        </div>

    </div>
</div>

Живий приклад з кількома варіантами:

🔒localhost:3000

4.4. Паралакс і тилт-ефект через JavaScript

Тилт-ефект (картка нахиляється за курсором) поєднує 3D-трансформації з JavaScript:

<!-- Картка з тилт-ефектом -->
<div id="tilt-card"
     class="[perspective:600px] w-64 h-40 cursor-pointer"
     onmousemove="handleTilt(event, this)"
     onmouseleave="resetTilt(this)">
    <div id="tilt-inner"
         class="w-full h-full rounded-2xl bg-gradient-to-br from-indigo-600 to-violet-700
                text-white flex items-center justify-center font-bold text-xl
                shadow-xl [transform-style:preserve-3d]
                transition-transform duration-100">
        <span class="[transform:translateZ(30px)]">Tailwind v4</span>
    </div>
</div>

<script>
function handleTilt(e, container) {
    const inner = container.querySelector('#tilt-inner') ?? container.firstElementChild
    const rect = container.getBoundingClientRect()
    const x = (e.clientX - rect.left) / rect.width  - 0.5   // від -0.5 до 0.5
    const y = (e.clientY - rect.top)  / rect.height - 0.5

    const rotateX = (-y * 20).toFixed(1) // від -10 до 10 deg
    const rotateY = ( x * 20).toFixed(1)

    inner.style.transform = `rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
}

function resetTilt(container) {
    const inner = container.querySelector('#tilt-inner') ?? container.firstElementChild
    inner.style.transform = 'rotateX(0deg) rotateY(0deg)'
}
</script>

4.5. Анімація доступності: prefers-reduced-motion

Не всі користувачі комфортно ставляться до анімацій. Люди з вестибулярними порушеннями, епілепсією або просто налаштованою системою «зменшити рух» — всі вони потребують поваги до своїх уподобань.

Tailwind надає варіант motion-reduce: та motion-safe::

<!-- motion-safe: — анімація ТІЛЬКИ якщо користувач НЕ вимкнув рух -->
<div class="motion-safe:animate-bounce">

<!-- motion-reduce: — альтернатива для тих, хто вимкнув -->
<div class="motion-reduce:transition-none motion-reduce:transform-none
            transition duration-300 hover:scale-105">

<!-- Spinner: повільніший для motion-reduce -->
<div class="animate-spin motion-reduce:animate-[spin_3s_linear_infinite]">

Правильна стратегія для критичних анімацій:

<!-- За замовчуванням — статично.
     Анімація тільки якщо рух прийнятний. -->
<div class="opacity-100
            motion-safe:opacity-0
            motion-safe:translate-y-4
            motion-safe:animate-fade-in-up">
    Контент
</div>

<!-- Тест: відкрийте DevTools → Rendering → Emulate CSS media feature → prefers-reduced-motion: reduce -->
motion-reduce:animate-none недостатньо — він зупиняє анімацію, але залишає початковий стан (наприклад, opacity-0). Завжди давайте motion-reduce:-стан видимий та функціональний без анімації.

Частина V. Завдання для самоперевірки


Підсумок

Ця стаття охопила повну систему анімацій та трансформацій Tailwind v4:

Transitions

transition → конкретний список властивостей. duration-* → тривалість. ease-* → характер. delay-* → затримка. Уникайте transition-all — воно дорого.

Transforms

scale-*, rotate-*, translate-*, skew-* поєднуються без конфліктів через CSS Custom Properties. origin-* контролює точку трансформації.

Keyframes

Вбудовані: spin, ping, pulse, bounce. Кастомні: @keyframes + реєстрація в @theme. Довільні: animate-[name_duration_easing_fill].

3D у v4

perspective-* на батьку + rotate-x/y-* на нащадку + transform-style-3d + backface-hidden = card flip, cube, tilt. Нова нативна підтримка без хаків.

Доступність

motion-safe: та motion-reduce: — обов'язкові для production. Завжди тестуйте з prefers-reduced-motion: reduce увімкненим.

Попередня стаття: Довільні значення та контейнерні запитиНаступна стаття: Tailwind CLI, PostCSS та інтеграція з фреймворками

Copyright © 2026