Gepubliceerd: 14 augustus 2025
Nu het Google I/O-evenementenseizoen ten einde loopt, blikt dit bericht terug op de belangrijkste hoogtepunten op het gebied van CSS en web-UI die dit jaar tijdens onze evenementen zijn gedeeld.
Ongelooflijk krachtige functies waar ontwikkelaars vroeger alleen maar van konden dromen, zijn nu beschikbaar in browsers en worden sneller dan ooit compatibel met verschillende browsers. Ondanks deze vooruitgang blijven sommige van de meest voorkomende UI-patronen echter verrassend moeilijk correct te implementeren. Je moet vaak vertrouwen op JavaScript-frameworks, complexe CSS-trucs en bergen aan aangepaste code om componenten te bouwen die eigenlijk veel eenvoudiger zouden moeten zijn.
Het Chrome-team werkt samen met andere browserleveranciers, standaardiseringsorganisaties zoals de CSSWG en WHATWG, en communitygroepen zoals Open UI om deze fundamentele UI-patronen daadwerkelijk eenvoudig te implementeren.
Aanpasbare selectiemenu's
Het <select> -element is essentieel voor formulieren, maar de interne structuur ervan is historisch gezien afgeschermd door de browser, waardoor consistente en uitgebreide CSS-styling vrijwel onmogelijk is. Om een beter <select> te bouwen, is inzicht in de bouwstenen ervan nodig: de Popover API en de CSS Anchor Positioning API.
De Popover API: nu beschikbaar in Baseline.
Een aangepast dropdownmenu heeft een zwevend vak met opties nodig dat boven alle andere UI-elementen verschijnt, eenvoudig te sluiten is en de focus correct beheert. De Popover API regelt dit allemaal en heeft sinds dit jaar de status 'Baseline Newly available' bereikt, wat betekent dat deze stabiel is in alle belangrijke browsers.
Het maken van een popover bestaat uit twee delen: een triggerelement (zoals een <button> ) en het popoverelement zelf. Verbind deze door de popover een id en het [popover] -attribuut te geven, en verwijs vervolgens naar die id in het [popovertarget] -attribuut van de knop.
De Popover API beheert de volledige levenscyclus van het element en biedt het volgende:
- Rendering op de bovenste laag : Geen gedoe meer met de z-index.
- Optionele functie voor het sluiten van het pop-upvenster : het sluit wanneer een gebruiker buiten het pop-upgebied klikt.
- Automatisch focusbeheer : De browser regelt de tabnavigatie in en uit het pop-upvenster.
- Toegankelijke bindingen : Het onderliggende interactiemodel wordt native afgehandeld.
Het <dialog> -element krijgt een upgrade.
Hoewel popovers krachtig zijn, zijn ze niet altijd de juiste keuze. Bijvoorbeeld in pagina-blokkerende interacties die feedback van de gebruiker vereisen, is een modaal <dialog> geschikter.
Historisch gezien miste <dialog> enkele van de gemakken van [popover] , maar daar komt verandering in. Met het nieuwe attribuut closedby="any" ondersteunen modale dialoogvensters nu een vereenvoudigde sluitingsfunctie, waarbij ze sluiten wanneer de gebruiker buiten het dialoogvenster klikt of op de Escape-toets drukt.
Daarnaast bieden command invokers ( [command] en [commandfor] ) een declaratieve, JavaScript-vrije manier om een knop aan een actie te koppelen, zoals het openen van een dialoogvenster met command="show-modal" .
<dialog> Element + closedby=any + opdrachtaanroepers | [popover] attribuut | |
|---|---|---|
| Primair gebruik | Modale interactie (gebruikersovereenkomsten, stapsgewijze handleidingen, enz.) | Tijdelijke gebruikersinterface (menu's, tooltips, kaarten, toastmeldingen) |
| Lichte, afwijsbare | Ja | Ja |
| Vallen Focus | Ja | Nee |
| Inertpagina | Ja | Nee |
| Declaratieve activering | Ja | Ja |
| Uitvoering | Element | Attribuut |
| Renders in de bovenste laag | Ja | Ja |
| Volledig te stylen | Ja | Ja |
CSS-ankerpositionering
Zodra een popover verschijnt, moet deze ten opzichte van het element dat de popover heeft geopend, worden gepositioneerd. Het handmatig berekenen hiervan met JavaScript is onbetrouwbaar en kan de prestaties negatief beïnvloeden.
Vanaf Chrome 125 kun je de CSS Anchor Positioning API gebruiken. Deze nieuwe mogelijkheid koppelt op declaratieve wijze een element aan een ander element, waarbij de herpositionering automatisch wordt afgehandeld wanneer het element de rand van het scherm nadert. Deze functie maakt deel uit van Interop 2025 , een initiatief voor meerdere browsers om veelgevraagde functies te implementeren. We kunnen verwachten dat deze functie tegen het einde van 2025 in alle belangrijke browsers beschikbaar zal zijn.

Hoewel je elementen expliciet kunt koppelen met de eigenschappen anchor-name en position-anchor , zorgt een update in de specificatie en in Chrome 133 voor een impliciete ankerrelatie tussen een ` <popover> en de bijbehorende <button> . Dit vereenvoudigt de code aanzienlijk en betekent dat je de popover nu met één regel CSS kunt positioneren, bijvoorbeeld: position-area: bottom span-left .
De anchor-tool van chrome.dev laat zien hoe je position-area kunt gebruiken om de gewenste positionering te verkrijgen:
Ga nog een stap verder en laat de browser je ankers herpositioneren, zodat ze niet buiten beeld raken, door fallbacks te definiëren met position-try-fallbacks . De volgende demo toont een popover die deze eigenschap gebruikt voor ingebouwde herpositioneringslogica:
Een volledig aanpasbare <select>
Met deze bouwstenen in eerdere versies is web-native styling voor <select> -elementen eindelijk beschikbaar in Chrome 134. Dit omvat een nieuwe eigenschap appearance , nieuwe pseudo-elementen en het <selectedcontent> -element.
Om de aanpassingsmogelijkheden te ontgrendelen, pas je appearance: base-select; toe op het <select> `-element en het nieuwe pseudo-element ::picker(select) `, dat is gericht op de dropdownlijst met opties. Dit maakt nieuwe interne onderdelen voor styling beschikbaar, waaronder:
-
<selectedcontent>: Geeft de inhoud weer van de geselecteerde optie die in de knop wordt getoond. -
::picker-icon: Het pijltje naar beneden -
<option>:checkeden::checkmark: Voor het stylen van de geselecteerde optie en het bijbehorende vinkje

Dit maakt rijke content binnen opties mogelijk en biedt nauwkeurige controle over de weergave. Zo kunt u bijvoorbeeld een pictogram en een ondertitel in de optielijst weergeven, maar deze in de gesloten status verbergen met behulp van display: none binnen selectedcontent .
Het mooiste is dat deze API steeds verder kan worden uitgebreid. In browsers die deze functies niet ondersteunen, krijgen gebruikers nog steeds een functioneel web-native select-element te zien. Je krijgt een aangepaste look, terwijl de ingebouwde toegankelijkheid, toetsenbordnavigatie en formulierintegratie van het web-native select-element behouden blijven.
Carrousels
Carrousels zijn overal op het web te vinden, en niet alleen in hero-secties. Dit geldt ook voor horizontaal scrollbare content in compacte lay-outs zoals de gebruikersinterface van een app store. Maar het bouwen van carrousels op het web blijft een uitdaging, met veel aandachtspunten zoals state management, scroll-haperingen, interactiviteit en toegankelijkheid. Als je er goed over nadenkt, zijn carrousels in wezen gewoon fraaie scrollgebieden met extra UI-functionaliteiten.
Aan de slag met scrollers
Om een carrousel te maken, begin je met een lijst items die buiten de container vallen. Om de horizontale schuifbalk te verbergen terwijl de inhoud wel scrollbaar blijft, gebruik je scrollbar-width: none . Om het scrollen soepeler te laten verlopen, pas je ` scroll-snap-type en scroll-snap-align toe. Dit zorgt ervoor dat items op hun plaats springen wanneer de gebruiker scrollt.
Vorige en volgende met een ::scroll-button
Het nieuwe pseudo-element ::scroll-button() , dat is geïntroduceerd in Chrome versie 135, geeft de browser de opdracht om stateful, toegankelijke "volgende" en "vorige" knoppen te genereren. De browser handelt automatisch de juiste ARIA-rollen en tabvolgorde af en schakelt de knoppen zelfs uit wanneer je het begin of einde bereikt – allemaal zonder extra JavaScript.
Om de scrollknoppen te activeren, moet je ze inhoud en een toegankelijk label geven, zoals hieronder:
.carousel {
&::scroll-button(left) {
content: "⬅" / "Scroll Previous";
}
&::scroll-button(right) {
content: "⮕" / "Scroll Next";
}
}

Stijl deze knoppen en positioneer ze ten opzichte van de carrousel waar ze bij horen met behulp van CSS-ankerpositionering. Dit is de aanbevolen methode.
Directe navigatie met ::scroll-marker
Voor puntindicatoren of miniaturen koppelen de pseudo-elementen ::scroll-marker en ::scroll-marker-group navigatiemarkeringen rechtstreeks aan de items in uw scrollcontainer. De browser behandelt de groep als een tablist en verzorgt de toetsenbordnavigatie.
Net als bij scrollknoppen, initialiseer je de scrollmarkeringen door ze in te schakelen met de eigenschap content en geef je een toegankelijk label op. In het volgende voorbeeld wordt een `data`-attribuut gebruikt om het label voor de scrollmarkering in te stellen. Plaats de scrollmarkeringen vervolgens in de ::scroll-marker-group met behulp van de eigenschap scroll-marker-group . Stijl ten slotte de actieve markering met de nieuwe pseudo-klasse :target-current . Hier is een voorbeeld van hoe dit eruit zou kunnen zien voor een eenvoudige carrousel:
.carousel {
scroll-marker-group: after;
> li::scroll-marker {
content: ''/ attr(data-name);
}
> li::scroll-marker:target-current {
background: blue;
}
}

Scroll-statusquery's
Met nieuwe CSS-functies voor scrollen kun je dynamischere en interactievere carrousels maken. De `scroll-state` query is een nieuwe mediaquery die wordt toegepast op basis van de status van een scrollelement. Er zijn drie verschillende typen `scroll-state` queries, die toegankelijk zijn via scroll-state() in een @container statement. Dit zijn:
-
scroll-state(snapped): Komt overeen wanneer een element zich in de "snapped"-positie bevindt. In carrousels is dat het element dat in het midden van de carrousel is vastgezet. -
scroll-state(stuck): Stijl een element, zoals een koptekst, wanneer het bovenliggende element vast komt te zitten (scroll-state). -
scroll-state(scrollable): Voeg visuele indicatoren toe, zoals een fade-effect, om aan te geven dat er nog meer content is om naar te scrollen.
Alles samenbrengen
Een combinatie van nieuwe CSS-carouselprimitieven, scrollstatusquery's en ankerpositionering maakt het eenvoudiger om aangepaste en interactieve carousels te bouwen. Ga nog een stap verder door scrollgestuurde animaties te integreren om animaties direct aan de scrollpositie te koppelen. Dit creëert vloeiende effecten, zoals het schalen en vervagen van items tijdens het scrollen. Deze animaties worden uitgevoerd op de hoofdthread, wat zorgt voor een soepele gebruikerservaring.
Deze interactieve carrousel combineert scroll-state() queries, ::scroll-button , ::scroll-marker , CSS-ankerpositionering en :target-current .
Daarnaast kunt u een nieuwe eigenschap genaamd interactivity gebruiken om gebruikers te helpen zich te concentreren op de actieve inhoud. interactivity: inert kan de gebruiker inertie toepassen met behulp van CSS, waardoor carrouselitems buiten beeld niet focusseerbaar worden en uit de toegankelijkheidsstructuur worden verwijderd.
Leer meer over CSS-carrousels .
Interactieve hovercards
Hovercards – de uitgebreide pop-ups die verschijnen wanneer je met de muis over een gebruikersnaam of link beweegt – zijn ontzettend handig, maar staan erom bekend dat ze lastig zijn om correct te bouwen. Het goed krijgen van de vertragingen, de gebeurtenisafhandeling en de ondersteuning voor meerdere apparaten kan een toegewijd team maanden kosten. Maar we werken aan een nieuwe declaratieve oplossing die dit probleem voor eens en voor altijd moet oplossen.
Pop-ups die worden geactiveerd door interesse met [interestfor]
The core magic behind declarative hovercards is the [interestfor] attribute. This upcoming feature brings the power of popovers but triggers them based on user "interest." For example, user interest on a pointer device would be a pointer-hover, tab navigation with a keyboard, or a long-press or tap on touch screens. The mobile interaction is yet to be resolved.
Om een popover die op een klik reageert om te zetten naar een popover die op interesses reageert, maak je een aanroepend element aan. Dit kan een <button> of een <a> zijn. Geef dit element een [interestfor] -attribuut dat gelijk is aan de id van het [popover] -element. In HTML ziet het er zo uit:
<button interestfor="profile-callout">
...
</button>
<div id="profile-callout" popover>
...
</div>
De browser handelt alle complexe gebeurtenislogica af, waaronder:
- Invoer- en uitvoergebeurtenissen: zwevende beweging bij apparaten met een fijne aanwijzer, tabnavigatie met het toetsenbord, lang indrukken of aanraken bij apparaten met een grove aanwijzer.
- Vertragingen bij gebeurtenissen: Beheer de in- en uitlooptijd met één enkele CSS-eigenschap.
Deze functie ondersteunt andere popover-functies, zoals ondersteuning voor de bovenste laag, waarbij de popover op een nieuwe laag boven de rest van de DOM-structuur wordt weergegeven. De semantische componentbindingen en het onderliggende toegankelijkheidsboommodel worden native afgehandeld.
Stijlgerelateerde interesseopwekkers
Interesse-invokers bevatten een aantal nieuwe mogelijkheden. Een daarvan is de mogelijkheid om de in- en uitlogvertraging te regelen met behulp van een CSS-eigenschap: interest-target-delay . De andere is de mogelijkheid om het aanroepende element te stylen op basis van of het interesse heeft of niet, met behulp van de pseudo-klasse :has-interest .
[interesttarget] {
interest-target-delay: 0s 1s;
&:has-interest {
background: yellow;
}
}
popover="hint" en multifunctionele gebruikersinterface
Een belangrijk onderdeel van de puzzel voor het opwekken van interesse is een nieuw popover-type: popover="hint" . Het voornaamste verschil met andere popovers is dat een hint-popover andere popovers niet sluit wanneer deze wordt geopend. Dit is perfect voor tooltips of voorbeeldkaarten die moeten verschijnen zonder een reeds geopend menu of chatvenster te sluiten.
Browser Support
popover=auto | popover=manual | popover=hint | |
|---|---|---|---|
Lichte weergave uitschakelen (door weg te klikken of esc -toets te drukken) | Ja | Nee | Ja |
Sluit andere popover=auto elementen wanneer deze geopend worden. | Ja | Nee | Nee |
Sluit andere popover=hint elementen wanneer deze geopend worden. | Ja | Nee | Ja |
Sluit andere popover=manual elementen wanneer deze geopend worden. | Nee | Nee | Nee |
Je kunt de popover openen en sluiten met JavaScript ( showPopover() of hidePopover() ). | Ja | Ja | Ja |
| Standaard focusbeheer voor het volgende tabblad | Ja | Ja | Ja |
Kan worden verborgen of in- of uitgeschakeld met popovertargetaction | Ja | Ja | Ja |
Kan binnen het bovenliggende popover worden geopend om het bovenliggende venster open te houden. | Ja | Ja | Ja |
Hiermee kun je op declaratieve wijze krachtige, multifunctionele gebruikersinterfaces bouwen. Een enkele knop kan nu een automatische pop-up hebben met popovertarget voor de primaire klikactie (zoals het openen van een notificatiepaneel) en een hint-pop-up die wordt geactiveerd wanneer de muiswijzer over een knop beweegt en een handige tooltip weergeeft.
De toekomst is verklarend.
De hier besproken functies vertegenwoordigen een fundamentele verschuiving naar een krachtiger en declaratief webplatform. Door de browser het complexe, repetitieve werk van statusbeheer en toegankelijkheid te laten afhandelen, kunnen we bergen JavaScript verwijderen, de prestaties verbeteren en ons concentreren op waar we het beste in zijn: het creëren van innovatieve en boeiende gebruikerservaringen. Dit is werkelijk een gouden tijdperk voor web-UI, en het staat nog maar aan het begin. Volg hier mee terwijl we werken aan een krachtiger en gebruiksvriendelijker web.
Aanvullende informatie: