CSS3 – transitions

CSS3 coraz śmielej zagląda do naszych przeglądarek. Widząc nowe wydania Firefoxa, Chrome’a czy IE (w dziewiątej wersji) wypada tylko uśmiechnąć się od ucha do ucha, bo wygląda na to, że — po 10 latach męki — będziemy mogli zapomnieć o czymś takim jak IE6, komentarzach warunkowych i wspieraniu się JavaScriptem w najbardziej trywialnych przypadkach.

Postanowiłem więc — jeśli wszystko pójdzie według mojego planu — opisać najważniejsze składniki CSS3 bazując na przykładach. Zacznijmy od transitions, które pozwalają nam czasem zapomnieć o jQuery’owym animate czy po prostu window.setTimeout.

Do czego służą CSS3 transitions?

Transitions to specjalne własności w CSS, dzięki którym możemy ustawić, że zmianie jakieś właściwości (np. marginesu lewego) towarzyszyć będzie animacja, zamiast błyskawicznej modyfikacji wartości z x na y. Przykładowo, jeśli ustawimy (bezpośrednio w JS bądź poprzez zmianę klasy/właściwości w CSS) wartość height i zdefiniujemy wcześniej odpowiednie transition, zmiana wysokości zostanie animowana (czyli element będzie się wydłużał albo skracał do podanej wartości). To samo tyczy się np. marginesów czy przeźroczystości – ustawiasz transition na jakimś elemencie, ktoś zmienia opacity z 0.1 na 1 i obserwujesz, jak zmiana tej wartości następuje stopniowo, od 0.1 do 1, w ciągu jakiegoś (zdefiniowanego przez nas) czasu.

Teoria

Powiedzieliśmy sobie, że aby zaobserwować jak to działa, należy ustawić jakieś transition na danym elemencie. Jak to się robi w teorii? Przyjmijmy, że działamy na <p/>:

p {
	transition: height 1s ease-out;
}

W ten sposób mówimy przeglądarce, że jeśli ktokolwiek ustawi nową wartość height dla jakiegokolwiek elementu <p/>, to zmianie tej ma towarzyszyć 1-sekundowa animacja (bądź przejście) typu ease-out. Czyli — dla przykładu — robiąc, dajmy na to, w jQuery:

$("p").css("height", 100);

Przeglądarka odpowiednio zareaguje, zmieniając w ciągu sekundy wysokość każdego elementu p z dotychczasowej na 100 pikseli (jako że taką wartość podaliśmy wyżej).

Podobnie byłoby, gdybyśmy mieli taki kod:

p {
	transition: height 1s ease-out;
}
.odpalTransition {
	height: 100px;
}
$("p").addClass("odpalTransition");

Powyżej dodajemy każdemu z <p/> nową klasę odpalTransition. Jej nazwa jest mało reprezentatywna, ważne jednak, że przy okazji zmieniamy wysokość. W ten sposób zadziała transition, zdefiniowany na początku dla każdego akapitu.

Przeglądarka przeglądarce nierówna

Musisz wiedzieć, że przeglądarki zaczęły implementować CSS3 transitions dość dawno temu, a specyfikacja z W3C ma nadal status draftu, dlatego wprowadzono tę opcję z odpowiednim prefiksem. Dla Chrome i Safari jest to -webkit-transition, dla Firefoxa -moz-transition, a dla Opery -o-transition. Z reguły wymienione przeglądarki nie rozumieją czystego transition. Aby zapewnić dla nich wsparcie należy więc aż cztery razy umieścić odpowiednią regułkę. Na naszym przykładzie będzie wyglądało to tak:

p {
	-webkit-transition: height 1s ease-out;
	-moz-transition: height 1s ease-out;
	-o-transition: height 1s ease-out;
	transition: height 1s ease-out;
}

Witaj w świecie cross-browserowych CSSów trzy!

