CSS transformacije u ravni
CSS transformacije predstavljaju geometrijsku promenu izgleda elemenata. Možemo transformisati elemenate bilo kog tipa - sliku, tekst, tabele... Da vidimo za početak koje transformacije su nam na raspolaganju:
- translacija - služi za prosto pomeranje elementa
- rotacija - služi za rotaciju elementa
- skaliranje - služi za promenu veličine elementa
- deformacija - služi za krivljenje elementa
Sa ove četiri transformacije možemo proizvesti različite efekte. Najpre ćemo ih savladati u najjednostavnijem obliku, kao 2D transformacije.
To znači da kada pričamo o translaciji, ona će se odnositi samo na pravce levo-desno i gore-dole. Isto bi važilo za rotaciju, koja će najpre biti samo u pravcu kazaljke na satu ili suprotnom.
Neverovatno da je za sve ove stvari zadužen jedan jedini CSS atribut (uz "asistenciju" još jednog):
transform | Transformacija CSS elementa |
transform-origin | Definisanje referentne tačke u odnosu na koju se vrše transformacije |
Referentna tačka
Pre nego što navalimo na transformacione funkcije, trebalo bi da se upoznamo sa pojmom referentne tačke. U pitanju je "tačka porekla" u odnosu na koju se transformacije obavljaju. Referentna tačka je uvek odgovor na pitanje "u odnosu na šta?" kada se govori o transformacijama.
Dakle, kada se element pomera, pomera se u odnosu na referentnu tačku. Kada se rotira, rotira se oko referentne tačke. Referentnu tačku je moguće definisati korišćenjem atributa transform-origin.
transform-origin: [horiz]
transform-origin: [horiz] [vert]
Ovaj atribut koristi isti način pozicioniranja kao background-position. Zadaje se jedna ili (češće) dve vrednosti koje označavaju položaj tačke po horizontali i vertikali. Ako se druga vrednost ne navede, podrazumeva se center. Moguće vrednosti za horizontalnu koordinatu su:
- left - leva ivica elementa
- center - sredina po horizontali
- right - desna ivica elementa
- [metrika] - bilo koja vrednost koja označava X koordinatu
- [procenat] - relativna vrednost u odnosu na dimenzije elementa po horizontali
Za poziciju po vertikali:
- top - gornja ivica elementa
- center - sredina po vertikali
- bottom - doanj ivica elementa
- [metrika] - bilo koja vrednost koja označava Y koordinatu
- [procenat] - relativna vrednost u odnosu na dimenzije elementa po vertikali
Ako zadajemo metričke ili procentualne pozicije, treba da znamo da vrednosti mogu "prevazići" dimenzije elementa ili biti negativne. Tako možemo smestiti referentnu tačku van samog elementa.
Inače, ako je ne definišemo, referentna tačka se nalazi u centru elementa.
Primeri zadavanja referentne tačke
transform-origin: center;
transform-origin: right bottom;
transform-origin: 50% 20%;
transform-origin: 10px 10px;
Transformacione funkcije
Mnogo lakše ćete razumeti transformacije ako ih posmatrate isključivo kao "specijalni efekat", a ne kao pravu promenu elemenata. Na primer - kako god da transformišemo elemenat, on neće uticati na ostale elemente - ni veličinom, ni poziciojom.
Ovakav način rada dosta podseća na relativno pozicioniranje elemenata. Elementi se izmeštaju u odnosu na svoju originalnu poziciju, ali web čitač "uračunava" upravo tu poziciju (iza elementa ostaje "rupa") kada se određuje pozicija ostalih elemenata.
Transformacije su praktično samo "slika". Nemojte se nadati da ćete čak i pomoću JavaScripta i DOM svojstava poput npr. offsetWidth uspeti da otkrijete novodobijenu poziciju, odnosno veličinu elementa.
Transformacije zadajemo atributom transform. Vrednost ovog atributa može biti veoma kompleksna. Postoji veliki broj transformacionih CSS funkcija i sve se one mogu navoditi unutar ovog atributa (čak i više puta). Upoznajmo se sa najosnovnijima:
translateX(x) | Translacija po X osi |
translateY(y) | Translacija po Y osi |
translate(x,y) | Translacija po X i Y osi |
rotate(a) | Rotacija za ugao A |
scaleX(s) | Promena veličine po širini za koeficijent S |
scaleY(v) | Promena veličine po visini za koeficijent V |
scale(s,v) | Promena veličine po širini za koeficijent S, odnosno visini za koeficijent V |
skewX(h) | Deformacija vertikalnih stranica po horizontali za ugao H |
skewY(v) | Deformacija horizontalnih stranica po vertikali za ugao V |
skew(h,v) | Deformacija stranica po horizontali/vertikali za ugao H, odnosno V |
Sve ove funkcije primaju parametre u obliku metrike. Za razliku od nekih drugih CSS atributa, ovde uvek moramo obavezno navesti mernu jedinicu.
Translacija
Osnovna funkcija za translaciju je translate(). Ova funkcija služi za pomeranje po X osi (levo-desno), odnosno Y osi (gore-dole). Može imati jedan ili dva parametra:
translate(x, y)
translate(x)
U varijanti sa samo jednim parametrom, vrši se translacija samo po X osi. Postoje i dve specijalizovane varijante ove funkcije, koje vrše translaciju samo po X, odnosno Y osi:
translateX(x)
translateY(y)
Parametri koji se zadaju predstavljaju metričke vrednosti. Znači da se izražavaju u nekoj jedinici mere, npr. px, em, itd... Moguće je zadati pozitivne i negativne vrednosti.
Dejstvo ove funkcije je naizgled isto što i relativno pozicioniranje elementa. Međutim, postoji jedna važna razlika: translacija izmešta element u odnosu na referentnu tačku. Ovo može da bude prilično značajno ako koristimo još neke transformacije.
Rotacija
Pomoću funkcije rotate() možemo "zavrteti" objekat za određeni ugao. Ugao može biti pozitivan ili negativan, ali pazite, smer rotacije je obrnut od onog što smo učili u trigonometriji:
- pozitivan ugao - u pravcu kazaljke na satu
- negativan ugao - suprotno od kazaljke na satu
rotate(ugao)
Ugao rotacije se zadaje kao metrika u specijalnim mernim jedinicama (koju je obavezno navesti). CSS poznaje sledeće merne jedinice za uglove:
- deg - stepeni (pun krug je 360deg)
- grad - gradi (pun krug ima 400grad)
- rad - radijani (pun krug ima 2*PI, odnosno 6.28rad)
- turn - krugovi (pun krug ima 1turn)
Na primer, prav ugao (od 90 stepeni) se u različitim mernim jedinicma zadaje:
90deg = 100grad = 1.57rad = 0.25turn
Element se rotira oko referentne tačke. Ona je inicijalno u centru elementa, ali se može definisati na nekoj drugoj poziciji atributom transform-origin, ili se sam element može izmestiti od ove tačke korišćenjem translacije.
Pazite, rotacija elementa ne podrazumeva rotaciju njegovih osa. To znači da translacija-rotacija-translacija nazad, neće dovesti element u početni položaj.
Skaliranje
Skaliranje je transformacija kojom možemo promeniti veličinu elementa. Za ovo koristimo funkciju scale(). Ova funkcija se može zadati sa jednom ili dve numeričke vrednosti.
scale(koef)
scale(horiz, vert)
Vrednosti koje se zadaju su koeficijenti, koji definišu promenu veličine. Vrednost 1 označava originalnu veličinu. Vrednosti iznad 1, predstavljaju povećanje (npr. 2 predstavlja dvostruko veću veličinu), a vrednosti između 0 i 1 predstavljaju umanjenje (npr. 0.5 je polovina veličine).
Kada se zada samo jedna vrednost, skaliranje je proporcionalno po horizontali i vertikali. Sa dva različita koeficijenta, element će se deformisati (npr. moguće ga je suziti po širini i istovremeno povećati po visini).
Ako se zadaju negativne vrednosti, dobićemo "izvrnutu" sliku elementa.
Postoje i dve specijalizovane funkcije, scaleX() za skaliranje samo po horizontali, odnosno scaleY() za skaliranje po vertikali.
scaleX(koef)
scaleY(koef)
Skaliranje se obavlja u odnosu na referentnu tačku. Recimo da mu povećavamo veličinu. To znači da ako je npr. referentna tačka u centru, element će se proširiti "na sve strane" od centra. Opet, ako se tačka postavi npr. na levoj strani, element će se "širiti" udesno.
Deformacija
Ova transformacija predstavlja efekat transvekcije, odnosno krivljenja (naginjanja) elementa u stranu. Da bismo to postigli, koristimo funkciju skew(). Kao parametri funkcije, zadaju se uglovi koliko se element "krivi". Ako se zada samo jedna vrednost, ona predstavlja deformaciju po horizontali.
skew(h)
skew(h, v)
Ugao h predstavlja krivljenje elementa po horizontali - to znači da će vertiklane ivice biti "nagnute" pod zadatim uglom (ulevo ili udesno). Na isti način, ugao v predstavlja deformisanje po vertikali, odnosno za koliko će se iskriviti horizontalne ivice (naviše ili naniže).
Postoje i specijalizovane funkcije koje možemo koristiti samo za horizontalu, odnosno vertikalu:
skewX(h)
skewY(v)
Ako kod horizontalnog krivljenja zadamo pozitivan ugao, vertiklane stranice će se nagnuti u pravcu suprotnom od kazaljke. Sa druge strane, kod vertiklanog krivljenja pozitivan ugao znači da će se horizontalne stranice nagnuti u pravcu kazaljke na satu.
Da li će se transformisani element "pomeriti" levo ili desno kod horizontalnog krivljenja, i da li će se pomeriti gore ili dole kod vertiklanog krivljenja, zavisi od pozicije referentne tačke. Možemo reći da se elemenat pomera od referentne tačke, koja predstavlja fiksnu tačku elementa.
Primeri transformacija
/* pomeranje udesno za 150px i naviše za 20px*/
transform: translateX(150px) translateY(-20px);
/* to isto u okviru jedne funkcije */
transform: translate(150px, -20px);
/* rotiranje za 45 stepeni u pravcu kazaljke */
transform: rotate(45deg);
/* dvostruko proširenje i smanjivanje visine za pola */
transform: scale(2, 0.5);
/* krivljenje elementa udesno i naniže */
transform: skew(-15deg, 10deg);
Pogledajte i "živi" primer.
Kombinovanje transformacija
Lepota (i glavna komplikacija) atributa transform je što je moguće kombinovati više transformacija, tako što zadajemo više transformacionih funkcija, odvojenih razmakom. Ispravan način bi bio:
transform: translate(x,y) rotate(a);
Jedna od tipičnih grešaka je navođenje više transform atributa:
transform: translate(x,y);
transform: rotate(a);
Kao i za sve CSS atribute, važi pravilo da ako navedemo više puta isti atribut, računa se samo njegova poslednja verzija (u ovom slučaju bi funkcionisala samo rotacija).
Navedene funkcije nisu nezavisne jedna od druge. Dakle, ovo nije običan spisak, već lanac transformacija, koje se onda "pakuju" jedna na drugu.
Trik je u tome da se transformacije uvek "razrešavaju" od poslednje prema prvoj. Dakle, ovo su dve sasvim različite stvari:
transform: translate(x,y) rotate(a); // prvo se rotira pa se onda pomera
transform: rotate(a) translate(x,y); // prvo se pomeri pa se onda rotira
Sve se svodi na to da li se menja centar rotacije. Kada se prvo izvrši translacija, element se "izmesti" od svoje referentne tačke, što onda kasnijoj rotaciji daje veći luk.
Kombinovane transformacije
/* element se zarotira za 15 stepeni i takav se pomeri udesno */
transform: translate(400px,0px) rotate(15deg);
/* element se pomeri udesno, onda rotira i to pod dosta većim lukom */
transform: rotate(15deg) translate(400px,0px);
/* pomeri, zarotira i pomeri unazad - NEĆE doći na početnu poziciju */
transform: translate(-200px) rotate(45deg) translate(200px);
/* znači, to što smo uradili NIJE ISTO što i */
transform: rotate(45deg);
/* ovako se elementu prvo promeni veličina, a onda se zarotira */
transform: rotate(35deg) scale(0.7, 1.6);
/* ovde se prvo zarotira, a onda ga promena veličine skroz deformiše */
transform: scale(0.7, 1.6) rotate(35deg);
Pogledajte i "živi" primer.
Redosled primene CSS atributa
Trebalo bi da zapamtimo da se transformacije primenjuju na kraju. Web čitač prvo reguliše izgled po svim ostalim CSS pravilima i kada sve lepo uklopi, tek onda izvrši još i transformacije.
Ovo može da dovede do pomalo neprijatnih iznenađenja. Na primer, kada dodamo efekat senke na objekat, koji bi trebalo da pruži utisak da "svetlo" dolazi iz određenog pravca, a onda zarotiramo taj objekat, senka neće "ostati" onako kako smo zamislili, već će se zarotirati zajedno sa objektom.
Isto tako, nemojte misliti da posle transformacije možete promeniti pozicuju referentne tačke, za neku buduću transformaciju koju biste dodali npr. pomoću JavaScripta. Web čitač obavlja transformacije uvek tako što prvo uračuna poziciju referentne tačke, pa tek onda lančano izvede sve transformacije, kada god da su zadate.
Nasleđivanje transformacija
Transformacije utiču na element, ali i na sve njegove podelemente. Potpuno je nebitno kako su elementi pozicionirani - apsolutno ili fiksno, jedino što je bitno da u HTML hijerarhiji pripadaju transformisanom elementu.
Potom i te podelemente možemo dodatno transformisati, čime se ta transformacija nadodaje na onu koju su nasledili od nadređenog elementa.
Nasleđivanje transformacije
Ako imamo HTML u kome se blok klase "mali" nalazi unutar bloka klase "veliki", svaka transformacija koju uradimo nad blokom "veliki" biće izvedena i nad njemu podređenom bloku "mali".
<div class="veliki">
<div class="mali">
</div>
</div>
Recimo da se u CSS-u definiše rotacija velikog bloka za 45 stepeni, samim tim će biti rotiran i blok "mali". Međutim, onda, nad unutrašnjim blokom, možemo izvršiti rotaciju u suprotnom smeru čime bismo ga doveli u "normalan" položaj.
.veliki {
transform: rotate(45deg);
}
.mali {
transform: rotate(-45deg);
}
Pogledajte i jedan jednostavan primer rotiranja bloka unutar bloka.
Možete pogledati i par praktičnih primera - kako napraviti vertikalnu "karticu" i trakicu u uglu ekrana.
- Mozilla Developer Network, Transform-function
- D. Storey (2012): Pro CSS Animation, Apress, New York