This extension will find any custom element on a page.
Container Queries with the <watched-box>
Custom Element
Heydon Pickering has created <watched-box>
:
I wanted a simple, declarative container queries solution, and here it is:
- ❤ Custom Element +
ResizeObserver
- 🥣 Use and mix together any CSS length units
- 🖼 Orientation supported
- 🧚♀️ ≅1.5KB minified
Once imported you can use it as follows:
<watched-box widthBreaks="70ch, 900px" heightBreaks="50vh, 60em">
<!-- HTML and text stuff here -->
</watched-box>
<watched-box>
will then automatically add the proper classes:
- Less than or equal to the supplied width:
w-lte-[the width]
- Greater than the supplied width:
w-gt-[the width]
- Less than or equal to the supplied height:
h-lte-[the height]
- Greater than the supplied height:
h-gt-[the height]
Rendering Markdown using Custom Elements v1
Inspired upon a v0 implementation, I’ve recreated a Markdown renderer in Custom Elements v1. The result is <custom-markdown>
.
The code itself is pretty straightforward: other than some (contained) styling the custom element uses showdown to convert the Markdown to HTML. This conversion is triggered in the connectedCallback()
.
class Markdown extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({mode: 'closed'});
shadowRoot.innerHTML = `
<style>
:host { display: block; font-family: monospace; }
</style>
<div class="output"></div>
`;
this.output = shadowRoot.querySelector('.output');
this.converter = new showdown.Converter();
}
connectedCallback() {
this.output.innerHTML = this.converter.makeHtml(this.innerHTML);
}
};
customElements.define('custom-markdown', Markdown);
Here’s a working example (if your browser supports it):
See the Pen Custom Elements v1: Render Markdown with <custom-markdown> by Bramus (@bramus) on CodePen.
Related: Introducing Custom Elements →
Web Components: Introducing Custom Elements
One of the new features in Safari Technology Preview 18 is Custom Elements v1 (Chrome/Opera already support for it):
To define a custom element, simply invoke
customElements.define
with a new local name of the element and a subclass ofHTMLElement
.
Example Code:
class CustomProgressBar extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({mode: 'closed'});
shadowRoot.innerHTML = `
<style>
:host { display: inline-block; width: 5rem; height: 1rem; }
.progress { display: inline-block; position: relative; border: solid 1px #000; padding: 1px; width: 100%; height: 100%; }
.progress > .bar { background: #9cf; height: 100%; }
.progress > .label { position: absolute; top: 0; left: 0; width: 100%;
text-align: center; font-size: 0.8rem; line-height: 1.1rem; }
</style>
<div class="progress" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
<div class="bar" style="width: 0px;"></div>
<div class="label">0%</div>
</div>
`;
this._progressElement = shadowRoot.querySelector('.progress');
this._label = shadowRoot.querySelector('.label');
this._bar = shadowRoot.querySelector('.bar');
}
get progress() { return this._progressElement.getAttribute('aria-valuenow'); }
set progress(newPercentage) {
this._progressElement.setAttribute('aria-valuenow', newPercentage);
this._label.textContent = newPercentage + '%';
this._bar.style.width = newPercentage + '%';
}
};
customElements.define('custom-progress-bar', CustomProgressBar);
Once defined you can then use it as follows in your HTML:
<custom-progress-bar"></custom-progress-bar>
It is also possible to create instances using JavaScript, and to define the allowed attributes for custom elements (and listen for changes on them).