// Adaugă asta în global.css sau index.css:
// @keyframes gradient-shift {
// 0% { background-position: 0% 50%; }
// 50% { background-position: 100% 50%; }
// 100% { background-position: 0% 50%; }
// }
// .animate-gradient { animation: gradient-shift 4s ease infinite; }
export function GradientButton() {
return (
<button className="px-6 py-3 font-semibold text-white rounded-xl shadow-lg transition-transform active:scale-95 bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 bg-[length:200%_200%] animate-gradient">
Abonament Pro
</button>
);
}Am văzut săptămâna trecută un PR în care un coleg a tras framer-motion doar ca să animeze fundalul unui buton de checkout. Pachetul ăla adaugă lejer 30-35KB gzipped în bundle, iar toată șmecheria se rezolvă cu câteva linii de CSS nativ. Am eliminat dependența, am rescris animația cu Tailwind și am scăzut timpul de încărcare pe un proiect cu 15k vizitatori zilnici.
De ce nu poți anima bg-gradient direct
Dacă ai încercat vreodată să pui transition-all pe o clasă de Tailwind precum bg-gradient-to-r from-blue-500 to-purple-500 și ai schimbat culorile pe :hover, ai observat probabil că nu se întâmplă nicio tranziție lină. Stările se schimbă brusc, fără niciun efect de estompare.
Motivul e simplu: browserele nu știu să facă interpolare directă între două declarații de background-image (care este tipul de date generat de linear-gradient). Spre deosebire de opacity sau transform, unde procesorul grafic (GPU) știe exact ce să calculeze cadru cu cadru, la imaginile de fundal browserul re-desenează totul instant.
Soluția: mărirea fundalului și deplasarea lui
Trucul clasic, care funcționează impecabil de ani de zile, este să faci imaginea de fundal mai mare decât elementul în sine (de exemplu, background-size: 200% 200%) și apoi să animezi doar background-position.
Deoarece background-position este o proprietate cu valori numerice (procente sau pixeli), browserul o poate interpola fără nicio problemă. Animația devine fluidă, rulând la 60 sau 120 FPS pe majoritatea ecranelor moderne.
Cum implementăm asta curat în Tailwind
În Tailwind CSS v3 sau v4, nu ai nevoie neapărat să modifici fișierul de configurare dacă vrei să folosești clase arbitrare. Trebuie doar să setezi două lucruri esențiale pe elementul tău:
- Dimensiunea fundalului:
bg-[length:200%_200%](sau300% 300%dacă ai 4-5 culori în gradient). - O animație custom definită în CSS-ul tău global sau în
tailwind.config.jscare schimbă poziția de la0% 50%la100% 50%și înapoi.
Când schimbi poziția pe axa X de la 0% la 100%, culorile ascunse din afara cadrului intră vizual în scenă, dând senzația că gradientul „curge”.
Trade-off-uri reale de care să ții cont
Soluția asta e super rapidă, dar are limitele ei evidente pe care e bine să le știi înainte să o pui peste tot:
Unde e brici:
- Butoane de CTA, badge-uri, carduri evidențiate sau text cu
bg-clip-text. - Zero JavaScript executat pe main thread pentru animație.
- Fără re-renderings inutile în React sau Vue.
Unde e nasol:
- Animate pe suprafețe uriașe (cum ar fi tot fundalul unei pagini pe un ecran 4K),
background-positionpoate declanșa repaint-uri costisitoare pe procesoare grafice slabe de mobil. - Schimbarea dinamică a culorilor din cod în timp real e mai greoaie comparativ cu un lib de JS, necesitând variabile CSS injectate în
style.
La proiectele unde fiecare kilobait contează pe mobil, CSS-ul pur bate oricând o librărie grea de JS. Voi mai folosiți pachete externe pentru animații micro în UI sau încercați să le rezolvați nativ?