W końcu udało mi się ukończyć nową wersję mojej strony (z tak często i gęsto przesuwanym terminem końcowym - teoretycznie wszystko miało być zrobione do końca zeszłego roku) oraz uaktualnić portfolio (które wisiało nieruszane od roku). Z tej okazji postanowiłem wrzucić dosyć lekki wpis związany z pewnym elementem, który użyłem w nowej wersji.

Na poprzedniej stronie domowej obrazki miały graficzną ramkę i cień. Fuj, przecież to można zrobić w CSS! To akurat nie jest żadnym problemem. Ale może by tak się trochę bardziej wysilić i zrobić na przykład swoją słitaśną focię w najnowszym CSS3? Efekt dwóch zdjęć, jedno na drugim, oba spięte spinaczem do papieru. Wiele razy motyw ten pojawiał się na stronach, niestety zawsze jako grafika. Czy da się uzyskać taki efekt w samym CSS3? Ależ oczywiście!

Do czego dążymy

Fotka 0

Po lewej widać moją fotkę z wyżej wspomnianym efektem, jako zdjęcie. Robione w Photoshopie? Nie bardzo - to screen zdjęcia ze strony głównej (Firefox 4.0), gdzie jedyną grafiką jest sama fotka, a wszystko inne to efekt uzyskany za pomocą CSS. Koniec gadania, zabierzmy się za rozłożenie tego na czynniki pierwsze, bo jak się okazuje zrobienie takiego bajeru jest bardzo proste.

Szkielet HTML

Do szczęścia wystarczy nam poniższe kilka tagów HTML:
<div class="aboutImg">
	<span></span>
	<img src="./img/andrzejmazur.jpg" alt="Andrzej Mazur" />
</div>

W tym przypadku <div class="aboutImg"> jest kontenerem, w środku którego dokonuje się magia. Pierwsza linijka wewnątrz naszego kontenera to element <span>, z którego automagicznie wykreujemy nasz spinacz do papieru (oczywiście można było użyć <p> lub <div> zamiast <span>). Druga linijka to nasz obrazek. Prawda, że proste?

CSS - efekt zdjęć z polaroida

Fotka 1 Zacznijmy od zwykłego zdjęcia, a potem nadajmy mu odpowiednie style:
.aboutImg img {
	-moz-transform: rotate(-8deg);
	-webkit-transform: rotate(-8deg);
	-moz-box-shadow: 0px 1px 6px #666;
	-webkit-box-shadow: 0px 1px 6px #666;
	border: 4px solid #fff;
	background: #fff;
	padding: 4px;
	float: left;
}

Fotka 2
Trochę się tu dzieje. Najpierw używamy transform (użyte są przedrostki dla Mozilli i Webkita, czyli dla przeglądarek Firefox, Chrome i Safari), by obrócić nieco obrazek - dokładnie o 8 stopni w stronę przeciwną do ruchu wskazówek zegara. Atrybutem box-shadow nadajemy odpowiedni cień. Do tego biały border, background także biały, padding i float. Po lewej efekt, który uzyskaliśmy dzięki tym kilku linijkom w CSS.
Zabierzmy się teraz za drugie zdjęcie wystające zza pierwszego. Użyjmy do tego celu naszego kontenera, by nie dodawać zbędnych tagów:
.aboutImg {
	float: left;
	position: relative;
	-moz-transform: rotate(6deg);
	-webkit-transform: rotate(6deg);
	-moz-box-shadow: 0px 1px 6px #666;
	-webkit-box-shadow: 0px 1px 6px #666;
	background: #fff;
}
Fotka 3

Nadajemy styl position: relative, by operować wewnątrz kontenera. Używamy tu także podobnych efektów jak w przypadku pierwszego zdjęcia: transform obraca nam element tym razem o 6 stopni zgodnie z ruchem wskazówek zegara, natomiast box-shadow jest identyczny jak ten użyty wcześniej. Do tego dochodzi białe tło i float. Po lewej prezentuje się efekt dotychczasowych naszych starań.

CSS - spinacz biurowy

Zabierzmy się teraz za gwóźdź programu, a dokładniej rzecz ujmując za spinacz. Pamiętacie strukturę HTML spinacza? To pojedynczy element <span>. Do ostylowania spinacza użyjemy pseudoelementów :before i :after. Pierwszy dodaje jakąś treść przed danym elementem, drugi bezpośrednio za nim w strukturze DOM. Skorzystajmy z pierwszego i nadajmy mu odpowiednie style CSS:
.aboutImg span:before {
	display: block;
	content: '';
	position: absolute;
	top: -15px;
	right: 30px;
	width: 14px;
	height: 54px;
	z-index: 1;
	border: 2px solid #999;
	-moz-transform: rotate(4deg);
	-webkit-transform: rotate(4deg);
	-moz-box-shadow: 1px 1px 1px #555, inset 1px 1px 1px #555;
	-webkit-box-shadow: 1px 1px 1px #555, inset 1px 1px 1px #555;
	-moz-border-radius: 10px;
	-webkit-border-radius: 10px;
}

Fotka 4 Nadajemy elementowi display: block, zawartość (content - wymagany dla :before) ustawiamy na pusty tekst, definiujemy odpowiednio długość, szerokość, absolutną pozycję, by za chwilę zdefiniować top i right, a także z-index, by element nie był przesłonięty przez zdjęcie, tylko widoczny w całej okazałości. Następnie nadajemy mu border, oraz to, co tygryski lubią najbardziej, czyli obracamy przy użyciu transform o 4 stopnie, ustawiamy odpowiedni box-shadow (podwójnie - jako cień normalny, widoczny na zewnątrz, a także cień wewnętrzny) oraz ustawiamy border-radius, dzięki któremu element uzyska efekt zaokrąglonych rogów. Efekt po lewej.

Ok, jednak to jedynie prostokąt z zaokrąglonymi rogami. Spinacz powinien spinać zdjęcia, czyli chować się z drugiej strony. Z pomocą przychodzi nam pewna sztuczka, czyli mały biały kwadracik przysłaniający nasz prostokąt w odpowiednim miejscu, dzięki czemu uzyskuje się efekt spinacza - z jednej strony się kończy, a z drugiej wchodzi za zdjęcia. Odpowiada za to następujący kod CSS podpięty pod pseudoelement :after:
.aboutImg span:after {
	display: block;
	content: '';
	position: absolute;
	top: -8px;
	right: 25px;
	width: 8px;
	height: 8px;
	background: #fff;
	z-index: 2;
}

Ustawiamy display: block, pustą treść, pozycję na absolutną, definiujemy położenie za pomocą top i right, a także szerokość, wysokość i białe tło. Na koniec pozostaje nam jedynie dodać z-index, by na pewno przesłonił on nasz spinacz. Tak prezentuje się efekt ostateczny naszych zmagań (pokazany na samym początku wpisu):
Fotka 0
CSS3 w akcji zobaczyć można na stronie głównej, lub tu: DEMO.
Uwaga: należy pamiętać, że odpowiednie ustawienie białego elementu przysłaniającego spinacz, a także dobranie odpowiednich cieni czy ułożenia samego spinacza, to kwestia indywidualna, która zależy na przykład od wielkości zdjęcia. Nie jest to także rozwiązanie idealne, tzw "pixel perfect", ponieważ kombinujemy i tak ustawiamy odpowiednie wartości, by uzyskać zadowalający efekt.
PS. Podziękowania za ładne wyjaśnienie via email użycia pseudoelementów :before i :after z odpowiednim przykładem upraszczającym mój pierwotny kod kieruję do Kacpra. Teraz wygląda to znacznie ładniej.