Tananyag
14. lecke · Kijelölők II. – pszeudók

3. modul · CSS alapok · 14. lecke

Kijelölők II. – pszeudók

Az előző leckében elemeket céloztunk meg. Most állapotokat fogunk: „amikor rajta az egér", „amikor ki van választva", „a harmadik elem a sorban". És a lecke végén olyan tartalmat is létrehozunk, ami nincs is benne a HTML-ben.

≈ 35 perc Előtte: 13. lecke 9 kipróbálható példa

Mit fogsz tudni a lecke végén

1Mi a pszeudo-osztály?

A pszeudo-osztály olyan kijelölő, ami nem az elem fajtáját vagy a nevét nézi, hanem az állapotát vagy a helyzetét. Felismerhető a kettőspontról:

a:hover {
  color: crimson;
}

Olvasva: „a elem, amikor rajta van az egér". A pszeudo szó görögül azt jelenti: „ál-". Vagyis olyan, mintha osztály lenne — csak nem te írod be a HTML-be, hanem a böngésző adja hozzá magától, amikor az adott állapot fennáll.

EZÉRT KÜLÖNLEGES

A HTML-ben semmit nem kell csinálnod. Nem kell osztályt írni, nem kell JavaScript. Az egér mozgásáról, a billentyűzetről, a bejelölt négyzetről és arról, hogy egy elem hányadik a sorban, a böngésző úgyis tud — a pszeudo-osztályokkal csak megkéred, hogy ezt a tudást ossza meg veled.

KategóriaPéldák
Felhasználói állapot:hover, :focus, :active, :visited
Űrlap-állapot:checked, :disabled, :required, :invalid
Helyzet a szülőn belül:first-child, :last-child, :nth-child()
Kizárás:not()

3A fókusz

A :focus akkor érvényes, amikor egy elem „aktív": bele van kattintva egy mezőbe, vagy a Tab billentyűvel odanavigáltak.

Kattints a mezőkbe, vagy Tab-olj végig rajtuk!
index.html
<p>
  <label for="a">Név</label><br>
  <input type="text" id="a">
</p>
<p>
  <label for="b">E-mail</label><br>
  <input type="email" id="b">
</p>
<p><button>Küldés</button></p>
style.css
input, button {
  padding: 6px 10px;
  border: 2px solid #d1d5db;
  border-radius: 6px;
  font-size: 15px;
}

input:focus, button:focus {
  outline: 3px solid #fb7185;
  outline-offset: 2px;
  border-color: #be123c;
  background-color: #fff5f7;
}
Eredmény — kattints bele, majd nyomj Tab-ot!
Kattints az első mezőbe, majd nyomd a Tab-ot: a keret végigvándorol a mezőkön és a gombon. Így navigál az, aki nem tud egeret használni.
SOHA NE ÍRD EZT: outline: none

A böngésző alapból rajzol egy fókuszkeretet. Sokan „csúnyának" tartják, és ezt teszik:

*:focus {
  outline: none;   /* SOHA! */
}

Ezzel használhatatlanná tetted az oldalt annak, aki billentyűzettel navigál: fogalma sem lesz, hol jár. Ha nem tetszik az alapértelmezett keret, cseréld le egy sajátra — de valami mindig legyen.

:focus-visible — A FINOMABB VÁLTOZAT

A :focus-visible csak akkor lép életbe, ha a fókusz billentyűzetről érkezett — egérkattintásnál nem. Így a billentyűzetes felhasználó megkapja a keretet, az egeres pedig nem lát „felesleges" díszt. Modern oldalakon ma ez a bevett megoldás.

4Űrlap-állapotok

Az űrlapmezőknek rengeteg állapotuk van, és mindegyikhez tartozik pszeudo-osztály.

Pszeudo-osztályMikor érvényes?
:checkedA jelölőnégyzet vagy rádiógomb be van jelölve
:disabledA mező le van tiltva
:requiredKötelezően kitöltendő
:valid / :invalidA beírt érték megfelel-e a szabályoknak
:placeholder-shownA mező üres, tehát a placeholder látszik
Pipáld be a négyzeteket, és írj az e-mail mezőbe!
index.html
<p>
  <input type="checkbox" id="a">
  <label for="a">Extra sajt</label>
