Stand van webcomponenten

Webcomponenten zijn aangepaste elementen, Shadow DOM en HTML-templates: de platformprimitieven voor herbruikbare, framework-agnostische componenten waarvan de opmaak en stijlen zijn ingekapseld in het document. Gebruik ze voor ontwerpsystemen, insluitbare widgets en zelfstandige UI.

De regels hieronder zijn overkoepelend. Haal de specifieke handleiding voor de taak op. In elke handleiding wordt de context herhaald die nodig is en worden de API's en valkuilen beschreven die uniek zijn voor de taak.

Bepaal of je wel een aangepast element nodig hebt

Gebruik alleen een aangepast element als je ingekapseld gedrag, een levenscyclus of een herbruikbare JS-ondersteunde API voor een tag nodig hebt. Maak geen website als:

  • Een gewoon HTML-element met CSS is voldoende. Een gestileerde <button> of <details> is toegankelijker en goedkoper dan een herimplementatie.
  • Het ding is puur presentatiegericht en heeft geen gedrag. Een klasse voor een native element presteert beter en kan worden beperkt met @layer of @scope.
  • Je hebt alleen stijlscoping op de server nodig zonder interactiviteit. Een stylesheet met bereik of Declarative Shadow DOM (zonder upgrade) is misschien voldoende.

Het opnieuw opbouwen van systeemeigen semantiek (een aangepaste <my-button> die focus, activering en ARIA opnieuw maakt) is het meest voorkomende misbruik: je krijgt de toegankelijkheid van het platform alleen kosteloos als je het systeemeigen element opnieuw gebruikt. Als een wrapper in de stijl van <my-button> gerechtvaardigd is (meestal voor gedeelde stijlhooks, extra opmaak of gedrag dat een native element niet kan uitdrukken), verpakt u de echte <button> in plaats van deze opnieuw te implementeren (ga naar Styling Web Components voor het doorsturen van stijlen naar een intern native element).

De test is of je een ingekapselde status, een scriptbare API of gedrag dat het native element niet kan uitdrukken nodig hebt, niet alleen een andere look. Een schakelaar voor liken/favoriet is geschikt: deze heeft een vergrendelde domeinstatus, toont die status als een stylinghook voor de omringende pagina en stuurt een eigen change-gebeurtenis. Een gestylede <button> biedt geen van deze mogelijkheden. Een knop die alleen van kleur verandert als je erop drukt, doet dat niet: gebruik <button> + CSS. Als je het element maakt, modelleer je de status met een aangepaste status of een kenmerk (zie Aangepaste elementen).

De tool afstemmen op de codebase

Of iets een aangepast element moet zijn, hangt af van wat het project al gebruikt. Agenten hebben de neiging om te veel te abstraheren en te snel naar een nieuw element te grijpen. Bij twijfel is de lichtere optie (native element, CSS, een servertemplate) meestal de juiste. Je kunt later upgraden naar een aangepast element als hergebruik of gedrag dit vereist. Heuristiek, in ruwe prioriteit:

  • De codebase heeft al een componentmodel (React, Vue, Svelte, …). Gebruik standaard de component van dat framework voor de in-app UI. Gebruik alleen een aangepast element als het element buiten het framework moet vallen of het framework moet overleven: een primitief ontwerpsysteem dat wordt gedeeld tussen apps of frameworks, een widget die is neergezet in opmaak die het framework niet beheert, of uitvoer die moet werken als platte HTML (e-mail, CMS, SSR-fragmenten). Stel geen parallel componentsysteem in voor gewone in-app weergaven.
  • Geen tools, voornamelijk statische opmaak. Gebruik bij voorkeur gewone HTML + CSS of een servertemplate/gedeeltelijke template. Een aangepast element is alleen nuttig als je echt gedrag, een levenscyclus of een door JS ondersteunde API op de tag nodig hebt, niet alleen om opmaak te delen, wat een server-include of <template> doet zonder JS te verzenden.
  • Generator voor statische sites met interactieve elementen. Geef de opmaak statisch weer. Reserveer het aangepaste element voor het interactieve gedeelte. Voor 'veel opmaak, een beetje interactiviteit' houd je de opmaak in Light DOM (of Declarative Shadow DOM) en laat je een klein aangepast element deze geleidelijk verbeteren, in plaats van alles opnieuw te renderen vanuit JS.
  • Je kunt ook een ingebouwd element verder pushen. Het is meestal beter om een native element zo ver mogelijk te gebruiken (CSS, een paar listeners, af en toe een pseudoelement) dan een aangepast element, omdat je de toegankelijkheid en het gedrag van het platform kosteloos behoudt. Stap over op een aangepast element als de tijdelijke oplossingen niet meer te onderhouden zijn, als je het ingebouwde gedrag van het element tegenwerkt of als de ontwerpervaring slechter wordt dan een schone component-API zou zijn. Als je een beetje JS nodig hebt voor een ingebouwd element, is dat op zich geen reden om het te vervangen.

Overkoepelende regels

Deze gelden voor elke gids hieronder:

  • VERPLICHT: De tagnaam moet kebab-case zijn met minstens één koppelteken (bijv. my-element). Zo onderscheid je aangepaste elementen van huidige en toekomstige ingebouwde elementen.
  • VERPLICHT: Roep super() eerst aan in de constructor voordat je this aanraakt. Als je deze aanroept na een instructie die this leest of schrijft, wordt er een uitzondering gegenereerd.
  • VERPLICHT: Gebruik semantische elementen (<button>, <nav>, <ul>) in schaduwtemplates. De meeste toegankelijkheidsfouten in schaduwbomen komen door niet-semantische opmaak. Een slot verandert de rol van wat het projecteert niet.
  • VERPLICHT: ARIA-id-verwijzingen (aria-labelledby, aria-describedby, aria-controls) kunnen geen schaduwgrens overschrijden. Het verwijzende element en de id waarnaar het verwijst, moeten zich in dezelfde boomstructuur bevinden.
  • Geef de voorkeur aan attachShadow({ mode: 'open' }), zodat ontwikkelaarstools, paginascripts en serverhydratatie element.shadowRoot kunnen bereiken. Gebruik 'closed' alleen als je de interne structuur moet verbergen voor paginascripts.
  • Vermijd aangepaste ingebouwde elementen (extends HTMLButtonElement met is="…"). Safari heeft permanent geweigerd deze te leveren.

Matrix met use cases

De taak identificeren en de handleiding ophalen:

Als je het volgende wilt doen: Ophalen
Een nieuwe semantische tag definiëren met gedrag en levenscyclus Aangepaste elementen
Stijlen en opmaak beperken tot een component en consumentencontent erin projecteren Shadow DOM, Templates en Slots
De schaduwstructuur van een component op de server (SSR) renderen zonder een flits van niet-opgemaakte content Aangepaste elementen vooraf renderen
Stijl over de schaduwgrens (thema's, ::part, aangepaste eigenschappen) Webcomponenten opmaken
De waarde van een aangepaste bediening indienen bij een omringende <form> Aan formulieren gekoppelde aangepaste elementen
Een aangepast element toegankelijk maken (rollen, focus, ARIA voor shadow roots) Toegankelijke webcomponenten