A stíluslapok – ahogyan azt Spányik Balázs a Websuli 6., nem véletlenül Stíluslapok címet viselő részében nagyon pontosan megfogalmazta – „képezik a jól felépített weboldal második rétegét, amely azt írja le, hogy az egyes szerkezeti és tartalmi részek miként jelennek meg, hogyan néznek majd ki a böngészőben vagy valamilyen más megjelenítő eszközön”. (Az első réteg az oldal tartalmát leíró HTML, a harmadik réteg pedig az oldal viselkedéséért felelős JavaScript.) Ugyanezen lecke Stílusanatómia alcímű részében az is kiderül, hogy „egy stílusdefiníció, amelyet a szaknyelvben gyakran CSS-szabályként is emlegetünk, alapvetően két fő részből áll: az első az úgynevezett jelölő (idegen szóval: selector), amely meghatározza, hogy az adott stílus a HTML-dokumentum mely részére fog vonatkozni; a második pedig az úgynevezett definíciós vagy deklarációs blokk, amelyet kapcsos zárójelek közé teszünk.
A deklarációs blokk tartalmával, amely nem más, mint a stílustulajdonságok és a hozzájuk rendelt értékek párosainak listája, már igen sokat foglalkoztunk leckéinkben az elmúlt bő két évben, ugyanakkor a jelölőkről, vagyis a stíluslapok azon elemeiről, amelyek azt határozzák meg, hogy az oldal mely objektumának, objektumainak stílustulajdonságait szeretnénk megadni, módosítani, szinte alig esett szó.
Természetesen azért a jelölők három legfontosabb altípusát (típus-, osztály- és azonosító jelölő) Balázs részben a már említett Stíluslapok című leckében, részben pedig két résszel később, Elemek, osztályok, azonosítók, dobozolás címen bemutatta. Természetesen azóta több jelölőtípust is használni kezdtünk a Websuli leckéiben, de ezek részletes ismertetése eddig különböző okok miatt elmaradt, ahogyan például nyelvtanulás közben is elkezdünk kifejezéseket használni anélkül, hogy az adott szófordulatok pontos felépítésének miértjeivel tisztában lennénk. Úgy gondoltuk, itt az idő, hogy egy kicsit alaposabban körülnézzünk a kapcsos zárójeleken kívül is.
Sikeresen túl a teszteken
E téma rejtett alapjait tulajdonképpen már az előző alkalommal elkezdtük letenni, hiszen hierarchikus listánk egyéni sorszámozásához jó pár olyan jelölőt használtunk, amelyekkel valószínűleg csak kevesen találkoztak eddig. Ennek egyik legfőbb oka, hogy a weboldalak kódjainak írásakor egyelőre csak kevesen engedhetik meg maguknak, hogy olyan honlapokat hozzanak létre, amelyek figyelmen kívül hagyják a látogatók igen jelentős része által favorizált Internet Explorer böngésző ismert hiányosságait. Esetünkben ez azt jelenti, hogy hiába próbálná meg valaki egyszerűsíteni a HTML-kódokat CSS2-es, pláne CSS3-as jelölők használatával, ha ez utóbbiak egy jelentős részét nem, vagy csak részben ismeri az oldal látogatóinak mintegy 40 százaléka által használt böngésző.
A www.css3.info oldalon található CSS3 Selectors Test program 41 jelölőtípus 574 különböző előfordulási formáját vizsgálja, az abszolút alaptípusoktól (CSS1) egészen a legújabb, még nem hivatalos ajánlásban megfogalmazott (CSS3) strukturális és az űrlapelem-állapot pszeudoosztályokig. A jelenleg legelterjedtebb öt böngészőből négy, a Firefox, a Chrome, az Opera és a Safari legújabb változatai, mondhatni természetesen, százszázalékos eredményt érnek el ezen a teszten, vagyis mind a 41 típus szinte minden elképzelhető előfordulását megfelelően kezelik. E tekintetben sajnos az Internet Explorer lemaradása még az átlagosnál is nagyobbnak mondható – de szerencsére ez hamarosan megváltozik. Ugyanis nagy örömünkre az Internet Explorer 9-nek már a legelső bétája is tökéletesen vette ezt az akadályt, a tesztprogram futását követően csak tiszta, zöld csíkok voltak láthatók az eredmények keretében. Ugyanezen a teszten az Internet Explorer 8 csak 20/41-es pontszámot ért el, de ez kissé csalóka, ugyanis alaposabban megnézve a részeredményeket azt láthatjuk, hogy a CSS2-es jelölők esetében a program csak két „nem igazán releváns” bakit követ el, piros háttérrel pedig csak CSS3-as jelölőket találunk a listában. (Az Internet Explorer 7-ről azért nem ildomos beszélnünk, mert a vele egykorú más böngészők sem érnének el sokkal jobb eredményt nála, azonban az ismert okok miatt a Microsoft böngészőit igencsak nehézkesen frissítik a felhasználók.)
Most pedig jöjjenek aktuális leckénk főszereplői, a stíluslapok jelölői, más szóval szelektorai!
Egyszerű jelölők
A leggyakrabban használt jelölők az úgynevezett típusjelölők. Ezek tulajdonképpen nem mások, mint a HTML-kódokban használt különböző elemek címkéi, nevei, megfosztva a kisebb-nagyobb jelektől. Vagyis ami a HTML-ben ‹div›, ‹p›, ‹table› vagy ‹b›, az a CSS-ben egyszerűen div, p, table vagy b. Ezekre nem is érdemes több szót vesztegetnünk, hiszen az elmúlt közel három évben számtalanszor volt már szó róluk, de mivel a teljességhez hozzátartoznak, így természetesen muszáj volt ezeket is megemlítenünk.
Hasonlóképpen kötelező, ám gyorsan letudható lesz az általános jelölő, vagyis a csillag karakter. Ennek a jelölőtípusnak az egyik jellegzetessége, hogy az esetek túlnyomó többségében el is hagyhatjuk, így például az elvileg hivatalos *.osztaly helyett elfogadott a .osztaly írásmód is. Az ez után a jelölő után megadott stílustulajdonságok érvényesek lesznek minden olyan elemre, amelynek az osztályneve osztaly, vagy az osztálynevei között megtalálható az osztaly is, legyen az bekezdés, felsorolás vagy táblacella. Igazából néhány nagyon ritka esetet leszámítva, az általános jelölőt csak a „szegény ember reseténél” – * {margin: 0; padding: 0; border: 0;} – szoktuk kiírni.
Ha pedig már szóba kerültek az osztályok, nem hagyhatjuk ki a két jól bevált jelölőt, az osztály- és az azonosító jelölőket sem. Előbbiek jelölésére a pontot, míg utóbbiéra a kettőskeresztet használjuk, és ahogyan azt korábban már a Websuli olvasói jól tudják, a fő különbség a kettő között, hogy amíg az osztályneveket többször is felhasználhatjuk egy oldalon belül, addig az azonosítóknak egyedieknek kell lenniük. Ez a stíluslap szempontjából például azt is jelenti, hogy amíg az osztályjelölőket kombinálhatjuk különböző típusjelölőkkel (például a p.red, li.red, td.red jelölők különböző elemekhez rendelnek különböző stílustulajdonságokat), addig az azonosító jelölők esetében ez teljesen felesleges – pontosabban zavaró –, mivel egy HTML-oldalon belül nem adhatjuk ugyanazt az azonosítót például egy ‹div›-nek és egy ‹ul›-nek, így a div#menu és ul#menu jelölők csak két különböző oldal elemeire hivatkozhatnak.
Ugyanakkor az osztályokat és/vagy az azonosítókat kombinálhatjuk egymással, így például a .red.center jelölő egy olyan elemre hivatkozik, amelynek az osztálynevei között szerepel mindkét osztálynév, vagy a div#menu.aktual csak akkor adja hozzá a megadott stílustulajdonságot a menu azonosítójú ‹div›-hez, ha annak osztálynevei között megtalálható az „aktual” is.
Jelölés attribútum alapján
Az azonosítók és az osztályok tulajdonképpen nem mások, mint az oldalelemekhez rendelt attribútumok – amelyeket többnyire azért rendelünk ezekhez az objektumokhoz, hogy a stíluslapokon egyszerűbb legyen egyes elemekre vagy elemcsoportokra hivatkoznunk. Az oldalelemeknek viszont az id és class attribútumok mellett számtalan más tulajdonsága is lehet, sőt nagyon sok olyan elem van, amelyeknek kötelező attribútumai is vannak, gondoljunk csak a hivatkozások href, vagy a képek src és alt paramétereire.
Már a CSS2-ajánlás is lehetővé tette, hogy ne kizárólag a két kiemelt attribútumra, hanem az elemek bármely más kötelező, vagy legalábbis a HTML-kódokban engedélyezett tulajdonságaira hivatkozhassunk, a CSS3 pedig további finomításokat vezet(ett) be e területen is. Korábban, egész pontosan a Websuli 14. leckéje kiegészítő részében már foglalkoztunk az úgynevezett attribútum jelölőkkel, majd miután a 26. leckében elbúcsúztunk az Internet Explorer 6-tól, „fű alatt” el is kezdtük ezeket használni, például a különböző dokumentumtípusokra mutató hivatkozások képes jelölésénél.
A legegyszerűbb attribútumjelölő nem vizsgál mást, mint hogy bizonyos elemtípusoknak létezik-e a paraméterként megadott attribútuma vagy sem. Például az img[title] jelölő csak azokhoz a képekhez rendeli hozzá az utána jövő deklarációs blokkban lévő stílustulajdonságokat, amelyeknek létezik title attribútuma, függetlenül attól, hogy annak mi a tartalma.
Természetesen nemcsak egy attribútum meglétét, hanem annak tartalmát is vizsgálhatjuk, több módon is. A legegyszerűbb vizsgálat az, amikor pontos azonosságot nézünk, vagyis azt, hogy a választott attribútum értéke megegyezik-e az általunk megadott szöveggel. Például az a[rel=”out”] jelölő azokat a hivatkozásoknak megjelenését változtatja meg, amelyek rel attribútumának az out értéket adtuk (pl. ‹a href=”#” rel=”out”›). Ennél alig bonyolultabb annak vizsgálata, hogy egy attribútum a megadott szövegrészlettel kezdődik (^=), vagy azzal végződik-e ($=). Ilyen jelölőket korábban már használtunk, hiszen ezekkel helyettesítettük a különböző hivatkozások javascriptes megjelölését, az a[href^="http://"] jelölő a külső, míg az a[href$=".pdf"] a PDF kiterjesztésű állományokra mutató hivatkozások formázásában segített konferenciánk honlapjának stíluslapján.
Ha pedig az attribútumok értékének belsejében (is) szeretnénk vizsgálódni, akkor az egyenlőségjel előtt a csillag vagy a hullámvonal karaktereket kell használnunk. Előbbinél csak az a lényeg, hogy míg a jelölőben használt szövegrészlet az attribútumon belül bárhol előfordulhat, addig a hullámvonalat választva a szövegrészletnek pontosan egyeznie kell az attribútumon belül szóközökkel elválasztott értékek valamelyikével. Erre legjobb példa a többszöri osztályhasználat. Van három bekezdésünk: ‹p class=”one”›, ‹p class=”one two”›) és ‹p class=”tone”›. A p[class=”one”] jelölő ezek közül csak az első bekezdésre lesz hatással, a p[class~=”one”] az első kettőre, a p[class*=”one”] viszont már mindháromra.
Kombinált jelölők
A különböző jelölőket kombinálni is lehet, ahogyan azt már hosszú ideje itt, a Websuliban is tesszük. Ám egészen az előző leckéig a négy lehetséges kombinálási módból mi csak egyet, a sima „utódlási” módot használtuk, amikor is olyan elemeket jelöltünk ki, amelyek egy másik elemen belül találhatók. Ez így leírva talán furcsán hangzik, de ez tulajdonképpen nem más, mint amikor például a fejlec azonosítójú ‹div›-en belül található ‹h2› elemre hivatkoztunk a div#fejlec h2 jelölővel. Azaz mindezt lefordítva a CSS nyelvére a két jelölőt a szóköz kombinátorral kapcsoltuk össze.
Legutóbb, a hierarchikus listák számozásánál bemutattunk egy másik kombinátort is, ami a szülőelemnek nem az összes megadott típusú leszármazottját jelöli ki, hanem csak a közvetlenül alá tartozó „gyermekeit”. Ha például egy többszintű listáját szeretnénk beljebb tolni, akkor a szokásos div ul {margin-left: 3em;} megoldás nem lenne jó, hiszen ez a belső listákat is beljebb tolná, márpedig mi csak a külső ‹ul› margóját akarjuk megnövelni. Ám ha a két jelölő közé nem szóközt, hanem „záró kacsacsőrt” teszünk (div › ul), akkor a problémát egy könnyed mozdulattal meg is oldottuk.
De nemcsak szülő–gyermek, hanem közvetlen szomszédi viszonyok szerint is kijelölhetünk bizonyos elemeket a plusz kombinátor használatával. Ha például a klasszikus tipográfiát követve azt szeretnénk, hogy bekezdéseink némi behúzással kezdődjenek (p {text-indent: 2em;}), kivéve a címsorok utániakat, amelyeknél nincs szükség behúzásra – és mindezt természetesen extra osztály bevezetése nélkül –, akkor a fenti szabályt követően létre kell hoznunk egy másikat, amelynek a jelölője az lesz, hogy h2 + p, deklarációs blokkjának tartalma pedig megszünteti ezeknek a bekezdéseknek a behúzását (text-indent: 0;).
A negyedik kombinátor (~) a CSS3-mal jelent meg, és olyan kapcsolatot hoz létre azonos szinten levő, vagyis azonos szülővel rendelkező elemek között, ami csak az első elem előfordulását követő második eleme(ek)re lesz hatással. Így kicsit furcsán hangzik, de azonnal látni fogjuk a hatását, ha az aktuális stíluslapunkba beszúrjuk a következő sort: p ~ h2 {color: red;} Az oldal frissítését követően látni fogjuk, hogy csak az első ‹p› utáni ‹h2›-k lettek pirosak, az első nem.
Pszeudoosztályok és elemek
A pszeudoosztályok és elemek oldalaink „mesebeli objektumai” – ugyanis vannak is, meg nem is. A HTML-kódban tulajdonképpen nincsenek, mégis megjelennek, megjelenhetnek oldalainkban. Hogy ez miként lehetséges? Például úgy, hogy egy hivatkozásnak vagy egy rádiógombnak több állapota lehet, de ezek nem jelennek meg a HTML-ben, ám mégis lehetőségünk van ezen állapotokhoz különböző megjelenéseket rendelni. A hivatkozásoknál ezek a jól ismert :link, :visited, :hover, :active, :focus, ami a CSS3-ban kiegészült a :target-tel, míg a rádiógombokhoz és a többi űrlapelemhez megjelentek az :enabled, :disabled és :checked pszeudoosztály jelölők.
Hasonlóképpen a mintaoldalainkban már közel egy éve használjuk az ún. strukturális pszeudoosztályokat, amelyekkel az elemeknek az oldalak objektummodelljében elfoglalt helyük alapján tudunk hivatkozni, például egy táblázat páratlan sorainak más háttérszínt adni (tr:nth-child(odd) {background: #ccc;}), vagy egy lista minden harmadik elemét dőlt betűvel írni (li:nth-child(3n+1) {font-style: italic;}).
Végül vannak az olyan elemek, amelyek nem is jelölt elemek, de mégis képesek úgy viselkedni. Ilyenből jelenleg „kettő plusz kettőt” használhatunk, a blokkszintű vagy hasonlóképpen viselkedő elemek első sorát (:first-line) és a szöveges elemek első karakterét (:first-letter), valamint a legutóbb alaposan körüljárt :before-t és :after-t.
A cikkben szereplő kódok és mintaoldalak letölthetők innen