Web Components/custom elements

Aus SELFHTML-Wiki
< Web Components(Weitergeleitet von Custom element)
Wechseln zu: Navigation, Suche
Web Components Logo

Mit Web Components haben Sie die Möglichkeit, eigene benutzerdefinierte Elemente (englisch: custom elements) zu erstellen. Dies können neue HTML-Tags mit besonderen Aufgaben oder die Erweiterung bestehender Tags sein.

Gegenüber externen Plugins haben custom elements den Vorteil, dass sie …

  • als HTML-Elemente ein einheitliches Markup besitzen,
  • miteinander kombinier- und schachtelbar sind sowie
  • ihren inneren Aufbau (HTML, CSS, JS) kapseln und so Konflikte mit anderen Plugins oder Scripts auf der Webseite verhindern.

Regeln

Benutzerdefinierte Elemente (englisch: custom elements) folgen einigen Regeln, damit Parser sie von regulären HTML-Elementen unterscheiden können:

  • Namen von benutzerdefinierten Elementen müssen immer einen Bindestrich enthalten.
    Beispiele: <x-line>, <mein-element>
    Dies sichert auch eine Vorwärts-Kompatibilität eventueller neuer Tags.
    (Google trackt die Verwendung von custom elements und plant, „erfolgreiche“ Elemente in den Standard zu übernehmen.)
  • Ein Tag kann nur einmal registriert werden, sonst gibt es einen DOMException-Fehler
  • Benutzerdefinierte Elemente müssen immer mit einem schließenden Tag geschlossen werden.
    Beispiel: <x-line>…</x-line>

Verwendung

neue Elemente

Um einem benutzerdefinierten Element eine Funktion zu geben, muss diese Funktion in einer Klasse definiert werden:

HTML:
<my-element></my-element>
Javascript:
class myElement extends HTMLElement {
 ...
}
customElements.define('my-element', myElement);

Diese Klasse muss einen Konstruktor haben, sowie bedarfsabhängig den Getter

  • observedAttributes: legt fest, auf welche Attributänderungen reagiert werden soll,

und die Methoden

  • connectedCallback: Wird aufgerufen, wenn das Element zu ersten Mal erstellt wird.
  • disconnectedCallback: Wird aufgerufen, wenn das Element entfernt wird.
  • adoptedCallback: Wird aufgerufen, wenn das Element in ein anderes Dokument geschoben wird.
  • attributeChangedCallback: Wird aufgerufen, wenn ein Element-Attribut hinzugefügt, geändert oder entfernt wird. Übergabeparameter sind der Attributname, der Wert vor und der Wert nach der Änderung. Beim ersten Aufruf hat oldValue den Wert null.

Das Grundgerüst für ein benutzerdefiniertes Element kann dann so aussehen:

Javascript:
// Custom-Element my-element anlegen
class myElement extends HTMLElement {
	
	// Festlegen, welche Attribute überwacht werden solle
	static get observedAttributes() {
		return ['attribut1', 'attribut2'];
	}
	
	constructor() {
		// Element wird anlgelegt
		
		// super muss als erstes im constructor aufgerufen werden, super ruft den construcor der Elternklasse auf
		super(); 
		
		// Schatten-Dom anlegen
			// mode: 'open' : Vom Dokument aus ist der Zugriff auf das Schatten-Dom möglich.
			// mode: 'closed' : Der Zugriff auf das Schatten-Dom ist nicht möglich.
		const shadow = this.attachShadow({mode: 'open'});

		// Element für Inhalt anlegen und ins Schatten-Dom einhängen
		const contend = document.createElement('div');
		contend.className = "contend";
		shadow.appendChild(contend);
		
		// CSS anlegen und ins Schatten-Dom einhängen
		// :host selektiert das Custom Element
		const style = document.createElement('style');
		style.textContent = `
			:host { … }	
			.contend { … }
		`;
		shadow.appendChild(style);
		
		// Weiterer Code
	}

	connectedCallback() {
		// Element wurde ins DOM eingehängt
	}
	
	disconnectedCallback () {
		// Element wurde entfernt
	}
	
	adoptedCallback() {
		// Element ist in ein anderes Dokument umgezogen
	}

	attributeChangedCallback(name, oldValue, newValue) {
		// Elementparameter wurden geändert
		// Achtung attributeChangedCallback wird vor connectedCallback aufgerufen
	}

}
customElements.define('my-element', myElement);

bestehende Elemente erweitern

Sie können bestehende Elemente um neue Fähigkeiten erweitern, so z. B. ein p-Element um eine Eigenschaft, die die Anzahl der Wörter zählt oder ein Shadow DOM an das Element hängt.[1]

customElements.define('word-count', WordCount, { extends: 'p' });

Anwendungsbeispiele

