Browsers create ANY tag with at least one dash as a *Custom Element*
They come in TWO flavours, and since they ARE HTMLElement, can be used for layout AND styling with CSS.
The official names are:
► UNdefined Custom Elements (the article calls these "CSS Web Components")
- shadowDOM optional with Declarative ShadowDOM
► Defined Custom Elements
- Defined with the JavaScript Custom Elements API
- shadowDOM optional
- A new Element, or an UPGRADED existing UNdefined Custom Element
---
### Good to know about UNDEFINED Custom Elements:
* Absolutely NO JavaScript required, it is only HTML and CSS
* This is STANDARD behaviour in all browsers for nearly a DECADE now:
Chrome (2016) Safari (2017) FireFox (2018)
* The W3C HTML Validator accepts ALL <tag-name> Custom Elements with a dash as HTMLElement.
It does not accept <tagname> (no dash), those are HTMLUnknownElement
* Custom Elements do not inherit the standard [hidden] behaviour;
so you have to add that behaviour yourself in your stylesheet.
* Same for DIVs display:block. You have to set the display property on these Custom Elements yourself.
(You will forget this 20 times, then you never make the mistake again)
* The :defined pseudo selector targets standard HTML tags and JavaScript defined Custom Elements
* Thus :not(:defined) targets the UNdefined Custom Elements; again... they are still valid HTMLElement so CSS applies like any element
* <you-are-not-bound-to-one-dash>
* Declarative ShadowDOM <template shadowrootmode="open"> creates the same UNdefined Custom Elements WITH a shadowDOM
* The Custom Elements JavaScript API upgrades UNdefined Custom Elements TO defined Custom Elements.
* You can't UNdefine defined Custom Elements
* You can't REMOVE a set shadowRoot
* for now, only Safari supports multiple custom element registries (duplicating Custom Element names)
----
Why?
► Try to find that closing </div> in a long HTML page. </tag-name> is always just there.
► Built a UI that doesn't FOUC, and UPGRADE it lazy-loaded with more logic and interactivity... you can not do this with technologies that CREATE HTML AFTER DOM was parsed.
Custom Elements/Web Components ARE HTML; Frameworks CREATE HTML
We will forever call Custom Elements: Web Components, and vice versa...
◄ <tagname> = always an HTMLUnknownElement until the WHATWG adds it as new Element.
◄ <tag-name> = (No JS!) UNDEFINED Custom Element, valid HTMLElement, great for layout and styling
◄ Upgraded with the JavaScript Custom Elements API it becomes a DEFINED Custom Element
---
► This is standard behaviour in all browsers. Chrome (2016) Safari (2017) FireFox (2018) Edge (2020)
► The W3C HTML Validator accepts all <tag-name> Custom Elements with a dash as HTMLElement.
It does not accept <tagname> (no dash), those are HTMLUnknownElement
► The UA - UserAgent StyleSheet (Browsers default stylesheet)
defines CSS [hidden] { display:none }.
But Custom Elements do not inherit the default stylesheet;
so you have to add that behaviour yourself in your stylesheet.
► <DIV> is display:block only in the UA StyleSheet
You have to set the display property on these Custom Elements yourself
(You will forget this 20 times, then you never make the mistake again)
► The CSS :defined pseudo selector targets standard HTML tags and JavaScript defined Custom Elements
► Thus the CSS :not(:defined) pseudo selector targets the UNDEFINED Custom Elements; they are still valid HTMLElement, CSS applies like any element
► DSD - Declarative ShadowDOM:
<template shadowrootmode="open"> creates the same undefined Custom Elements with a shadowDOM
this.querySelector will return nothing when you define this Web Component before (light)DOM is parsed, because the connectedCallback fires on the opening tag.
Above code will only work when the Web Component is defined after DOM has parsed; using "defer" or "import" makes your JS file execute after DOM is parsed, you "fixed" the problem without understanding what happened.
The article isn't complete/correct.
Something did change with HTML.
Since 2018 every browser interprets ANY <tag-name> with a dash as a valid HTMLElement, not HTMLUnknownElement.
Absolutly NO JavaScript required to turn the DIV-soup into
<semantic-html> and CSS
> there are no weird rendering glitches or timing issues or weird gotchas that you have to dig into to.
Ehm... define the Web Component render blocking in the head, because you want to prevent FOUCs.
Then try to access the .innerHTML of your Web Component in the connectedCallback
Browsers create ANY tag with at least one dash as a *Custom Element*
They come in TWO flavours, and since they ARE HTMLElement, can be used for layout AND styling with CSS.
The official names are:
► UNdefined Custom Elements (the article calls these "CSS Web Components")
► Defined Custom Elements - Defined with the JavaScript Custom Elements API
---
### Good to know about UNDEFINED Custom Elements:
* Absolutely NO JavaScript required, it is only HTML and CSS
* This is STANDARD behaviour in all browsers for nearly a DECADE now: Chrome (2016) Safari (2017) FireFox (2018)
* The W3C HTML Validator accepts ALL <tag-name> Custom Elements with a dash as HTMLElement. It does not accept <tagname> (no dash), those are HTMLUnknownElement
* Custom Elements do not inherit the standard [hidden] behaviour; so you have to add that behaviour yourself in your stylesheet.
* Same for DIVs display:block. You have to set the display property on these Custom Elements yourself. (You will forget this 20 times, then you never make the mistake again)
* The :defined pseudo selector targets standard HTML tags and JavaScript defined Custom Elements
* Thus :not(:defined) targets the UNdefined Custom Elements; again... they are still valid HTMLElement so CSS applies like any element
* <you-are-not-bound-to-one-dash>
* Declarative ShadowDOM <template shadowrootmode="open"> creates the same UNdefined Custom Elements WITH a shadowDOM
* The Custom Elements JavaScript API upgrades UNdefined Custom Elements TO defined Custom Elements.
* You can't UNdefine defined Custom Elements
* You can't REMOVE a set shadowRoot
* for now, only Safari supports multiple custom element registries (duplicating Custom Element names)
----
Why?
► Try to find that closing </div> in a long HTML page. </tag-name> is always just there.
► Built a UI that doesn't FOUC, and UPGRADE it lazy-loaded with more logic and interactivity... you can not do this with technologies that CREATE HTML AFTER DOM was parsed.
Custom Elements/Web Components ARE HTML; Frameworks CREATE HTML
We will forever call Custom Elements: Web Components, and vice versa...