A CSS a kezdetekhez képest nagy fejlődésen ment keresztül. Már nem csak statikusan képes tulajdonságokat rendelni az egyes html elemekhez, hanem dinamikusan is tudja bizonyos szinten azok tartalmát megváltoztatni. Erre egy jó példa a CSS számlálók.
A CSS számlálók gyakorlatilag a CSS változói, melyeket CSS szabályokkal tudunk létrehozni, növelni, megjeleníteni. Ezeket általában elemekhez rendeljük sorszámként. A számlálót a counter-reset tulajdonsággal hozzuk létre. Ha már egy korábban létrehozott számlálót rendelünk ehhez a tulajdonsághoz, akkor a már létezőt felülírjuk egy új kezdőértékkel. (A kezdőérték alapértelmezetten 0, de megadhatunk mást is a változó után írva.)
counter-reset: oldal; counter-reset: oldal 5;
A létrehozott változót ezután a counter-increment tulajdonsággal tudjuk növelni. Alapértelmezetten 1-gyel növeli, de itt is megadhatunk más értéket a változó után írva.
counter-increment: oldal; counter-increment: oldal 2;
Ezután már csak ki kell íratnunk az oldal megfelelő helyére, ezt a content tulajdonsággal tehetjük meg. Alapértelmezetten arab számként írja ki, de megadhatjuk, hogy akár római számmal (kis- vagy nagybetűsen), de számos más formátum is rendelkezésre áll. (A különböző lehetőségeket ezen a linken tudjuk megtekinteni: link)
content: counter(oldal); content: counter(oldal, upper-roman);
Nézzünk meg egy egyszerű példát. Tegyük fel, hogy egy tartalomjegyzékben sorszámmal szeretnénk hivatkozni az egyes oldalakra. Alapesetben ilyenkor ezeket a sorszámokat az alábbi módon bedrótozzuk a kódba:
<a href="#">1.</a> <a href="#">2.</a> <a href="#">3.</a> <a href="#">4.</a> <a href="#">5.</a> <a href="#">6.</a> <a href="#">7.</a>
A fenti megoldás azért nem szerencsés, mert bármikor új hivatkozást szúrunk be a többi közé, újra kell sorszámozni az utána következő elemeket. Állítsuk elő ezeket a sorszámokat inkább CSS számlálóval. A számlálónk neve az oldal lesz, az oldal legelején (a body elemnél) hozzuk létre, és minden hivatkozásnál eggyel megnöveljük. A ::before pszeudo elemmel a hivatkozás tartalma elé íratjuk ki. (Jelen esetben nincsen a hivatkozásnak tartalma, így csak a sorszám jelenik meg.) Elismerem, hogy az oldal kinézete elég egyszerű, a bejegyzés vége tájékán azért megformázzuk egy kicsit.
<html> <head> <style> body {counter-reset: oldal;} a {counter-increment: oldal ;} a::before {content: counter(oldal);} </style> </head> <body> <a href="#"></a> <a href="#"></a> <a href="#"></a> <a href="#"></a> <a href="#"></a> <a href="#"></a> <a href="#"></a> </body> </html>
Természetesen lehetőség van egyszerre több számláló kezelésére is. Tegyük fel, hogy egy hosszabb dokumentumban többszintű (a példában 3 szintű) fejezeteket szeretnénk létrehozni a h1, h2 és h3 címsorokkal. A fejezeteket sorszámozni szeretnénk, de megint nem szeretnénk bedrótozni a sorszámokat a kódba. Hozzunk létre 3 számlálót (fejezet_1, fejezet_2 és fejezet_3), melyek az egyes fejezetszinteket sorszámozzák. A body elemnél inicializáljuk a fejezet_1 változót, melyet a h1 elemnél inkrementálunk. A fejezet_2 változót a h1 eleménél hozzuk létre (illetve nullázzuk), hiszen minden h1-es fejezetcím után újrakezdődik a 2. szintű fejezetek (h2) sorszámozása. Ugyanígy a fejezet_3 változót a h2 elemnél inicializáljuk, és a h3 elemeknél növeljük. (A fejezetcímeket kicsit átszíneztük, hogy jobban látszódjék, melyik melyik szinthez tartozik.)
<html> <head> <style> body{counter-reset: fejezet_1;} h1{counter-reset: fejezet_2; counter-increment: fejezet_1;} h2{counter-reset: fejezet_3; counter-increment: fejezet_2;} h3{counter-increment: fejezet_3;} h1::before{content: counter(fejezet_1) ". ";} h2::before{content: counter(fejezet_1) "." counter(fejezet_2) ". ";} h3::before{content: counter(fejezet_1) "." counter(fejezet_2) "." counter(fejezet_3) ". ";} h1{font-size: 1.8em; background-color: #afafaf; margin: 0px;} h2{font-size: 1.4em; background-color: #d2d2d2; margin: 0px; font-weight:300;} h3{font-size: 1em; background-color: #e2e2e2; margin: 0px;font-weight:100;} </style> </head> <body> <h1>Őskor</h1> <h2>Kína őstörténete</h2> <h2>Megalitikus kultúrák</h2> <h2>Mezopotámia, Kis-Ázsia és a Közel-Kelet kultúrái</h2> <h1>Újkor</h1> <h2>Korai újkor</h2> <h3>Reformáció</h3> <h3>Edo-kor</h3> <h3>Qing-kor</h3> <h3>Felvilágosodás</h3> <h3>Ipari forradalom</h3> <h2>Modern kor</h2> <h3>Napóleon kora</h3> <h3>Japán modern kor</h3> <h3>Kínai modern kor</h3> <h3>I. világháború</h3> <h3>A két világháború közötti korszak</h3> </body> </html>
Vegyük figyelembe, hogy minden h1, h2 és h3 tag-nél növelni fogja a változókat (illetve inicializálni, amit kell), így ha nem csak a fejezetcímekben használjuk ezeket a tag-eket, akkor célszerű valamivel megjelölni azokat (például egy-egy CSS-osztályt hozzájuk rendelni, és csak az ebbe a CSS osztályba tartozó elemek esetében legyen a számláló kezelve.)
Hasznos dolog, hogy egyszerre több számlálót is használhatunk, de a fenti példában ebből a három különböző számlálóból ténylegesen egy, többszintű számlálót készítettünk. Jó lenne, ha az ilyen többszintű sorszámozást a CSS egyszerűbben is támogatna. Támogatja a beágyazott számlálók használata által. A következő példában egy többszintű sorszámozott lista sorszámozását bízzuk egy ilyen beágyazott számlálóra. Mint látjuk, a sorszámozott lista saját jelölőit kikapcsoltuk (list-style-type: none;), és a számlálót a hagyományos módon inicializáljuk és inkrementáljuk, viszont a kiíratásánál nem a counter hanem a counters függvényt használjuk. Ennek a függvénynek nem csak a számlálót, hanem az egyes szintek közötti elválasztó karaktert is átadjuk. (A végére nem teszi oda ezt a karaktert, így ezt mi illesszük oda manuálisan.) A CSS tudni fogja, hogy a számlálónak melyik szintjét kell növelni éppen.
<html> <head> <style> ol { counter-reset: szamlalo; list-style-type: none; } li { counter-increment: szamlalo;} li::before { content: counters(szamlalo,".") ". ";} </style> </head> <body> <ol> <li>Alaplapok</li> <li>Processzorok <ol> <li>AMD</li> <li>Intel <ol> <li>Core i3</li> <li>Core i5</li> <li>Core i7</li> <li>Core i9</li> </ol> </li> </ol> <li>Videokártyák</li> </ol> </body> </html>
Mi van akkor, ha valamelyik listaelemnél nem szeretnénk a számlálót növelni, illetve a tartalmát megjeleníteni. Tegyük fel, hogy processzor típusok előtt meg akarjuk jeleníteni a “Típusok” feliratot, de értelemszerűen nem akarunk elé sorszámot tenni. Ehhez hozzunk létre egy nemszamol osztályt, és az ilyen osztályú listaelemeknél nem növeljük a számlálót, illetve nem írjuk ki a tartalmát:
<html> <head> <style> ol {counter-reset: szamlalo; list-style-type: none;} li {counter-increment: szamlalo;} li::before {content: counters(szamlalo,".") ". ";} li.nemszamol {counter-increment: none;} li.nemszamol::before{content: none;} </style> </head> <body> <ol> <li>Alaplapok</li> <li>Processzorok <ol> <li>AMD</li> <li>Intel <ol> <li class="nemszamol">Típusok</li> <li>Core i3</li> <li>Core i5</li> <li>Core i7</li> <li>Core i9</li> </ol> </li> </ol> <li>Videokártyák</li> </ol> </body> </html>
Igaz, hogy nem tartozik a CSS számlálók témakörébe, de egy kicsit színezzük ki a fenti listát, hogy nézzen már ki valahogy.
ol {counter-reset: szamlalo; list-style-type: none;} li {counter-increment: szamlalo; padding-left:0px;} li::before {content: counters(szamlalo,".") ". ";} li.nemszamol {counter-increment: none; background-color: orange;} li.nemszamol::before{content: none;} body>ol {width: 300px; padding-left:0px;} ol {background-color: yellow;} ol>li{background-color: pink;} ol>li>ol>li{background-color: lightgreen;} ol>li>ol>li>ol>li{background-color: lightblue;}
Érezzük, hogy az egyes elemek elérése logikus, de a színek kiválogatása elég véletlenszerű, és nem is tekinthető egységesnek. A következő példában erre is olvashatunk egy jó trükköt. Korábban már említettem, hogy az automatikusan sorszámozott hivatkozásokra ráférne egy kis formázás. Tegyük most ezt meg. A CSS stílusokat most egyben nézzük meg, és csak az érdekesebb részekhez fűzök magyarázatot.
<html> <head> <style> body {counter-reset: oldal;} a {counter-increment: oldal;} a::before {content: counter(oldal);} body {background-color: #1f4261;} div { font: 32px Arial; background-color: rgba(255, 255, 255, .1); margin-bottom: 16px; padding: 16px; border-radius: 6px; overflow: auto; } a { float: left; width: 32px; margin: 6px; padding: 6px; border-radius: 6px; border: solid 2px rgba(255, 255, 255, .4); text-decoration: none; text-align: center; color: #fff; background-color: rgba(255, 255, 255, .2); } a:hover { border: solid 2px #fff; background-color: rgba(255, 255, 255, .4); box-shadow: 0 0 10px #fff; } </style> </head> <body> <div> <a href="#"></a> <a href="#"></a> <a href="#"></a> <a href="#"></a> <a href="#"></a> <a href="#"></a> <a href="#"></a> </div> </body> </html>
A sorszámozást megvalósító tulajdonságokkal már korábban foglalkoztunk. Nézzük a háttérszíneket: Az oldal háttérszínét a body elemhez rendeltük, az összes többi elem esetében az átlátszósággal játszunk. Így érjük el, hogy ugyan különbözőek a háttérszínek, de mégis egységesek, és csak egy helyen kell módosítani, ha változtatni szeretnénk rajta.
A következő furcsaság, hogy a hivatkozásokra alkalmaztuk a floating: left tulajdonságot, noha azok eleve már egymás mellé (balra) vannak rendezve. Akkor miért kellett? Tudni kell, hogy a floating tulajdonságot blokk szintű elemekre lehet alkalmazni, míg a hivatkozások in-line elemek. Az in-line elemekre viszont nem lehet a width tulajdonságot alkalmazni, amit mi meg szeretnénk, vagyis előtte a display: block tulajdonsággal blokk szintűvé kell alakítanunk. Ezt a tulajdonságot viszont nem alkalmaztuk. A lényeg az, hogy ha a floating tulajdonságot in-line elemre alkalmazzuk, azt blokk szintűként kezeli, így viszont már a width tulajdonságot is alkalmazza anélkül, hogy a display: block tulajdonsággal átalakítottuk volna.
Az utolsó tulajdonság az overflow, ami magyarázatra szorul. Az overflow eredetileg arra való, hogy amennyiben egy blokk szintű elembe nem fér bele a tartalma, akkor a mit kezdjünk a “kilógó” részekkel. Az overflow: hide beállítást arra utasítaná a böngészőt, hogy a kilógó részeket rejtse el. Itt most a hivatkozásokat befoglaló div elembe nem férnek be a hivatkozások, tehát a kilógókat nem kellene látnunk. Mégis látjuk. Miért van ez? Azért, mert a div elemnek nem adtuk meg a height tulajdonságát, így az overflow: hide ilyenkor akkorára nyújtja a div elemet, hogy minden beleférjen. Miért nem adtuk meg inkább a height tulajdonságot? Mert akkor ha a későbbiekben újabb hivatkozásokat helyeznénk el ide, akkor a div magasságát is növelni kellene. Így viszont mindig követi a tartalmat.