Gedicht mit Zeilen

benutzerdefinierte Elemente für eine Zeile ansehen …
<blockquote>
	<p>
		<x-line>Someday girl I don't know when we're gonna get to that place</x-line><br>
		<x-line>Where we really want to go and we'll walk in the sun</x-line><br>
		<x-line>But till then tramps like us baby we were born to run</x-line>
	</p>
	<footer><cite>Bruce Springsteen, “Born to Run”</cite></footer>
</blockquote>
Anstelle von hier semantisch nicht passenden Zeilumbrüchen (br) sind die Zeilen in einem x-line-Element notiert.
x-line {
	display: block;
	--indent: 0.8em;
	padding-left: var(--indent);
	text-indent: calc(-1 * var(--indent));
}

x-line + br {
	/* for WebKits */
	content: '';
	
	/* visually hidden; for Firefox */
	position: absolute !important;
	height: 1px;
	width: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
}
Diese erhalten mit CSS ein display:block und werden so untereinander dargestellt.[2]

Ein custom element hat per se dieselbe Semantik wie ein span oder div – nämlich gar keine. Jedenfalls für eine Maschine (Browser); für menschliche Code-Leser mag x-l aussagekräftiger sein als span (wobei es dann vielleicht besser x-line heißen sollte).

Ein Grund für das custom element ist Faulheit: <x-line> ist kürzer als <span class="line">. Was auch der Lesbarkeit des Codes zugutekommt.

Ein anderer Grund ist, dass AFAIK Google die Häufigkeit der Verwendung von Elementtypen (also auch von custom elements) trackt und damit Zahlen in der Hand hat, die für eine mögliche Einführung neuer Elementtypen in den HTML-Standard sprechen könnten. Vielleicht kommt ja doch noch in HTML irgendwann ein l-Element wie es in XHTML 2 vorgesehen war.

SELF-Forum Semantische Verwendung von br von Gunnar Bittersmann am 21.09.2018

Listen im Tabellen-Look

Im Forum wurde gefragt, wie man Listenelemente mit Tabulatoren formatieren könnte. Mit custom elements können die einzelnen Teile der Adresse erkannt und passend formatiert werden:[3]

benutzerdefinierte Elemente für Adresselemente ansehen …
<ul>
	<li>
		<x-postal-code>40233</x-postal-code>
		<x-locality>Düsseldorf</x-locality>
		<x-location>Capitol-Theater</x-location>
	</li>
	<li>
		<x-postal-code>10117</x-postal-code>
		<x-locality>Berlin</x-locality>
		<x-location>Admiralspalast</x-location>
	</li>
</ul>
ul {
	display: table;
	padding-left: 0;
	font: 1.5em Candara;
}

li {
	display: table-row;
}

li > * {
	display: table-cell;
	padding: 0 0.5em;
}

li > :first-child::before {
	content: '•';
	margin-right: 0.5em;
}

x-postal-code {
	font-feature-settings: "tnum", "lnum";	
}
Die Ziffern sollten bei den PLZ gleichbreit sein (tabular figures "tnum"). Zur Verdeutlichung wurde im Beispiel die Microsoft-Schriftart Candara gewählt. Ohne "tnum" in der font-feature-settings-Angabe wären die Ziffern unterschiedlich breit. (Und ohne "lnum" wären es Mediävalziffern.)

Die Custom elements mit einem - im Bezeichner verwenden sprechende Namen wie <x-postal-code> und <x-locality>. Allerdings gibt es hier keinen Vorteil gegenüber <span class="postal-code"> bzw. <span class="locality">.

Empfehlung: Besser wäre eine semantische Auszeichnung mit RDFa, die ohne Klassen auskommt: <span property="postalCode"> und <span property="addressLocality">.

Beispiele im Netz

In den Tutorials wimmelt es von Beispielen, die nur das Prinzip veranschaulichen, aber keinen Nutzen bringen, wie das <x-treehouse>-Element im ebenso benannten Blog oder der <x-greeter> im Self-Blog von 2014. Die <howto-checkbox> bringt sogar Nachteile mit sich: das Standardverhalten der Tastaturbedienung muss erst noch nachgebaut werden, innerhalb von form-Elementen sind keine custom elements erlaubt, sodass Eingaben über ein versteckes input-Element importiert werden müssen.

Trotzdem gibt es einige Beispiele, die einen zweiten Blick lohnen:

Weblinks


  1. High-Level-Ansicht (MDN)
  2. SELF-Forum: semantische Verwendung von br (und doch nichts für Screenreader) von Gunnar Bittersmann am 21.09.2018
  3. SELF-Forum: Dürfen HTML-Tags (z. B. Tabulatoren) erfunden werden? von Gunnar Bittersmann am 30.03.2019

Siehe auch