</p>
<p>
  <input type="checkbox" id="b">
  <label for="b">Gomba</label>
</p>
<p>
  <input type="email" placeholder="Írj be egy e-mailt"
         size="24" required>
</p>
<p>
  <input type="text" value="Nem szerkeszthető" disabled>
</p>
style.css
/* a bejelölt négyzet UTÁNI címke */
input:checked + label {
  color: #047857;
  font-weight: bold;
}

input:disabled {
  background-color: #e5e7eb;
  color: #9ca3af;
}

input:invalid {
  border: 2px solid #be123c;
}

input:valid {
  border: 2px solid #047857;
}
Eredmény — próbáld ki mindet!
Pipáld be a négyzeteket: a feliratuk zöld és félkövér lesz. Írj az e-mail mezőbe egy @ nélküli szöveget: bordó keretet kap; egészítsd ki érvényes címmé: zöldre vált. Mindez CSS-ből, azonnal.
FIGYELD MEG A TRÜKKÖT

Az input:checked + label két dolgot köt össze, amit a 13. leckében tanultál: egy pszeudo-osztályt és egy testvér-kijelölőt. Olvasva: „az a label, ami közvetlenül egy bejelölt input után áll". Így tudsz úgy formázni egy elemet, hogy közben egy másik elem állapotát figyeled.

AZ :invalid AZONNAL MŰKÖDIK

Ez néha zavaró: egy üres, kötelező mező már az első betű előtt hibásnak számít, tehát rögtön pirosan jelenik meg. Éles oldalakon ezért gyakran a :invalid:not(:placeholder-shown) kombinációt használják — így csak akkor pirosodik, ha már elkezdték kitölteni.

5Helyzet szerinti kijelölés

Ezek a pszeudo-osztályok azt nézik, hányadik gyerek egy elem a szülőjén belül.

Első, utolsó és a harmadik elem
index.html
<ul class="lista">
  <li>Első</li>
  <li>Második</li>
  <li>Harmadik</li>
  <li>Negyedik</li>
  <li>Ötödik</li>
</ul>
style.css
.lista li {
  padding: 4px 8px;
  border-bottom: 1px solid #e5e7eb;
}

.lista li:first-child {
  color: #047857;
  font-weight: bold;
}

.lista li:last-child {
  color: #be123c;
  border-bottom: none;
}

.lista li:nth-child(3) {
  background-color: #fef3c7;
}
Eredmény a böngészőben
A :last-child egyik leggyakoribb haszna itt látszik: az utolsó elemről levesszük az elválasztó vonalat, hogy ne lógjon ki egy fölösleges csík a lista alján.
A :first-child CSAPDÁJA

A :first-child azt jelenti: „az első gyerek, feltéve hogy ő ilyen elem" — nem azt, hogy „az első ilyen elem". Nézd meg:

<div>
  <h3>Cím</h3>
  <p>Első bekezdés</p>
</div>

Itt a p:first-child semmit nem talál, mert az első gyerek a h3, nem a bekezdés.

Amire itt szükséged van: p:first-of-type — „az első p a testvérei között". Ez működni fog.

6Az nth-child képletei

Az :nth-child() zárójelébe nemcsak számot írhatsz, hanem képletet is. Ettől lesz igazán hasznos.

ÉrtékMit jelent?
3A harmadik elem
even vagy 2nMinden páros: 2., 4., 6.…
odd vagy 2n+1Minden páratlan: 1., 3., 5.…
3nMinden harmadik: 3., 6., 9.…
3n+1Az 1., 4., 7.… — minden hármas csoport eleje
-n+3Az első három elem
HOGYAN OLVASD A KÉPLETET?

Az n sorban felveszi a 0, 1, 2, 3… értékeket, és minden eredmény egy találat. A 3n+1 tehát: 3·0+1=1, 3·1+1=4, 3·2+1=7… A nullától vagy negatív tartományba eső eredményeket a böngésző egyszerűen kihagyja.

Csíkos táblázat egyetlen szabállyal
index.html
<table>
  <tr><th>Név</th><th>Pont</th></tr>
  <tr><td>Anna</td><td>92</td></tr>
  <tr><td>Béla</td><td>78</td></tr>
  <tr><td>Cili</td><td>85</td></tr>
  <tr><td>Dani</td><td>64</td></tr>
  <tr><td>Emese</td><td>97</td></tr>
</table>
style.css
table {
  border-collapse: collapse;
}

td, th {
  padding: 6px 14px;
  text-align: left;
}

th {
  background-color: #be123c;
  color: white;
}

tr:nth-child(even) {
  background-color: #fce7f3;
}
Eredmény a böngészőben
Egyetlen sor csinálja a csíkozást — és ha holnap beszúrsz egy új sort középre, a csíkozás magától újrarendeződik. Ezt kézzel, osztályokkal soha nem tudnád karbantartani.
Képletek működés közben
index.html
<ul class="sor">
  <li>1</li><li>2</li><li>3</li>
  <li>4</li><li>5</li><li>6</li>
  <li>7</li><li>8</li><li>9</li>
</ul>
style.css
.sor {
  list-style: none;
  padding: 0;
}

.sor li {
  display: inline-block;
  width: 32px;
  padding: 8px 0;
  margin: 2px;
  text-align: center;
  border: 1px solid #d1d5db;
}

/* minden harmadik */
.sor li:nth-child(3n) {
  background-color: #be123c;
  color: white;
}

/* az első három */
.sor li:nth-child(-n+3) {
  border-color: #047857;
  border-width: 3px;
}
Eredmény a böngészőben
A 3., 6. és 9. doboz bordó (3n), az első három pedig zöld keretet kapott (-n+3). A harmadikra mindkettő érvényes.

7A :not() kizárás

A :not() megfordítja a feltételt: „minden ilyen elem, kivéve azokat, amelyek…".

Minden gomb, kivéve a letiltottakat
index.html
<p>
  <button>Mentés</button>
  <button>Mégse</button>
  <button disabled>Törlés</button>
</p>

<ul>
  <li>Alma</li>
  <li class="kesz">Kenyér</li>
  <li>Tej</li>
</ul>
style.css
button {
  padding: 6px 14px;
  border: none;
  border-radius: 6px;
}

/* csak a NEM letiltott gombokra */
button:not(:disabled) {
  background-color: #be123c;
  color: white;
  cursor: pointer;
}

/* minden li, kivéve a .kesz osztályút */
li:not(.kesz) {
  font-weight: bold;
}

li.kesz {
  text-decoration: line-through;
  color: #9ca3af;
}
Eredmény a böngészőben
A „Törlés" gomb szürke maradt, mert letiltott — a :not(:disabled) kizárta. A „Kenyér" pedig áthúzva és halványan jelenik meg, a többi listaelem félkövéren.
GYAKORI HASZNÁLAT