Jak widzisz, w transition: podaliśmy trzy wartości: height, 1s i ease-out. Pierwsza to oczywiście własność, na której zmianę ma zareagować przeglądarka. Może być ich kilka:

p {
	-webkit-transition: height 1s ease-out, width 1s ease-out;
	-moz-transition: height 1s ease-out, width 1s ease-out;
	-o-transition: height 1s ease-out, width 1s ease-out;
	transition: height 1s ease-out, width 1s ease-out;
}

Można też podać all:

p {
	-webkit-transition: all 1s ease-out;
	-moz-transition: all 1s ease-out;
	-o-transition: all 1s ease-out;
	transition: all 1s ease-out;
}

Tutaj, niezależnie od tego, jaką własność będziemy chcieli ustawić, brałzer spróbuje włączyć zdefiniowany transition.

Czas to z kolei jakaś część sekundy, może być to np. 100 milisekund (wyrażone przez 0.1s):

p {
	-webkit-transition: height 0.1s ease-out, width 0.1s ease-out;
	-moz-transition: height 0.1s ease-out, width 0.1s ease-out;
	-o-transition: height 0.1s ease-out, width 0.1s ease-out;
	transition: height 0.1s ease-out, width 0.1s ease-out;
}

Jeśli chodzi o typ animacji, mamy do wyboru:

Jak zapewne zauważyłeś, typy animacji są wyliczane na podstawie krzywych Béziera. Odpowiednie parametry każdej z nich znajdziesz w specyfikacji.

Kojarzysz zapewne CSSowy border, prawda? Skrótowiec wygląda tak:

border: 1px solid #000;

Dzięki temu nie musimy pisać w ten sposób:

border-style: solid;
border-color: #000;
border-width: 1px;

Podobna sytuacja jest z transitions. Możemy użyć skróconego zapisu:

transition: height 1s ease-out;

Aczkolwiek można też odwołać się bezpośrednio do każdej z pod-własności. W naszym przypadku będzie to wyglądać tak:

transition-property: height;
transition-duration: 1s;
transition-timing-function: ease-out;

Nie jest to jednak zbyt efektywne, wyobraź sobie, że musiałbyś napisać coś takiego dla każdej z przeglądarek (-moz, -webkit itd.). W sumie – 12 linijek!

Przy okazji, jest jeszcze transition-delay, który oznacza opóźnienie w wykonaniu się animacji:

transition-property: height;
transition-duration: 1s;
transition-timing-function: ease-out;
transition-delay: 1s;

Powyżej będzie to jednosekundowe opóźnienie.

Podsumowując, używając skrótowca, wzór pisania transitions wygląda tak:

[-moz,-webkit,-o]transition: własność czas_trwania typ opóźnienie

Praktyczny przykład

Czas na jakiś praktyczny przykład wykorzystania transitions. Zróbmy więc prosty accordion po najechaniu myszką na odpowiedni nagłówek. Oto przykładowy kod HTML:

<h1>Poczytaj o:</h1>
<ul>
	<li>
		<h2><a href="#more">CSS3</a></h2>
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque placerat molestie mauris, ac mollis neque ultricies sit amet. Quisque ligula nisi, facilisis in molestie sit amet, blandit at felis.</p>
	</li>
	<li>
		<h2><a href="#more">Transitions</a></h2>
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque placerat molestie mauris, ac mollis neque ultricies sit amet. Quisque ligula nisi, facilisis in molestie sit amet, blandit at felis.</p>
	</li>
	<li>
		<h2><a href="#more">Czymś innym</a></h2>
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque placerat molestie mauris, ac mollis neque ultricies sit amet. Quisque ligula nisi, facilisis in molestie sit amet, blandit at felis.</p>
	</li>
</ul>

Mamy więc prostą listę nieuporządkowaną, a wewnątrz trzy nagłówki oraz po jednym akapicie, które powinny być ukryte. Nasz cel to zrobić tak, by po najechaniu na nagłówek wysokość oraz przeźroczystość sąsiadującego akapitu zmieniły na jakieś dodatnie wartości, aby był on widoczny. Ustawmy więc odpowiednie style:

