:after i :before

icon-before

Pseudo selektory :before i :after służą odpowiednio do umieszczania kontentu przed i za danym elementem.

Stosuje się je z właściwością content, za pomocą której wstawia się do dokumentu dodatkowy kontent. W praktyce za pomocą tych prostych poleceń można dokonywać prawdziwych czarów. Tym właśnie będziemy się dzisiaj zajmowali. Czarowaniem. Prawie.


Podstawowa składnia użycia takich pseudo selektorów ma postać:

HTML:
jestem super snow manem
CSS:
#akapit:before {
    content:'☃ ';
}

Dam nam w rezultacie coś takiego:

☃ jestem super snow manem

czyli po prostu wstawia naszego „super ice-mana” przed akapit P. Proste.

Shadow DOM

Nie, nie. To żadna wersja DOOMA w której poruszamy się Mario-Ninja.

Wstawiony do w powyższy sposób content należy do tak zwanego Shadow DOM (chwytliwa nazwa :).
Z czym to się je? Istnieje sobie coś takiego jak DOM, czyli drzewo dokumentu.
Dzień w dzień większość z nas bada takie drzewa za pomocą Firbuga czy podobnych narzędzi. Istnieje też Shadow DOM, czyli to co jest renderowane. Pseudo elementy należą właśnie do Shadow DOM. Są renderowane przez przeglądarkę, ale nie istnieją w fizycznym DOM. Najłatwiej przekonać się o tym we wspomnianym Firebugu. W poniższym przykładzie zbadaj ostylowany element, a zobaczysz, że nie będziesz w stanie „złapać” contentu :before.

Wymądrzać się nie będę. Jeżeli interesuje was ten temat, zapraszam tutaj: http://glazkov.com/2011/01/14/what-the-heck-is-shadow-dom/

Różne podejście przeglądarek do pseudo elementów

Warto zauważyć, że nie wszystkie przeglądarki pozwalają jednako używać pseudo selektorów.
Dla przykładu w Firefoxie możemy ich używać tylko z tagami „otwartymi” czyli takimi, które w normalnych warunkach pozwalają wstawiać content w swoje wnętrze. Tak więc div, p, a czy podobne zadziają, natomiast input, hr, br i podobne już nie.
W chromie sytuacja wygląda nieco inaczej. Tam bez problemu możemy używać pseudo selektorów z każdym elementem na stronie. Jeżeli wykorzystamy je dla elementów formularza łącząc je z właściwością -webkit-appearance:none;, wtedy możemy bez problemu nadawać formularzom dowolny wygląd.
http://lab.simurai.com/umbrui/ (tylko dla chrome)

Czym różni się ::before od :before?

Właściwie niczym. Podwójny dwukropek został wprowadzony w CSS3 jako rozróżnienie pseudo selektorów od pseudo klas. Jaka jest różnica między tymi dwoma rzeczami? Pseudo klasy służą do określania stanów elementów (np. :hover, :focus itp). Pseudo elementy służą do wyłapywania elementów (np. :first-line, :nth-of-type). W CSS2 nie było rozróżnienia między obydwoma typami i mogło to nieco mylić. W CSS3 naprawiono ten błąd.
W praktyce używa się i pewnie jeszcze przez jakiś czas używać się będzie pojedynczych kropek, gdyż część przeglądarek (zgadnijcie jakie :) nie obsługuje podwójnego dwukropka.

Używanie atrybutów

Ciekawą możliwością jest użycie dla właściwości content funkcji attr(X), która pobiera dany atrybut z elementu:

a:after{
    content: " [" attr(href) "] ";
}

Dzięki tej konstrukcji za każdym linkiem na naszej stronie zostanie wpisany jego adres umieszczony między kwadratowymi nawiasami (bardzo przydatna sprawa jeżeli chodzi o drukowanie stron).

Technika ta jest bardzo przydatna, jeżeli połączymy ją z atrybutami HTML5 data-….:

Stylowanie :before i :after

