Posted 2 months ago. Visible to the public. Repeats.

Defining new elements for your HTML document

Browsers come with a set of built-in elements like <p> or <input>. When we need a new component not covered by that, we often build it from <div> and <span> tags. An alternative is to introduce a new element, like <my-element>.

When a browser encounters an unknown element like <my-element>, the browser will proceed to render <my-element>'s children. The visual rendering of your page will not be affected.

If you care about their HTML being valid, your new element should contain a dash character (-) to mark it as a custom element. Custom elements will be ignored for the purposes HTML validation, but their children will still be validated.

Styling new elements

Browsers will give unknown elements a default style of display: inline. This way the element will not affect the layout flow.

You may style new elements with CSS:

Copy
my-element { display: block; font-weight: bold; }

If you have been in web development for a long time, you might remember browsers not applying styles to unknown elements. This was fixed in Internet Explorer 9, and hasn't been an issue for a decade.

If your new element isolates its children in a shadow DOM, they do not inherit styles from the document. See Styling a Web Component for this case.

Applying JavaScript behavior to new elements

All client-side JavaScript frameworks comes with mechanisms to activate JavaScript behavior on certain DOM elements. E.g. in Unpoly uses compilers for that purpose. Instead of using a framework mechanism you may use customElements.define() to register your custom element's JavaScript behavior with the browser directly.

A big advantage of using the browser's customElements.define() is that your new element does not not need to be compiled or activated after insertion. Attaching a <my-element> to the document will automatically activate the registered behavior. This decouples your custom element from a particular JavaScript framework.

Here is an example:

Copy
class MyElement extends HTMLElement { connectedCallback() { // the element was added to the DOM } disconnectedCallback() { // the element was removed from the DOM } attributeChangedCallback(attribute, oldValue, newValue) { // the given attribute was changed } foo() { // a custom method } } customElements.define('my-element', MyElement)

Note that this class automatically describes the JavaScript API for your new element. The DOM node objects are their own JavaScript representation:

Copy
let newElement = new MyElement() document.body.appendChild(newElement) let queriedElement = document.querySelector('my-element') console.log(newElement === queriedElement) // true queriedElement.foo()

Transpiling custom elements

Note that custom element classes must not be transpiled down to ES5 prototypes. You must send native ES6 classes to the browser. All browsers except IE11 have been supporting ES6 classes natively your years, so you might want to stop dumbing down your ES6 classes anyway.

makandra has been working exclusively with Ruby on Rails since 2007. Our laser focus on a single technology has made us a leader in this space.

Owner of this card:

Avatar
Henning Koch
Last edit:
2 months ago
by Besprechungs-PC
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Henning Koch to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more