li:not(:last-child) { border-bottom: 1px solid #ddd; } — minden elem alá vonal, kivéve az utolsót. Ez elegánsabb, mint utólag levenni a vonalat az utolsóról.

8Pszeudo-elemek: ::before és ::after

Most jön valami egészen más. A pszeudo-elem nem egy meglévő elem állapotát célozza meg, hanem új tartalmat hoz létre — olyat, ami a HTML-ben nincs is benne. Felismerhető a két kettőspontról.

Pszeudo-elemHova szúr be?
::beforeAz elem tartalma elé
::afterAz elem tartalma után
A content KÖTELEZŐ!

content nélkül a ::before és az ::after egyáltalán nem jelenik meg — akkor sem, ha mindenféle más tulajdonságot beállítasz rajta. Ha nincs mit beleírni, akkor is kell egy üres érték: content: "";

Ikonok és jelölések a HTML érintése nélkül
index.html
<ul class="teendok">
  <li class="kesz">Bevásárlás</li>
  <li>Takarítás</li>
  <li class="kesz">Mosogatás</li>
</ul>

<p class="kotelezo">E-mail cím</p>

<p class="ar">3490</p>
style.css
.teendok {
  list-style: none;
  padding: 0;
}

.teendok li::before {
  content: "☐ ";
  color: #9ca3af;
}

.teendok li.kesz::before {
  content: "☑ ";
  color: #047857;
}

.kotelezo::after {
  content: " *";
  color: #be123c;
  font-weight: bold;
}

.ar::after {
  content: " Ft";
  color: #7c6b74;
}
Eredmény a böngészőben
A HTML-ben sehol nincs pipa, csillag vagy „Ft" — mindhárom a CSS-ből származik. Ha egy elem megkapja a kesz osztályt, a jelölése is magától átvált.
MIT NE TEGYÉL BELE?

Fontos tartalmat. A content tulajdonságban lévő szöveget a keresők nem indexelik, másolni nem mindig lehet, és a képernyőolvasók is eltérően kezelik. Díszítéshez, ikonokhoz, jelölésekhez kiváló — de az oldal mondanivalója maradjon a HTML-ben.

A LEGGYAKORIBB HASZNÁLAT: ÜRES CONTENT

Meglepő módon a content: "" a leggyakoribb: így hozol létre egy üres dobozt, amit aztán színnel, mérettel és pozícióval alakítasz — elválasztó vonalnak, díszítő négyzetnek, buborék-nyílnak. Ehhez viszont már kell a dobozmodell (17. lecke) és a pozicionálás (19. lecke).

9További pszeudo-elemek

Első betű, kijelölés, placeholder — jelöld ki az egérrel a szöveget!
index.html
<p class="bevezeto">
  Egyszer volt, hol nem volt, volt egyszer
  egy weboldal, amelyiknek nagyon szép
  volt az első betűje.
</p>

<p>
  <input type="text" size="26"
         placeholder="Írj ide valamit…">
</p>
style.css
.bevezeto::first-letter {
  font-size: 44px;
  color: #be123c;
  font-weight: bold;
  line-height: 1;
}

::selection {
  background-color: #fbcfe8;
  color: #831843;
}

::placeholder {
  color: #be123c;
  font-style: italic;
}
Eredmény — jelöld ki a szöveget egérrel!
Húzd végig az egeret a szövegen: a kijelölés rózsaszín lesz a megszokott kék helyett. A mező súgószövege pedig bordó és dőlt.
Pszeudo-elemMit céloz meg?
::first-letterA bekezdés első betűjét (iniciálé)
::first-lineAz első sort — ami ablakmérettől függ!
::selectionAz egérrel kijelölt szövegrészt
::placeholderA mező súgószövegét
::markerA listaelem pontját vagy számát

Egy vagy két kettőspont?

Egy kettőspont :Két kettőspont ::
Pszeudo-osztály — meglévő elem állapota Pszeudo-elemúj, nem létező elemrész
:hover, :focus, :checked, :nth-child() ::before, ::after, ::selection
MIÉRT LÁTNI NÉHOL EGY KETTŐSPONTTAL?

Régen a pszeudo-elemekhez is egy kettőspont járt (:before), és a böngészők ma is elfogadják — visszafelé kompatibilitásból. Te írj kettőt: abból egyből látszik, hogy pszeudo-elemről van szó, nem állapotról.

10Tipikus hibák

HibaMi történik, és mi a megoldás?
Szóköz a kettőspont előtt: a :hover Ez „az a elemen belüli hoverelt elem" — nem a link maga. Néma hiba.
Rossz LVHA-sorrend A meglátogatott linkeken nem működik a hover. Sorrend: :link:visited:hover:active.
outline: none a fókuszon A billentyűzetes felhasználó nem látja, hol jár. Cseréld le, ne vedd el.
::before content nélkül Nem jelenik meg semmi. Üres esetben is kell: content: "";
:first-child a :first-of-type helyett Nem talál semmit, ha nem az adott elem az első gyerek.
::before egy <img>-en Nem működik. Az üres elemeknek (img, input, br) nincs tartalmuk, amibe be lehetne szúrni.
Fontos szöveg a content tulajdonságban Nem kereshető, nehezen másolható. Csak díszítés kerüljön oda.
Csak :hover, :focus nélkül Aki billentyűzettel navigál, nem kap visszajelzést. Írd egybe: a:hover, a:focus { ... }

Önellenőrző kérdések

Előbb válaszolj magadban, csak utána nézd meg a megoldást.

1. Mi a különbség az a:hover és az a :hover között?

Az első: a link maga, amikor rajta az egér. A második (szóközzel): a linken belüli elem, amikor azon van az egér. A szóköz itt is leszármazottat jelent, mint a 13. leckében.

2. Mit jelent az LVHA, és mi történik, ha felcseréled a sorrendet?

:link:visited:hover:active (LoVe HAte). Ha a :hover a :visited elé kerül, akkor a már meglátogatott linkeken nem lesz hover-hatás — mert az azonos erősségű szabályok közül a később írt nyer.

3. Miért tilos az outline: none a fókuszon?

Mert aki billentyűzettel (Tab-bal) navigál, nem látja, melyik elemen áll éppen — az oldal használhatatlanná válik számára. Ha az alapértelmezett keret nem tetszik, cseréld le egy sajátra (pl. egy saját színű outline keretre), de valami jelzés mindig legyen.

4. Mely elemeket célozza meg a li:nth-child(3n+1)?

Az 1., 4., 7., 10.… elemeket. Az n felveszi a 0, 1, 2, 3… értékeket: 3·0+1=1, 3·1+1=4, 3·2+1=7 és így tovább.

5. Van egy <div>, benne egy h3, utána egy p. Miért nem hat a p:first-child szabály?

Mert a :first-child azt jelenti: „az első gyerek, ha az történetesen p". Itt viszont a h3 az első gyerek, tehát nincs találat. Helyette: p:first-of-type.

6. Beállítottál egy ::after szabályt színnel és mérettel, de semmi nem látszik. Mi hiányzik?

A content tulajdonság. Enélkül a pszeudo-elem egyáltalán nem jön létre. Ha nincs mit beleírni, akkor is kell: content: "";

7. Mikor írsz egy, és mikor két kettőspontot?

Egyet a pszeudo-osztályokhoz (állapot: :hover, :checked, :nth-child()), kettőt a pszeudo-elemekhez (új elemrész: ::before, ::after, ::selection).

8. Hogyan tennél vonalat minden listaelem alá, az utolsó kivételével?

li:not(:last-child) { border-bottom: 1px solid #ddd; } — vagy minden elemre ráteszed, majd li:last-child { border-bottom: none; }-nal leveszed. Az első elegánsabb.

11Összefoglalás

  1. A pszeudo-osztály (egy kettőspont) az elem állapotát vagy helyzetét célozza meg. A HTML-be semmit nem kell írnod hozzá.
  2. Link-állapotok: :link, :visited, :hover, :activeebben a sorrendben (LoVe HAte).
  3. A :hover érintőképernyőn nem létezik — soha ne rejts mögé fontosat.
  4. :focus: a billentyűzetes navigáció alapja. Az outline tulajdonságot cseréld le, ne vedd el.
  5. Űrlap-állapotok: :checked, :disabled, :valid, :invalid. Az input:checked + label mintával másik elemet is formázhatsz.
  6. :first-child, :last-child, :nth-child() — helyzet a szülőn belül. Vigyázat: :first-child:first-of-type.
  7. Az nth-child képletei: even, odd, 3n, 3n+1, -n+3 — az n 0-tól nő.
  8. :not(): kizárás. Klasszikus: li:not(:last-child).
  9. A pszeudo-elem (két kettőspont) új tartalmat hoz létre: ::before, ::after. A content kötelező.
  10. A content tulajdonságba csak díszítés kerüljön, soha ne fontos tartalom.
  11. Üres elemeken (img, input) a ::before/::after nem működik.