Dzięki możliwości stylowania wstawionych rzeczy, selektory te można wykorzystać do o wiele ciekawszych rzeczy niż tylko wstawianie śnieżnych ludzi. Powyższy przykład to tylko jedno z miliona zastosowań.
Domyślnie wstawiany content jest typu „inline”, dlatego aby sensownie nadawać mu wygląd należy zmienić ten typ poprzez nadanie display:block.
Jeżeli stylowany element ma pozycjonowanie relatywne, wtedy możemy zastosować pozycjonowanie absolutne, które będzie odnosić się do pozycji stylowanego elementu (czyli tak samo jak zwykle). Oczywiście działają tutaj wszystkie właściwości takiego pozycjonowania – width:100% rociąga wstawiany pseudo content na szerokość stylowanego elementu, height:100% rociąga wysokość itp. Warto nie zapominać też, że możemy pozycjonować względem każdego boku :)

Zanim jednak przejdziemy do ciekawszych przykładów, warto wspomnieć coś na temat ukochanego IE. Niestety IE w wersji < 9 nie za bardzo radzi sobie z pseudo elementami, które są wyświetlane blokowo. Ogólnie im bardziej skomplikowane stylowanie (szczególnie połączone z hover) tym mniejsza szansa, że IE dobrze to wyświetli. Często gęsto sytuację poprawia użycie właściwości zoom:1, ale bardzo często trzeba po prostu się pogodzić z faktem, że niektórzy ludzie wolą po prostu oglądać „mało piękne” strony.Polecam też zapoznać się z wątkiem na stronie http://stackoverflow.com/questions/4181884/after-and-before-css-pseudo-elements-hack-for-ie-7 i polecanymi tam bibliotekami IE7/8. Nie zawsze uratują nam życie, ale są bardzo pomocne.

:before i :after dla spritów

Before i after dla spritów – technika, którą pokazałem tutaj. Wystarczy pseudo element pozycjonować absolutnie względem relatywnego elementu „rodzica” dodatkowo ograniczając mu wymiary, tak by wyświetlany był tylko dany fragment tła.

.icon-button {
     position: relative;
}

.icon-button:before { /* wycinek tła */
     content:"";
     display:block;
     background: url(...) 10px 20px no-repeat;
     overflow:hidden;
     width:30px;
     height:40px;
     position:absolute;
     top:5px;
     left:5px;
}

Wyróżnianie zewnętrznych linków

W CSS możemy skorzystać ze sprawdzania atrybutów. W połączeniu z :before daje nam to możliwość stylowania poszczególnych elementów – np linków, które prowadzą „na zeenątrz”:

a[href^="http"]:before {
    content:"";
    background:url(http://cdn1.iconfinder.com/data/icons/CrystalClear/16x16/actions/window_new.png);
    display:inline-block;
    width:16px;
    height:16px;
    margin-right:5px;
    vertical-align:middle;
}

Oczywiście to tylko prosty przykład. Inwencję pozostawiam dla was :)

Separatory w menu

Bardzo często robimy menu na listach. Aż prosi się, by tak częste kreski oddzielające poszczególne pozycje były tam umieszczane za pomocą :before, :after

nav li {
   padding-right:3px;
}

nav li:after {
   content:"";
   display:block;
   position:absolute;
   right:0;
   top:0;
   height:100%;
   width:3px;
   background:url(.....) no-repeat;
}

nav li:last-of-type {
   display:none;
}

Efekty świetlne na guzikach

Jak wspomniałem wcześniej, jeżeli wstawiany pseudo content ma pozycjonowanie absolutne, a element pozycjonowanie relatywne, wtedy width:100% i height:100% rozciągają wstawiany content na szerokość elementu. Możemy także pozycjonować względem każdej ze stron (top; right; bottom; left;). Jeżeli będziemy pozycjonować równocześnie względem każdej z nich, wtedy wymiary elementu także zostaną rozciągnięte na 100%.
Dzięki tym sztuczkom w łatwy sposób możemy uzyskać dodatkowe efekty:

Dodatkowe przykłady

Tak naprawdę można by tutaj wyliczać setki przykładów. Ale nie ma sensu wynajdywać koła na nowo. Poniżej zamieściłem kilka linków z artykułami, w których autorzy odwalili kawał dobrej roboty:

http://html5doctor.com/css3-pseudo-classes-and-html5-forms/
http://css-tricks.com/pseudo-element-roundup/
http://anton.trollback.se/shine-effect/
http://webdesign.tutsplus.com/tutorials/site-elements/orman-clarks-chunky-3d-web-buttons-the-css3-version/
http://tympanus.net/codrops/2011/11/07/animated-buttons-with-css3/
http://nicolasgallagher.com/css-drop-shadows-without-images/demo/
http://hellohappy.org/css3-buttons/