body {
	font-family: "Helvetica", Arial;
}

h1 {
	font-size: 100%;
}

h2 {
	font-size: 90%;
	margin: 0;
	padding: 0;
	margin-bottom: 10px;
	display: inline-block;
}

li {
	padding-bottom: 5px;
	max-height: 150px;
}

li p {
	margin: 0;
	padding: 0;
	color: #fff;
	background: #cc0000;
	overflow: hidden;
}

Chyba nie zrobiliśmy wszystkiego, bo akapity nie są ukryte i nic się nie dzieje. Ukryjmy je więc:

li p {
	margin: 0;
	padding: 0;
	color: #fff;
	background: #cc0000;
	overflow: hidden;
	height: 0;
	opacity: 0;
}

opacity i height ustawione na zero załatwiły sprawę. Pora obsłużyć nasz hover na nagłówku h2:

li h2:hover + p {
	height: 50px;
	opacity: 1;
}

Oznacza to, że jeśli ktoś najedzie myszką na h2 silnik CSS poszuka sąsiadującego z nim elementu p i ustawi jego wysokość (height) na 50px oraz przeźroczystość (opacity) na 1.

CSSy wyglądają teraz tak:

body {
	font-family: "Helvetica", Arial;
}

h1 {
	font-size: 100%;
}

h2 {
	font-size: 90%;
	margin: 0;
	padding: 0;
	margin-bottom: 10px;
	display: inline-block;
}

li {
	padding-bottom: 5px;
	max-height: 150px;
}

li p {
	margin: 0;
	padding: 0;
	color: #fff;
	background: #cc0000;
	overflow: hidden;
	height: 0;
	opacity: 0;
}

li h2:hover + p {
	height: 50px;
	opacity: 1;
}

Całość działa dość dobrze. Nie ma jednak animacji! Musimy dodać obsługę transitions. Jak widzimy, w selektorze li h2:hover + p zmieniamy wysokość i przeźroczystość. Jak powiedzieliśmy też wcześniej, transitions mają za zadanie powiedzieć przeglądarce, by w razie zmiany odpowiednich wartości, zmieniła je krok po kroku, używając jakiejś animacji bądź — to chyba będzie lepsza nazwa — efektu przejścia z jednej wartości do drugiej.

Tak więc, jako że zmieniamy te wartości dla akapitu p, dodajmy odpowiedni transition właśnie tam:

li p {
	margin: 0;
	padding: 0;
	color: #fff;
	background: #cc0000;
	overflow: hidden;
	height: 0;
	opacity: 0;
	-webkit-transition: opacity 0.5s ease-out, height 0.5s ease-out;
	-moz-transition: opacity 0.5s ease-out, height 0.5s ease-out;
	-o-transition: opacity 0.5s ease-out, height 0.5s ease-out;
	transition: opacity 0.5s ease-out, height 0.5s ease-out;
}

Kilka linijek, a ile radości! Ustawiliśmy właśnie, by włączało się półsekundowe przejście typu ease-out, jeśli ktokolwiek, kiedykolwiek zmieni właściwość opacity bądź height dla elementów <p/>.

Podsumowanie

CSS3 transitions to bardzo ciekawe narzędzie, które potrafi zaoszczędzić nam brudzenia sobie rąk JavaScriptem. Wszystko działa pod Firefoxem 4, Chrome 1+, Safari 3.2+ i Operą 10.5+.

Liczę, że wkrótce pojawią się tu kolejne artykuły na temat nowych ficzerów, bo, jak widzicie, jest o czym pisać.

Komentarze

1

Miałem ten sam temat zapisany w Instapaper na później, ale nie po naszemu. A tutaj niespodzianka. Dzieki, na pewno skorzystam :)

singles
2

Żeby tylko ten IE9 można było zainstalować pod WindowsXP, niestety rzeczywistość bywa brutalna.

manolo
3

Zauważ przecinek przed ostatnią wartością (width)!

Chyba chodziło o “po ostatniej wartości”? W podanych przykładach przecinek jest po każdej wartości, a więc także po ostatniej, co niekoniecznie jest intuicyjne, bo gdy wymieniona jest jedna tylko właściwość, to nie ma po niej przecinka.

4

@TPReal – mały update, poprawiłem plus zauważyłem w Operze kolejny bug. Zrobiłem na początku mega skrótowca, jednak okazuje się, że nie działa on ze wszystkimi browserami, więc musiałem dla każdego property robić oddzielnie po bożemu.

5

Bardzo przydatny wpis – pamiętać należy jednak, aby efektów tych używać np. do galerii lub innych mniej istotnych miejsc. W menu takie skoki są na pewno nie na miejscu… Efekt: “pińset” różnych wersji CSSa pod każdą przeglądarkę, aby to jakoś wyglądało – niestety z nowościami tak to już jest… Ale CSS3 to dobra droga :)

6

Bardzo ciekawe, jak zwykle bardzo prosto i przejrzyście opisane, czekam na kolejne wpisy w tym temacie.

7

@procek – lepsze to niz hackowanie IE6. Raczej kwestia czasu kiedy zostaną usunięte prefiksy (oby).

8

Nie wiem dlaczego, ale na mojej stronie nie działa transition pod Operą. Walczyłem już z tym miesiąc temu, ale się poddałem. Teraz gdy zobaczyłem działający przykład, to znowu walczę, żeby poprawić po Operkę i nadal nic.
-webkit-transition: padding .15s linear, -webkit-box-shadow 0.15s linear;
-moz-transition: padding 0.15s linear, -moz-box-shadow 0.15s linear;
-o-transition: padding 0.15s linear, box-shadow 0.15s linear;
transition: padding 0.15s linear, box-shadow .15s linear;
Próbowałem użyć szczegółowych właściwości, ale nic to nie dało.

Przykład znajduje się na mojej stronie, a dokładnie to menu.

WRB
9

Animacja nie działa w Firefox 3.6.12.
W Chrome 7.0.517.44 wygląda super:)

Pharass
10

@Pharass: Firefox 3.6 nie obsługuje tego. Dopiero 4 dostanie wsparcie dla transitions.

Omawiane tutaj nowości CSSa naprawdę cieszą, bo zwalniają webdewelopera z konieczności obsługi sporej ilości spraw, na które trzeba było uważać gdy robiło się animacje z użyciem JS i to w dodatku z użyciem kilku linijek kodu. Co prawda mało kto się tym przejmuje, bo dla wielu to jQuery odwala robotę, ale jednak ktoś to musiał zaimplementować, żeby ktoś inny mógł używać. W każdym razie z CSS3 można się skupić na celu i szybko osiągnąć wymarzone efekty.

11

Niestety w pracy pod Firefoxem na iMacu nie widzę żadnych z owych transitions. Nasuwa się jedna myśl – Safari for the win ;)

Free
12

Panowie – napisane jak byk, dziala od Firefoksa 4 ;-)

@WRB – Twoje menu dziala pod Opera u mnie.. Chyba ze ma jeszcze robic cos innego o czym nie wiem.

13

Zbijcie mnie, ale skoro trzeba jeszcze obsłużyć IE przy pomocy jQuery, to lepiej od razu to zrobić dla wszystkich przeglądarek… IMO nie ma sensu tego rozdzielać.

14

Są jeszcze urządzenia mobilne zdominowane przez WebKita (tablety, iPady, iPhony, Androidy), wkrótce będzie IE9, więc tak, rób w jQuery, a za rok obudzisz się z ręką w nocniku ;-)

15

IE nie zasługuje, żeby dla niego teraz fixować przez jQuery. Niech jego użytkownicy poczują faktyczną różnicę w wyświetlaniu stron.

Można ew. na siłę wykorzystywać CSS3 Pie dla IE.

