web-components-examples
A series of web components examples, related to the MDN web components documentation at https://developer.mozilla.org/en-US/docs/Web/Web_Components.
Top Related Projects
Our original Web Component library.
A toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, and traditional web developers from a single, framework-agnostic codebase.
Lit is a simple library for building fast, lightweight web components.
⚡️ LWC - A Blazing Fast, Enterprise-Grade Web Components Foundation
Quick Overview
The mdn/web-components-examples repository is a collection of example code for Web Components, maintained by the Mozilla Developer Network (MDN). It serves as a practical resource for developers learning about Web Components, providing various implementations and use cases.
Pros
- Comprehensive collection of Web Component examples
- Maintained by MDN, ensuring high-quality and up-to-date content
- Covers a wide range of Web Component features and use cases
- Excellent learning resource for both beginners and experienced developers
Cons
- Not a standalone library or framework
- Examples may not cover all possible edge cases or complex scenarios
- Some examples might become outdated as Web Component specifications evolve
- Limited to Web Components only, not covering other web development topics
Code Examples
- Creating a custom element:
class WordCount extends HTMLParagraphElement {
constructor() {
super();
// Count words in element's parent element
const wcParent = this.parentNode;
function countWords(node) {
const text = node.innerText || node.textContent;
return text.split(/\s+/g).length;
}
const count = `Words: ${countWords(wcParent)}`;
// Create a shadow root
const shadow = this.attachShadow({mode: 'open'});
// Create text node and add word count to it
const text = document.createElement('span');
text.textContent = count;
// Append it to the shadow root
shadow.appendChild(text);
}
}
// Define the new element
customElements.define('word-count', WordCount, { extends: 'p' });
- Using HTML templates:
<template id="my-paragraph">
<p>My paragraph</p>
</template>
<script>
class MyParagraph extends HTMLElement {
constructor() {
super();
const template = document.getElementById('my-paragraph');
const templateContent = template.content;
this.attachShadow({mode: 'open'}).appendChild(
templateContent.cloneNode(true)
);
}
}
customElements.define('my-paragraph', MyParagraph);
</script>
- Using Shadow DOM:
class PopUpInfo extends HTMLElement {
constructor() {
super();
// Create a shadow root
const shadow = this.attachShadow({mode: 'open'});
// Create spans
const wrapper = document.createElement('span');
wrapper.setAttribute('class', 'wrapper');
const icon = document.createElement('span');
icon.setAttribute('class', 'icon');
icon.setAttribute('tabindex', 0);
const info = document.createElement('span');
info.setAttribute('class', 'info');
// Take attribute content and put it inside the info span
const text = this.getAttribute('data-text');
info.textContent = text;
// Insert icon
let imgUrl;
if(this.hasAttribute('img')) {
imgUrl = this.getAttribute('img');
} else {
imgUrl = 'img/default.png';
}
const img = document.createElement('img');
img.src = imgUrl;
icon.appendChild(img);
// Create some CSS to apply to the shadow dom
const style = document.createElement('style');
console.log(style.isConnected);
style.textContent = `
.wrapper {
position: relative;
}
.info {
font-size: 0.8rem;
width: 200px;
display: inline-block;
border: 1px solid black;
padding: 10px;
background: white;
border-radius: 10px;
opacity: 0;
transition: 0.6s all;
position: absolute;
bottom: 20px;
left: 10px;
z-index: 3;
}
img {
width: 1.2rem;
}
.icon:hover + .info, .icon:focus + .info
Competitor Comparisons
Our original Web Component library.
Pros of Polymer
- Comprehensive library with a full suite of tools and components
- Offers data binding and property observation out of the box
- Provides a more opinionated structure for building web components
Cons of Polymer
- Steeper learning curve due to its extensive API and concepts
- Larger bundle size compared to vanilla web components
- Less flexibility in implementation choices
Code Comparison
web-components-examples:
<template id="element-details-template">
<details>
<summary>
<span>
<code class="name"><<slot name="element-name">NEED NAME</slot>></code>
<i class="desc"><slot name="description">NEED DESCRIPTION</slot></i>
</span>
</summary>
<div class="attributes">
<h4>Attributes</h4>
<slot name="attributes"><p>None</p></slot>
</div>
</details>
</template>
Polymer:
<dom-module id="element-details">
<template>
<details>
<summary>
<span>
<code class="name"><[[name]]></code>
<i class="desc">[[description]]</i>
</span>
</summary>
<div class="attributes">
<h4>Attributes</h4>
<template is="dom-if" if="[[!attributes.length]]">
<p>None</p>
</template>
<template is="dom-repeat" items="[[attributes]]">
<p><code>[[item.name]]</code>: [[item.description]]</p>
</template>
</div>
</details>
</template>
</dom-module>
A toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, and traditional web developers from a single, framework-agnostic codebase.
Pros of Stencil
- Provides a complete toolchain for building and optimizing web components
- Offers TypeScript support out of the box for better type checking and developer experience
- Includes a virtual DOM for efficient rendering and updates
Cons of Stencil
- Has a steeper learning curve due to its more complex architecture
- Requires additional build steps, which may increase development time
- May introduce unnecessary overhead for simple web component projects
Code Comparison
Stencil component:
@Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true
})
export class MyComponent {
@Prop() name: string;
render() {
return <div>Hello, {this.name}</div>;
}
}
web-components-examples vanilla JS component:
class MyComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.shadowRoot.innerHTML = `<div>Hello, ${this.getAttribute('name')}</div>`;
}
}
customElements.define('my-component', MyComponent);
The Stencil example showcases its TypeScript integration and decorator-based approach, while the web-components-examples repository demonstrates a more straightforward vanilla JavaScript implementation of web components.
Lit is a simple library for building fast, lightweight web components.
Pros of lit
- Provides a lightweight, performant library for building web components
- Offers reactive properties and efficient rendering with lit-html
- Includes TypeScript support out of the box
Cons of lit
- Requires learning a specific library and syntax
- May introduce additional complexity for simple components
- Slightly larger bundle size compared to vanilla web components
Code Comparison
web-components-examples:
class WordCount extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.shadowRoot.innerHTML = `<p>Word count: ${this.countWords()}</p>`;
}
}
lit:
import { LitElement, html } from 'lit';
class WordCount extends LitElement {
render() {
return html`<p>Word count: ${this.countWords()}</p>`;
}
}
The web-components-examples repository focuses on vanilla web components, providing straightforward examples without additional libraries. It's ideal for learning the fundamentals of web components and understanding their core concepts.
lit, on the other hand, offers a more opinionated approach with its own library. It simplifies component creation and provides additional features like reactive properties and efficient rendering. While it requires learning a specific library, it can lead to more maintainable and performant components for larger applications.
⚡️ LWC - A Blazing Fast, Enterprise-Grade Web Components Foundation
Pros of LWC
- More comprehensive framework with built-in performance optimizations
- Tighter integration with Salesforce ecosystem and data model
- Extensive documentation and learning resources
Cons of LWC
- Steeper learning curve due to Salesforce-specific concepts
- Limited use outside of Salesforce platform
- More opinionated structure, potentially less flexible for custom implementations
Code Comparison
LWC component:
import { LightningElement, api } from 'lwc';
export default class Greeting extends LightningElement {
@api name;
}
Web Components example:
class Greeting extends HTMLElement {
constructor() {
super();
this.name = '';
}
connectedCallback() {
this.render();
}
}
customElements.define('my-greeting', Greeting);
Key Differences
- LWC uses a more declarative approach with decorators
- Web Components examples are closer to vanilla JavaScript
- LWC provides additional features like reactive properties and lifecycle hooks
- Web Components examples offer more flexibility but require more boilerplate code
Use Cases
- LWC: Ideal for Salesforce-based applications and developers working within the Salesforce ecosystem
- Web Components examples: Better suited for learning core Web Components concepts and implementing custom elements in various web projects
Community and Support
- LWC: Strong support from Salesforce, active community within Salesforce ecosystem
- Web Components examples: Broader web development community, backed by MDN documentation
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
web-components-examples
A series of Web Components examples, related to the MDN Web Components documentation at https://developer.mozilla.org/en-US/docs/Web/API/Web_components.
Please refer to our contribution guidelines before contributing.
The following examples are available:
- composed-composed-path. A very simple example that shows the behavior of the
Event
objectcomposed
andcomposedPath
properties. See composed-composed-path live. - defined-pseudo-class. A very simple example that shows how the
:defined pseudo-class
works. See defined-pseudo-class live. - editable-list âÂ
<editable-list>
. A simple example showing how elements can be consolidated to create a list with addable/removable items. Items are added by using alist-item
attribute or by entering text and clicking the plus sign. See editable-list live. - edit-word â
<edit-word>
. Wrapping one or more words in this element means that you can then click/focus the element to reveal a text input that can then be used to edit the word(s). See edit-word live. - element-details â
<element-details>
. Displays a box containing an HTML element name and description. Provides an example of an autonomous custom element that gets its structure from a<template>
element (that also has its own styling defined), and also contains<slot>
elements populated at runtime. See element-details live. - expanding-list-web-component â
<ul is="expanding-list">
. Creates an unordered list with expandable/collapsible children. Provides an example of a customized built-in element (the class inherits fromHTMLUListElement
rather thanHTMLElement
). See expanding-list live. - life-cycle-callbacks â
<custom-square l="" c="">
. A trivial example web component that creates a square colored box on the page. The demo also includes buttons to create, destroy, and change attributes on the element, to demonstrate how the web components life cycle callbacks work See life-cycle-callbacks live. - popup-info-box-web-component â
<popup-info img="" text="">
. Creates an info icon that when focused displays a popup info box. Provides an example of an autonomous custom element that takes information from its attributes, and defines structure and basic style in an attached shadow DOM. See popup-info-box live. - simple-template â A very simple trivial example that quickly demonstrates usage of the
<template>
and<slot>
elements. See simple-template live. - slotchange example â
<summary-display>
. An example that takes as its two slot values a list of possible choices, and a description for the selected choice. Multiple paragraphs are included inside the element containing all the possible descriptions; when a choice is clicked, its corresponding description paragraph is given an appropriate slot attribute so that it appears in the second slot. This example is written to demonstrate usage of the slotchange attribute, and features of the HTMLSlotElement interface See the slotchange example live. - slotted-pseudo-element. A very simple example that shows how the
::slotted
pseudo-element works. See slotted-pseudo-element live. - word-count-web-component â
<word-count>
. When added to an element, counts all the words inside that element and displays them inside an attached shadow DOM. It also contains an interval that periodically updates the word count as it changes. Provides an example of a customized built-in element (the class inherits fromHTMLParagraphElement
rather thanHTMLElement
). See word-count live.
Top Related Projects
Our original Web Component library.
A toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, and traditional web developers from a single, framework-agnostic codebase.
Lit is a simple library for building fast, lightweight web components.
⚡️ LWC - A Blazing Fast, Enterprise-Grade Web Components Foundation
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot