Hvad er :has()
:has() kaldes ofte en relationel pseudo-klasse: du kan style et element ud fra hvad det indeholder eller hvad der ligger ved siden af det.
Det gør det muligt at flytte logik op på parent-niveau i stedet for at style kun det inderste element.
Det åbner op for helt nye måder at tænke på i forhold til styling baseret på indhold og struktur.
Undersøg relationerne
Gæt hvilke bokse der rammes, og afprøv derefter div:has(h2), div:has(h2, h3) og div:has(h2):has(h3). Brug fx outline-color: deeppink til at vise resultatet.
Komma betyder her enten/eller, mens to :has() efter hinanden kræver begge betingelser. Det er stadig div, der vælges; overskrifterne bruges som betingelse.
Sammenlign også p + figure med p:has(+ figure): den første vælger figuren, den anden afsnittet umiddelbart før figuren. De skal være søskende.
Patterns og øvelser
Der er mange patterns du kan bygge med :has(). Her er nogle eksempler:
.card:has(img)Vælger .card, hvis der findes et img indeni.
.card:not(:has(img))Vælger .card, hvis den ikke har et billede.
.form:has(:focus)Vælger .form, hvis et felt indeni har fokus.
.option:has(input:checked)Vælger .option, hvis den indeholder et input der er :checked.
.list:has(> :nth-child(4))Vælger .list, hvis der er mindst 4 direkte element-børn.
.item:has(+ .item)Vælger .item, hvis der findes en søskende-.item lige efter.
.item:has(~ .item)Vælger .item, hvis der findes en søskende-.item senere i DOM'en.
.card:has(img, video)Vælger .card, hvis den har enten img eller video indeni.
.card:has(img):has(video)Vælger .card, hvis den har både img og video indeni.
:has() er altså særligt nyttig, når du har brug for at style baseret på indholdets tilstedeværelse, tilstand eller mængde. Det kan være:
- card, hvor indholdet kan variere
- formularer, hvor noget bliver aktivt eller valgt
- lister og feeds med forskelligt antal elementer
- layout, der skal skifte alt efter indholdet
Test dig selv
- Knappen med et ikon skal have helt runde hjørner og have reduceret padding på højre side til
0.675rem.
- Giv kun det udsolgte produkt en outline ved hjælp af CSS
:has().
.containerskal have et grid med to kolonner, hvis der er et<figure>-element. Hvis der ikke er et<figure>-element, skal.containerhave enmax-widthpå40chog være centreret.
- Giv
pen grøn farve, hvis den kommer førfigure, og rød farve, hvis den kommer efterfigure.
Bonus: display: contents
display: contents fjerner elementets egen boks fra layoutet, men fjerner ikke elementet fra DOM’en. Dets børn kan derfor deltage i det omgivende layout, mens selectors stadig følger den oprindelige HTML-struktur.
p:has(img) { display: contents;}Mønstret fra slides kan være nyttigt for wrappers omkring billeder. Undersøg forskellen mellem DOM-træet og de bokse, browseren tegner. Det er bonusstof; et godt første mål er at forstå de almindelige relationer med :has().
Bonus: Quantity queries
.list:has(> :nth-child(4)) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));}Her er betingelsen mindst fire direkte element-børn. Uden > kunne fjerde barn i en nested struktur også udløse reglen. Test ved at tilføje indhold inde i det første kort uden at øge antallet af kort.
En mere sammensat selector er .gallery:not(:has(:not(img))). Den matcher, når galleriet ikke har efterkommerelementer, der er andet end img. Den undersøger ikke tekstnoder og matcher også et tomt galleri. Den betyder derfor ikke i almindelighed “indeholder kun billeder og intet andet”. Brug den kun, når du kan forklare de konkrete matches i din HTML.