16

Zależy, polakom i tak się nie dogodzi – jeśli na urządzeniach mobilnych (typu iphone) zrobimy stronę, która będzie się zachowywała jak jakaś aplikacja (ładne przejścia itd) to wtedy zostanie się zjechanym za to że nie jest to zrobione w cocoa a wygląda jak iPhone app :) Przetestowane na własnej skórze w firmie,w której mam przyjemność pracować. Mieliśmy komentarze typu “szkoda, że nie jest to zrobiona jako aplikacja tylko zwykła strona” Ot, życie :P

Co do FF4 – sorki, czytane na szybko w pracy i nie dojrzałem :D

Free
17

@ferrante – Zakładki menu na mojej stronie powinny wysunąć się animacyjnie, tak samo jak cień z tytułu strony powinien animacyjnie zniknąć. Pod FF4, Chrome, Safari działa, ale pod Operą (WinXP, Mac, Ubuntu) nie ma animacji, bynajmniej na tych komputerach na których testowałem. Nie mam pomysłu dlaczego. Będę walczył dalej.

WRB
18

Bardzo ciekawy i przystępny artykuł. Tylko trapi mnie jedna rzecz. W tej formule “coś:hover + coś { }” nie można używać elementów class i id. Czy ktoś ma na to radę? Mam w ten sposób zagnieżdżone divy:
Div “a” jest tym, na który będę najeżdżał, a div “b” będzie zmieniał swoje height, kiedy najadę na “a”. Niestety poniższy kod nie działa:
div:hover + div {
height: 223px;
}
podobnie, jak dopisanie do divów ich nazw np. div.a….
Działa tylko taki kod:
img:hover + div {
height: 223px;
}
Ale wtedy div zmieniający wysokość szaleje. Kiedy “spływający” div dojedzie do kursora, kursor mimo woli zostaje zasłonięty przez diva i schodzi z elementu img.

Kali
19

Zapomniałem dodać, że wszystkie trzy elementy leżą na sobie tak, że div “a” jest na wierzchu, a w nim siedzą img, a następnie div “b”.

Kali
20

[…] zaokrąglanie rogów, podwójne tła, obrazkowe obramowanie czy choćby takie dobrodziejstwo jak transitions. Patrząc na to wszystko z uśmiechem na twarzy stwierdzamy, że nic nam więcej do szczęścia nie […]

21

Czy skoro w 1szym przykładzie podajesz 1s dla transision to w przykładzie jQuerowym nie powinno być ‘1000’ zamiast ‘100’ ?

22

dobra, nie wazne, zapomnij, zamotalem sie troche:D

23

[…] CSS3 – transitions […]

24

Cześć!
Przeczytałem Twój artykuł i inne w sieci i strasznie się cieszę , że rzeczy które musiałem robić w JS teraz zrobię w CSS-ie. Jak uważacie czy JS po woli umiera?? Świetnie by było gdyby w CSS3 wprowadzono funkcje czasowe tzn. zrób coś co jakiś czas i oczywiście onclick którego nie ma i nie wiem dlaczego!?
//
Mam taki problem chcę aby po najechaniu myszką height ,,rozszerzał” się w górę a nie w dół jak jest domyślnie oczywiście wszystko z transition mogłby ktoś mi to wytłumaczyć bo ten problem mnie nurtuje od dłuższego czasu.

Kamp
25

W końcu jakąś alternatywą przy tworzeniu stron a nie ciągle ta java.

26

Bardzo dobry artykuł i pomocny. Dopiero raczkuję w css3 i animacjach i tutaj moja mała prośba. Jak wykonać aby rozwinął się o 300px w prawo zaraz po wejściu na stronę (nie po kliknięciu w element czy najechaniu). Tak automatycznie rozwinął z szerokości 10px do 300px ?

Można to uzyskać w css3 i animacji ?

Dodaj komentarz

Dozwolone tagi: <blockquote>, <code>, <strong>