module.exports = {
theme: {
extend: {
keyframes: {
'gradient-flow': {
'0%, 100%': { 'background-position': '0% 50%' },
'50%': { 'background-position': '100% 50%' },
},
},
animation: {
'gradient-flow': 'gradient-flow 6s ease infinite',
},
},
},
}Am văzut zeci de proiecte care trag după ele librării gigantice de animație doar ca să facă un amărât de gradient curgător pe un buton sau pe un background. Azi vă arăt cum facem asta doar din Tailwind și trei linii de CSS, fără să adăugăm niciun kilobyte în plus în bundle. Metoda e simplă, curată și extrem de performantă dacă o folosești unde trebuie.
La ultimul landing page pe care am lucrat (unde aveam cam 15k vizitatori unici pe zi), designerul voia neapărat un hero section cu un gradient subtil care se mișcă pe fundal. Inițial, un coleg mai junior pusese Framer Motion pentru asta. Am scos JS-ul inutil, am trecut pe varianta pure CSS și am economisit cam 40kb la încărcarea paginii. În plus, am scăpat complet de acel mic delay de hidratare enervant din React.
Cum funcționează logica din spate
Ideea e veche de când lumea, dar mulți o uită. Nu poți anima direct culorile unui linear-gradient prin proprietăți CSS standard în mod fluid (cel puțin nu fără @property care încă are ceva probleme de suport pe browserele vechi).
Șmecheria este să mărim fundalul la 200% (sau chiar 400%) din dimensiunea elementului și apoi să mutăm poziția acestui fundal folosind background-position. Când mișcăm poziția de la stânga la dreapta și înapoi, culorile par că curg organic.
Configurarea în Tailwind
Ca să nu scriem CSS clasic în fișiere separate, putem extinde configurația de Tailwind direct în tailwind.config.js. Avem nevoie de două chestii: să definim @keyframes și apoi să le legăm de o clasă de animație utilitară.
După ce adăugăm asta în config, putem folosi direct clasa animate-gradient-flow combinată cu utilitarele de gradient nativ din Tailwind, cam așa:
bg-gradient-to-r from-pink-500 via-red-500 to-yellow-500 bg-[length:200%_200%] animate-gradient-flow
Compromisul de care trebuie să fii conștient
Să fim sinceri până la capăt. Soluția asta merge brici pentru butoane, text decupat cu bg-clip-text sau secțiuni medii. Este extrem de rapid de implementat și nu încarcă JS-ul.
Totuși, există un trade-off important. Animarea proprietății background-position forțează browserul să facă repaint la fiecare cadru (frame). Spre deosebire de transform: translate3d sau opacity, care sunt procesate direct de placa video (GPU), mișcarea fundalului rulează parțial pe procesor (CPU). Dacă aplici animația asta pe un element uriaș care acoperă tot ecranul (de exemplu, pe un div de 100vh și 100vw) și ai și mult text deasupra, pe telefoanele mai vechi s-ar putea să simți un mic lag sau drop de frame-uri.
Pentru elemente mari, folosește culori mai puțin contrastante ca să nu se vadă eventualele sacadări, sau limitează animația doar pe desktop unde puterea de calcul nu e o problemă.
Voi cum abordați animațiile de genul ăsta în proiectele de zi cu zi? Tot pe CSS pur mergeți sau aruncați direct un Framer Motion în package.json pentru orice mișcare mică?