Introduzione
Una delle tendenze più interessanti dello sviluppo web moderno è l’uso dei Web Components per costruire parti di interfaccia autonome, riutilizzabili e facili da mantenere. In questo tutorial vedremo un caso pratico molto utile: creare una barra di ricerca personalizzata che può essere riutilizzata in più pagine o progetti senza riscrivere ogni volta la stessa logica.
Perché scegliere proprio una barra di ricerca? Perché è un componente presente in moltissime applicazioni: cataloghi prodotti, blog, documentazione tecnica, dashboard, e-commerce. Con HTML e Web Components possiamo incapsulare struttura, comportamento e stile in un unico elemento, ottenendo un componente pulito e indipendente dal resto della pagina.
L’obiettivo non è solo “far funzionare” il componente, ma capire come progettare un elemento moderno che rispetti le buone pratiche: accessibilità, riuso, isolamento degli stili e comunicazione con il resto dell’applicazione tramite eventi personalizzati.
Codice completo
Di seguito trovi un esempio completo di Web Component chiamato search-bar. Il componente include un input, un pulsante per avviare la ricerca e un evento personalizzato che invia all’esterno il testo inserito dall’utente.
<!-- Uso del componente nella pagina -->
<search-bar placeholder="Cerca articoli..." button-label="Cerca"></search-bar>
<script>
class SearchBar extends HTMLElement {
constructor() {
super();
// Shadow DOM: isola struttura e stile del componente
const shadow = this.attachShadow({ mode: ´open´ });
shadow.innerHTML = `
<style>
:host {
display: block;
max-width: 520px;
font-family: Arial, sans-serif;
}
.wrapper {
display: flex;
gap: 8px;
align-items: center;
}
input {
flex: 1;
padding: 12px 14px;
border: 1px solid #cfd6e4;
border-radius: 8px;
font-size: 16px;
outline: none;
}
input:focus {
border-color: #2563eb;
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}
button {
padding: 12px 16px;
border: none;
border-radius: 8px;
background: #2563eb;
color: white;
font-size: 16px;
cursor: pointer;
}
button:hover {
background: #1d4ed8;
}
button:active {
transform: translateY(1px);
}
</style>
<div class="wrapper">
<input type="search" aria-label="Campo di ricerca" />
<button type="button">Cerca</button>
</div>
`;
this.input = shadow.querySelector(´input´);
this.button = shadow.querySelector(´button´);
}
static get observedAttributes() {
return [´placeholder´, ´button-label´];
}
connectedCallback() {
this.updateFromAttributes();
this.button.addEventListener(´click´, () => {
this.emitSearch();
});
this.input.addEventListener(´keydown´, (event) => {
if (event.key === ´Enter´) {
this.emitSearch();
}
});
}
attributeChangedCallback() {
this.updateFromAttributes();
}
updateFromAttributes() {
const placeholder = this.getAttribute(´placeholder´) || ´Cerca...´;
const buttonLabel = this.getAttribute(´button-label´) || ´Cerca´;
this.input.setAttribute(´placeholder´, placeholder);
this.button.textContent = buttonLabel;
}
emitSearch() {
const query = this.input.value.trim();
this.dispatchEvent(
new CustomEvent(´search´, {
detail: { query },
bubbles: true,
composed: true
})
);
}
}
customElements.define(´search-bar´, SearchBar);
// Esempio di utilizzo dell´evento personalizzato
document.addEventListener(´search´, (event) => {
console.log(´Ricerca richiesta:´, event.detail.query);
});
</script> Spiegazione
Vediamo il componente passo per passo per capire davvero come funziona.
1. Creazione del custom element
La classe SearchBar estende HTMLElement. Questo è il primo passo per creare un Web Component. In questo modo il browser riconosce il nostro elemento come un tag HTML personalizzato.
La registrazione avviene con customElements.define(´search-bar´, SearchBar). Da quel momento possiamo usare il tag <search-bar> nel markup come se fosse un elemento nativo.
2. Shadow DOM per isolamento
Con attachShadow({ mode: ´open´ }) creiamo uno Shadow DOM. Questo significa che HTML e CSS interni del componente non interferiscono con il resto della pagina e, allo stesso tempo, gli stili esterni non lo modificano accidentalmente.
È un vantaggio enorme nei progetti grandi, dove il rischio di conflitti CSS è alto. Inoltre, rende il componente più prevedibile e facile da riutilizzare.
3. Attributi configurabili
Il componente supporta due attributi: placeholder e button-label. In questo modo possiamo personalizzare il comportamento senza cambiare il codice JavaScript.
Per esempio:
<search-bar placeholder="Cerca nel catalogo" button-label="Trova"></search-bar> Quando un attributo cambia, il metodo attributeChangedCallback aggiorna il contenuto interno. Questo rende il componente flessibile e adatto a contesti diversi.
4. Interazione con l’utente
Il componente ascolta due eventi:
- click sul pulsante, per avviare la ricerca;
- keydown sull’input, per supportare il tasto Enter.
Questa scelta migliora l’usabilità: l’utente può usare il mouse o la tastiera senza differenze di comportamento.
5. Comunicazione verso l’esterno
Quando l’utente avvia la ricerca, il componente non esegue direttamente una logica specifica dell’applicazione. Invece emette un CustomEvent chiamato search, con il testo inserito dentro detail.query.
Questo è un approccio molto importante: il componente resta riutilizzabile e non dipende dal progetto in cui viene inserito. Sarà poi l’applicazione a decidere cosa fare con il testo cercato: filtrare una lista, interrogare un’API, aggiornare i risultati o navigare a una nuova pagina.
Best practice
Quando lavori con HTML e Web Components, è utile seguire alcune regole pratiche per evitare componenti fragili o difficili da mantenere.
- Usa nomi chiari e descrittivi: i custom element devono contenere un trattino, quindi search-bar è una scelta migliore di nomi vaghi o troppo generici.
- Non mescolare logica e presentazione: il componente dovrebbe occuparsi della propria interfaccia e comunicare tramite eventi, non gestire direttamente tutta l’applicazione.
- Prevedi attributi configurabili: placeholder, etichette, stati iniziali e varianti rendono il componente più utile in contesti diversi.
- Supporta la tastiera: l’accessibilità non è opzionale. Gestire Enter e usare attributi come aria-label migliora molto l’esperienza d’uso.
- Evita dipendenze inutili: uno dei punti forti dei Web Components è la portabilità. Più il componente è autonomo, più sarà facile riutilizzarlo.
- Usa eventi personalizzati per comunicare con il contenitore esterno, invece di accoppiare il componente a logiche specifiche della pagina.
- Rendi gli stili coerenti ma semplici: il componente deve essere bello e leggibile, ma anche facile da adattare ai diversi design system.
Un altro consiglio importante è testare il componente in più contesti: dentro una pagina semplice, dentro un framework e in presenza di altri stili globali. Lo Shadow DOM aiuta molto, ma è sempre bene verificare che il comportamento sia davvero prevedibile.
Riepilogo
In questo tutorial abbiamo visto come costruire una barra di ricerca riutilizzabile con HTML e Web Components. Questo esempio mostra bene i vantaggi delle tecnologie moderne del web:
- creazione di elementi personalizzati;
- isolamento tramite Shadow DOM;
- configurazione tramite attributi HTML;
- comunicazione con eventi personalizzati;
- migliore riuso del codice in più progetti.
Se vuoi sviluppare interfacce moderne, modulari e scalabili, i Web Components sono una competenza molto utile. Ti permettono di ragionare per blocchi indipendenti, proprio come avviene nei componenti dei framework più diffusi, ma con una soluzione nativa del browser.
La barra di ricerca è solo un esempio: lo stesso approccio può essere applicato a menu, card, filtri, pannelli informativi, player multimediali e molto altro.
Approfondisci con risorse ufficiali
- MDN Web Docs - Web Components: documentazione completa e aggiornata sui componenti web.
- MDN Web Docs - Custom Elements: guida pratica per creare elementi HTML personalizzati.
- MDN Web Docs - Shadow DOM: approfondimento sull’incapsulamento dell’interfaccia.
- MDN Web Docs - CustomEvent: riferimento utile per comunicare eventi dal componente all’esterno.
- Web Components.org: sito dedicato con esempi, pattern e best practice.
