{"id":164052,"date":"2025-06-13T09:00:00","date_gmt":"2025-06-13T07:00:00","guid":{"rendered":"https:\/\/gtechgroup.it\/blog\/web-components-custom-elements-shadow-dom\/"},"modified":"2025-06-13T09:00:00","modified_gmt":"2025-06-13T07:00:00","slug":"web-components-custom-elements-shadow-dom","status":"publish","type":"post","link":"https:\/\/gtechgroup.it\/blog\/web-components-custom-elements-shadow-dom\/","title":{"rendered":"Web Components: Custom Elements e Shadow DOM in HTML"},"content":{"rendered":"<p style=\"text-align: justify;\">I <strong>Web Components<\/strong> rappresentano un insieme di tecnologie native del browser che permettono di creare componenti HTML personalizzati, riutilizzabili e incapsulati, senza dipendere da framework o librerie esterne. Basati su standard web aperti, i Web Components offrono una soluzione nativa al problema della componentizzazione dell&#8217;interfaccia utente che ha guidato lo sviluppo di React, Vue e Angular. In questa guida esploreremo le tre tecnologie fondamentali che compongono i Web Components.<\/p>\n<h2>Cosa Sono i Web Components<\/h2>\n<p style=\"text-align: justify;\">I Web Components sono un insieme di tre tecnologie browser complementari che, combinate, permettono di creare elementi HTML personalizzati con un comportamento e uno stile encapsulato. Queste tecnologie sono: <strong>Custom Elements<\/strong> per definire nuovi tag HTML, <strong>Shadow DOM<\/strong> per l&#8217;incapsulamento di stile e struttura, e <strong>HTML Templates<\/strong> per definire markup riutilizzabile.<\/p>\n<p style=\"text-align: justify;\">Il vantaggio fondamentale dei Web Components \u00e8 che sono basati su <strong>standard web nativi<\/strong>, supportati da tutti i browser moderni senza la necessit\u00e0 di transpilazione, build step o librerie aggiuntive. Un componente creato con Web Components funziona in qualsiasi contesto: un sito HTML statico, un&#8217;applicazione React, un progetto Vue o Angular. Questa interoperabilit\u00e0 li rende particolarmente adatti per librerie di componenti UI condivise e design system aziendali.<\/p>\n<p style=\"text-align: justify;\">La specifica dei Web Components \u00e8 maturata significativamente negli ultimi anni e oggi gode di un supporto browser completo. Chrome, Firefox, Safari e Edge supportano tutte e tre le tecnologie nella loro versione attuale, rendendo i Web Components una scelta praticabile per la produzione.<\/p>\n<h2>Custom Elements: Definire Nuovi Tag HTML<\/h2>\n<p style=\"text-align: justify;\">I <strong>Custom Elements<\/strong> permettono di definire nuovi elementi HTML con un nome personalizzato, un comportamento specifico e un&#8217;interfaccia programmabile. La regola fondamentale per i nomi dei custom elements \u00e8 che devono contenere un <strong>trattino<\/strong> (hyphen), ad esempio &#8220;my-button&#8221;, &#8220;user-card&#8221; o &#8220;app-header&#8221;. Questa convenzione evita conflitti con i tag HTML presenti e futuri.<\/p>\n<p style=\"text-align: justify;\">Per creare un custom element, si definisce una classe JavaScript che estende <strong>HTMLElement<\/strong> (o un&#8217;altra classe di elemento HTML) e si registra con il metodo customElements.define(). All&#8217;interno della classe, il costruttore inizializza l&#8217;elemento, e metodi e propriet\u00e0 personalizzati definiscono il suo comportamento.<\/p>\n<p style=\"text-align: justify;\">I <strong>lifecycle callbacks<\/strong> sono metodi speciali che il browser chiama automaticamente in momenti specifici del ciclo di vita dell&#8217;elemento:<\/p>\n<ul>\n<li><strong>constructor()<\/strong>: chiamato quando l&#8217;elemento viene creato. Usato per l&#8217;inizializzazione, la creazione del Shadow DOM e la configurazione iniziale. Non deve accedere ad attributi o figli perch\u00e9 potrebbero non essere ancora disponibili<\/li>\n<li><strong>connectedCallback()<\/strong>: chiamato quando l&#8217;elemento viene inserito nel DOM. \u00c8 il momento ideale per configurare event listener, avviare fetch di dati e renderizzare il contenuto<\/li>\n<li><strong>disconnectedCallback()<\/strong>: chiamato quando l&#8217;elemento viene rimosso dal DOM. Usato per pulire risorse, rimuovere event listener e interrompere operazioni in corso<\/li>\n<li><strong>attributeChangedCallback(nome, vecchioValore, nuovoValore)<\/strong>: chiamato quando un attributo osservato viene aggiunto, modificato o rimosso. Gli attributi da osservare devono essere dichiarati nella propriet\u00e0 statica observedAttributes<\/li>\n<li><strong>adoptedCallback()<\/strong>: chiamato quando l&#8217;elemento viene spostato in un nuovo documento. Raramente utilizzato nella pratica<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Esistono due tipi di custom elements: gli <strong>autonomous elements<\/strong> che estendono HTMLElement e vengono usati come tag indipendenti, e i <strong>customized built-in elements<\/strong> che estendono elementi HTML esistenti (come HTMLButtonElement) e vengono usati con l&#8217;attributo is=&#8221;my-button&#8221; sull&#8217;elemento nativo. Quest&#8217;ultimo approccio ha un supporto browser incompleto (Safari non lo supporta), quindi gli autonomous elements sono la scelta pi\u00f9 sicura.<\/p>\n<h2>Shadow DOM: Incapsulamento di Stile e Struttura<\/h2>\n<p style=\"text-align: justify;\">Il <strong>Shadow DOM<\/strong> \u00e8 la tecnologia che fornisce l&#8217;incapsulamento ai Web Components. Crea un albero DOM separato e isolato, chiamato &#8220;shadow tree&#8221;, che \u00e8 nascosto dal DOM principale (light DOM) della pagina. Gli stili CSS definiti all&#8217;interno del Shadow DOM non influenzano il resto della pagina, e viceversa, gli stili della pagina non penetrano nel Shadow DOM.<\/p>\n<p style=\"text-align: justify;\">Per creare un Shadow DOM, si chiama il metodo <strong>attachShadow()<\/strong> sull&#8217;elemento, passando un oggetto di configurazione con la propriet\u00e0 mode. Il valore &#8220;open&#8221; rende il shadow root accessibile tramite JavaScript (element.shadowRoot), mentre &#8220;closed&#8221; lo nasconde completamente. Nella maggior parte dei casi, &#8220;open&#8221; \u00e8 la scelta appropriata, poich\u00e9 &#8220;closed&#8221; pu\u00f2 complicare il testing e il debugging senza offrire vera sicurezza.<\/p>\n<p style=\"text-align: justify;\">L&#8217;incapsulamento del Shadow DOM opera su pi\u00f9 livelli. Gli <strong>stili CSS<\/strong> sono completamente isolati: un selettore come p { color: red; } nel Shadow DOM non colorer\u00e0 i paragrafi della pagina esterna, e uno stile p { color: blue; } nella pagina non influenzer\u00e0 i paragrafi interni al componente. Alcune propriet\u00e0 CSS ereditabili (come font-family, color e line-height) attraversano il confine del Shadow DOM, poich\u00e9 sono ereditate dall&#8217;elemento host.<\/p>\n<p style=\"text-align: justify;\">Lo pseudo-elemento <strong>:host<\/strong> seleziona l&#8217;elemento host del Shadow DOM dall&#8217;interno, permettendo di stilizzare il componente stesso. <strong>:host(.className)<\/strong> seleziona l&#8217;host solo quando ha una specifica classe. <strong>::slotted(selettore)<\/strong> stilizza gli elementi proiettati tramite slot. La propriet\u00e0 CSS <strong>part<\/strong> e lo pseudo-elemento <strong>::part()<\/strong> permettono all&#8217;esterno di stilizzare parti specifiche del componente, offrendo punti di personalizzazione controllati.<\/p>\n<h2>HTML Templates e Slot<\/h2>\n<p style=\"text-align: justify;\">L&#8217;elemento <code>&lt;template&gt;<\/code> definisce un frammento di markup HTML che non viene renderizzato dal browser fino a quando non viene esplicitamente clonato e inserito nel DOM tramite JavaScript. Il suo contenuto \u00e8 &#8220;inerte&#8221;: le immagini non vengono scaricate, gli script non vengono eseguiti e gli stili non vengono applicati fino all&#8217;attivazione.<\/p>\n<p style=\"text-align: justify;\">Per utilizzare un template, si accede al suo contenuto tramite la propriet\u00e0 <strong>content<\/strong> (un DocumentFragment) e lo si clona con <strong>cloneNode(true)<\/strong> (il parametro true indica una clonazione profonda). Il clone viene poi inserito nel Shadow DOM o nel DOM della pagina. Questo pattern \u00e8 pi\u00f9 efficiente della creazione di elementi tramite innerHTML, poich\u00e9 il template viene parsato una sola volta dal browser.<\/p>\n<p style=\"text-align: justify;\">Gli <strong>slot<\/strong> sono un meccanismo potente che permette di proiettare contenuto dal light DOM all&#8217;interno del Shadow DOM. L&#8217;elemento <code>&lt;slot&gt;<\/code> nel template del componente funge da segnaposto: il contenuto inserito dall&#8217;utente del componente tra i tag del custom element viene proiettato nella posizione dello slot. Per approfondire il funzionamento dei template e degli slot, consulta il nostro articolo dedicato al <a href=\"https:\/\/gtechgroup.it\/blog\/tag-template-html-componenti-riutilizzabili\/\">tag template in HTML<\/a>.<\/p>\n<p style=\"text-align: justify;\">Esistono <strong>slot con nome<\/strong> (named slots) e uno <strong>slot predefinito<\/strong> (default slot). Uno slot con nome viene dichiarato con l&#8217;attributo name e riceve il contenuto dagli elementi con attributo slot corrispondente. Lo slot predefinito (senza attributo name) riceve tutto il contenuto che non ha un attributo slot specifico. Se nessun contenuto viene proiettato, lo slot mostra il suo contenuto di fallback.<\/p>\n<h2>Web Components vs Framework: Quando Usare Cosa<\/h2>\n<p style=\"text-align: justify;\">I Web Components e i framework JavaScript (React, Vue, Angular) non sono necessariamente in competizione; spesso si complementano. Tuttavia, comprendere le differenze \u00e8 importante per fare la scelta giusta in ogni progetto.<\/p>\n<p style=\"text-align: justify;\">I <strong>Web Components<\/strong> eccellono come soluzione per: componenti UI condivisi tra progetti che utilizzano framework diversi, design system aziendali che devono essere framework-agnostic, widget distribuibili da integrare in siti di terze parti, e scenari dove la riduzione delle dipendenze \u00e8 prioritaria. La loro natura nativa garantisce la longevit\u00e0: non diventano obsoleti quando esce una nuova versione di un framework.<\/p>\n<p style=\"text-align: justify;\">I <strong>framework<\/strong> offrono vantaggi complementari: gestione dello stato dell&#8217;applicazione pi\u00f9 sofisticata, ecosistemi di strumenti maturi (routing, build tools, testing), rendering lato server, e una Developer Experience (DX) spesso pi\u00f9 completa. Per applicazioni complesse con molte pagine e logica di business elaborata, un framework rimane generalmente la scelta pi\u00f9 produttiva.<\/p>\n<p style=\"text-align: justify;\">La soluzione ideale per molte organizzazioni \u00e8 un approccio <strong>ibrido<\/strong>: un design system basato su Web Components per i componenti UI di base (pulsanti, form, card, modali), utilizzato all&#8217;interno di applicazioni costruite con il framework preferito dal team. Questo approccio massimizza la riutilizzabilit\u00e0 e riduce la duplicazione tra progetti diversi.<\/p>\n<p style=\"text-align: justify;\">Librerie come <strong>Lit<\/strong> (sviluppata da Google) semplificano significativamente la creazione di Web Components, fornendo un layer sottile sopra le API native che gestisce automaticamente il rendering reattivo, la gestione delle propriet\u00e0 e altre funzionalit\u00e0 comuni, mantenendo la compatibilit\u00e0 con lo standard Web Components.<\/p>\n<p style=\"text-align: justify;\">Hai bisogno di aiuto con lo sviluppo di Web Components per il tuo progetto? <strong>G Tech Group<\/strong> offre servizi di sviluppo web professionale e consulenza sulle architetture frontend. Contattaci a <strong>support@gtechgroup.it<\/strong> o via WhatsApp al <strong>0465 84 62 45<\/strong>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I Web Components rappresentano un insieme di tecnologie native del browser che permettono di creare componenti HTML personalizzati, riutilizzabili e incapsulati, senza dipendere da framework&hellip;<\/p>\n","protected":false},"author":2,"featured_media":164232,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"1246","_seopress_titles_title":"Web Components: Custom Elements e Shadow DOM in HTML %%sep%% %%sitename%%","_seopress_titles_desc":"Guida ai Web Components: Custom Elements, Shadow DOM, lifecycle callbacks, slot, template HTML e confronto con React, Vue e Angular.","_seopress_robots_index":"","footnotes":""},"categories":[1246],"tags":[787],"class_list":["post-164052","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-html","tag-sviluppo-web"],"_links":{"self":[{"href":"https:\/\/gtechgroup.it\/blog\/wp-json\/wp\/v2\/posts\/164052","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gtechgroup.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gtechgroup.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gtechgroup.it\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/gtechgroup.it\/blog\/wp-json\/wp\/v2\/comments?post=164052"}],"version-history":[{"count":0,"href":"https:\/\/gtechgroup.it\/blog\/wp-json\/wp\/v2\/posts\/164052\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gtechgroup.it\/blog\/wp-json\/wp\/v2\/media\/164232"}],"wp:attachment":[{"href":"https:\/\/gtechgroup.it\/blog\/wp-json\/wp\/v2\/media?parent=164052"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gtechgroup.it\/blog\/wp-json\/wp\/v2\/categories?post=164052"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gtechgroup.it\/blog\/wp-json\/wp\/v2\/tags?post=164052"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}