Relační selektor :has – zdaleka ne jen selektor rodiče
Publikováno: 27.4.2022
Funkční selektor :has() můžeme použít jako selektor rodiče, tedy vybrat rodičovské prvky, obsahující potomky určitého typu. Podívejme se na něj detailně.
Text vyšel původně na webu autora.
:has()
je funkční selektor, který můžeme mimojiné použít jako selektor rodiče, tedy vybrat rodičovské prvky, obsahující potomky určitého typu:
a:has(img) { }
Tento selektor cílí na všechny odkazy (a
), které mají v DOMu jako potomka obrázek (img
).
Selektor :has
je podporován v Safari a to od verze 15.4 z března 2022. Fanfáry prosím!
Chrome oznámil, že od verze 101, takže v nejbližším měsíci, bude selektor podporovat zkušebně s možností zapnout jej pod nastavením vlaječek (flags).
Nejen selektor rodiče
Selektor :has
je součástí návrhu specifikace W3C Selectors Level 4. Vzbudil velkou pozornost, protože jednou z možností jeho použití je právě selektor rodiče, což je v CSS už asi dvacet let něco jako banány za komunistů. Lidé to strašně moc chtějí, stáli by na to fronty, ono se to občas někde objeví, ale zpravidla je to planý poplach.
Jenže :has
ve skutečnosti selektor rodiče není. Doslovně, přesně podle specifikace, jde o relační pseudotřídu (Relational Pseudo-class). Relační proto, že do závorek můžete napsat jakýkoliv relativní selektor, se vztahem k selektoru před dvojtečkou:
/* Vybere <a>, jejichž přímým potomkem je <img>: */
a:has(> img) { }
/* Vybere všechny <section>, které obsahují <h1> nebo <h2>: */
section:has(h1, h2) { }
/* Vybere všechny <img>, za nimiž následují <figcaption>: */
img:has(+ figcaption)
Všimněte si posledního případu. Vybírá prvního z bezprostředně navazujících sourozenců v DOMu. Tady o selektoru rodiče nemůže být řeč. Navíc je to užitečné a skoro stejně nedostatkové jako ty banány za komunistů. Nebo jako selektor rodiče v CSS.
Ukázka se selektorem rodiče
Podívejme se na následující CodePen. Jsou v něm dva prvky .box
. Jeden obsahuje obrázek a jeden pouze text:
<p class="box">
Lorem ipsum…
</p>
<p class="box">
<img />
<br>
Quam doloremque…
</p>
Relační pseudotřídou :has
se pak snažím zacílit boxík s obrázkem:
.box:has(img) {
border: 5px #30680d dotted;
}
Výsledek uvidíte níže. Jen pozor, v dubnu 2022 to bude fungovat jen v Safari 15.4:
Ukázka se selektorem předchozího sourozence
V tomto demíčku se zaměříme na stylování prvků v textu, za nimiž následují jiné specifické prvky. Máme dva nadpisy, za jedním následuje odstavec, za druhým seznam položek:
<h2>Lorem ipsum, dolor sit amet</h2>
<p>
Lorem…
</p>
<h2>Quam doloremque…</h2>
<ul>
<li>
Lorem…
</li>
</ul>
Pokud bychom ten druhý chtěli stylovat jinak, opět nemusíme složitě přidávat třídu, ale použít relační pseudotřídu :has
:
h2:has(+ul) {
border-bottom: 5px #30680d dotted;
margin-bottom: 2rem;
}
Ani tuto ukázku neuvidíte plně funkční jinde než v Safari 15.4:
Další možnosti, občas dechberoucí
Když jsem procházel, co se selektorem :has
vykouzlili jiní autoři, občas mě srdíčko poskočilo radostí. O jejich nápady se s vámi musím podělit, v tomto případě hlavně o nápady Matthiase Otta.
/* Vybere formulář, ve kterém je zatržené zatržítko: */
form:has(input[type="checkbox"]:checked) { }
/* Vybere formulář, kde jsou dvě zatržená zatržítka: */
form:has(input[type="checkbox"]:checked ~ input[type="checkbox"]:checked) { }
/* Vybere <img> ve <figure>, za nímž následuje <figcaption>: */
figure img:has(+ figcaption) { }
/* Vybere kontejner layoutu, v němž jsou dvě položky: */
.grid:has(:nth-child(2):last-child) { }
Všimněte si hlavně té poslední možnosti. Rozložení v CSS layoutu upravujeme počítáním prvků uvnitř. Jde o aplikaci takzvaných quantity queries, které už před lety popsal Heydon Pickering.
Podpora v prohlížečích
Stav podpory :has
k dubnu 2022 je tento:
- Safari nový selektor plně podporuje od poslední verze, tzn. 15.4.
- Chrome si s
:has
pohrává a od verze 101 bude možné zkoušet za vlaječkou. - Firefox zatím nevysílá signály, že by měl podporu v nejbližší době v plánu. To nás mrzí, že… ?
V tuto chvíli by, kvůli zdaleka ne plné podpoře, asi nebylo vhodné selektor :has
začít používat na veřejných webech.
Pokud byste to přes to chtěli zkusit, zmiňuji zde nápad testování podpory selektoru s možností vytvoření alternativního řešení pro přohlížeče, které :has
neumí. Prostě využijeme dotaz na podporu @supports
:
@supports selector(:has(*)) {
/* Kód pro prohlížeče, které podporují :has */
}
Existují samozřejmě také javascriptové polyfilly, které funkci :has
nahrazují, ale neodkážu na ně, protože z pohledu výkonu považuji nahrazování takto nízkoúrovňové funkce prohlížeče za nepěknou prasárnu.
Nevím jak vy, ale já se na podporu :has
v prohlížečích docela těším.
Kniha „Vzhůru do (responzivního) designu“
Kompletní průvodce návrhem a implementací responzivních uživatelských rozhraní v e-booku a knize. Více informací.