Spesso trascurate ma incredibilmente potenti, le Chrome Extension rappresentano uno strumento versatile per migliorare e personalizzare l’esperienza di navigazione.
In questo articolo, esploreremo a fondo la creazione e il funzionamento di un’estensione, la “Inverse Dark/Light Mode”, che dimostra come questi piccoli ma efficaci tool possano rispondere a esigenze operative quotidiane e offrire svariate funzionalità.
Panoramica dell’Estensione “Inverse Dark/Light Mode”
L’estensione “Inverse Dark/Light Mode” nasce dall’idea di offrire un controllo dinamico sulla visualizzazione dei contenuti web. Le sue funzionalità principali includono:
- Modalità “Inversa”: la capacità di trasformare istantaneamente un sito web dalla “light mode” alla “dark mode” e viceversa, offrendo un comfort visivo personalizzabile.
- Pagina “Options”: una sezione dedicata alla gestione dell’estensione, dove gli utenti possono visualizzare e modificare la lista dei siti per i quali la modalità “inversa” è attiva.
- Conteggio Testo: una funzionalità aggiuntiva che consente di contare il numero di parole o lettere di un testo selezionato, accessibile tramite una voce personalizzata nel menu contestuale di Chrome.
Addentriamoci nei dettagli tecnici di ciascuna di queste funzionalità.
La Modalità “Inversa”e i suoi effetti sulla visualizzazione
Il cuore di questa estensione risiede nella sua capacità di invertire i colori di una pagina web. L’idea di base è semplice ma efficace: applicare stili CSS dinamici per modificare l’aspetto del sito.
L’Idea Dietro l’Inversione di Colore
Il meccanismo principale si basa sull’iniezione di stili CSS al caricamento della pagina. In particolare, vengono utilizzate due proprietà CSS fondamentali:
filter: invert(1)
: Applicato all’elemento<html>
della pagina, questo filtro inverte tutti i colori del sito. Il bianco diventa nero, il nero diventa bianco e ogni colore si trasforma nel suo complementare. Questo è il primo passo per ottenere il cambio di tema desiderato.filter: hue-rotate(180deg)
: Questo filtro viene applicato per ripristinare i colori originali di elementi specifici come immagini, video e iframe. Sebbene il filtroinvert(1)
sia ottimo per il testo e gli sfondi, applicarlo a un’immagine o un video renderebbe i loro colori innaturali. Ruotando la tonalità di 180 gradi, si cerca di compensare l’inversione cromatica per questi elementi, riportandoli a una rappresentazione visivamente più accurata.

È importante notare che invertire i colori significa trasformare ogni colore nel suo complementare. Ad esempio, il bianco diventerà nero, il rosso diventerà ciano, e così via. Il filtro hue-rotate(180deg)
interviene proprio per mitigare questo effetto indesiderato su specifici elementi, cercando di ripristinare i colori allo stato iniziale.

Perché non Tutti i Colori Tornano Perfettamente Originali?
Questo è un punto cruciale per comprendere i limiti dei filtri CSS. Il filtro hue-rotate()
manipola la tonalità (la “H” nel modello colore HSL), ma il rendering dei colori sullo schermo avviene in RGB. Quando un colore viene dichiarato in HSL nel CSS, il browser lo converte internamente in RGB per la visualizzazione.
I filtri CSS come invert(), hue-rotate(), brightness(),
ecc., operano dopo il rendering visivo. Ciò significa che non lavorano sui valori colore dichiarati nel CSS, ma piuttosto sull’immagine finale già renderizzata, ovvero sui pixel RGB.
Di conseguenza, hue-rotate()
simula una rotazione del tono nel modello HSL, ma l’elaborazione avviene approssimativamente sul modello RGB. Il browser esegue una conversione da RGB a HSL, ruota la tonalità e poi riconverte in RGB. Questa doppia conversione e l’approssimazione nel modello RGB possono portare a leggere deviazioni, motivo per cui alcuni colori potrebbero non tornare esattamente al loro stato originale dopo l’applicazione combinata di invert(1)
e hue-rotate(180deg)
.
Caricamento degli Stili e degli Script

Per garantire che questi stili e script vengano caricati al momento giusto, il file manifest.json
dell’estensione gioca un ruolo fondamentale. Attraverso la chiave content_scripts, viene configurato il caricamento di style.css
e content.js
(quest’ultimo per la logica dell’interfaccia), assicurando che vengano iniettati nelle pagine web visitate. Contemporaneamente, il service-worker.js
viene caricato per gestire la logica in background dell’estensione.
Attivazione, Disattivazione e Persistenza dello Stato

Al clic sull’icona dell’estensione, la logica implementata nel service-worker.ts
entra in azione. Viene aggiunta o rimossa una classe CSS (inverse-mode)
al tag <html>
della pagina corrente. Questa classe, a sua volta, abilita o disabilita le regole CSS descritte in precedenza.
Per un’esperienza utente fluida, l’estensione utilizza il LocalStorage per salvare la lista degli “origin” dei siti (ad esempio, https://danielzotti.it
se si visita https://danielzotti.it/blog
) per i quali la modalità “inversa” è stata attivata. Questo assicura che lo stato della modalità “inversa” persista durante la navigazione all’interno dello stesso dominio o quando si ritorna sul sito in futuro, senza dover riattivare manualmente l’estensione.
Aggiornamento Dinamico dell’Icona dell’Estensione
Per fornire un feedback visivo immediato all’utente, l’icona dell’estensione cambia in base allo stato della modalità “inversa” per il sito attualmente visitato. Questo avviene monitorando i cambiamenti nel LocalStorage e aggiornando l’immagine dell’icona di conseguenza. Il service-worker.ts
è responsabile di questa logica di ascolto e aggiornamento.


Gestione degli Eventi Aggiuntivi per un’Esperienza Coerente
Mantenere l’icona dell’estensione e la classe .inverse-mode
allineate con lo stato corrente della pagina non si limita al semplice click sull’icona o ai cambiamenti nel LocalStorage
. È fondamentale gestire una serie di scenari aggiuntivi per garantire un’esperienza utente fluida e coerente:
- Cambio di Tab: Quando l’utente passa da un tab all’altro, l’icona dell’estensione deve riflettere lo stato (attivo/disattivo) della modalità “inversa” per il dominio del tab appena selezionato.
- Apertura di un Nuovo Tab: Se un nuovo tab viene aperto, l’estensione deve verificare se il dominio è presente nella lista dei siti con la modalità “inversa” attiva. In tal caso, la classe .inverse-mode deve essere aggiunta al tag HTML e l’icona aggiornata.
Per affrontare queste casistiche, l’estensione sfrutta diverse API di Chrome:
chrome.webNavigation.onCommitted
: Questo evento viene attivato quando una navigazione è stata definitivamente confermata, ovvero quando il browser ha deciso di caricare una nuova pagina in un tab. Viene utilizzato per iniettare il filecontent.js,
essenziale per applicare gli stili e la logica frontend.chrome.runtime.onStartup
: Eseguito all’avvio di Chrome (non all’installazione o aggiornamento dell’estensione), questo evento è utile per identificare il tab attivo e aggiornare l’immagine dell’icona dell’estensione fin dall’inizio della sessione di navigazione.chrome.tabs.onUpdated
: Chiamato ogni volta che una scheda viene aggiornata (cambio di URL, stato, reindirizzamento, ecc.). Viene impiegato per aggiornare l’immagine dell’icona in base allo stato del tab.chrome.tabs.onActivated
: Attivato quando l’utente cambia la scheda attiva. Questo evento è cruciale per aggiungere la classe.inverse-mode
al tag HTML della nuova scheda e per aggiornare l’icona dell’estensione in tempo reale.
I Permessi Necessari: Il manifest.json

Ogni estensione Chrome necessita di un file manifest.json che dichiara i permessi richiesti per operare correttamente. Per la “Inverse Dark/Light Mode”, i permessi essenziali includono:
scripting
: Permette all’estensione di iniettare ed eseguire codice JavaScript e CSS nelle pagine web, fondamentale per la modalità “inversa”.tabs
: Consente di ottenere informazioni sulle schede aperte nel browser, come URL e titolo, utili per la gestione degli stati e delle icone.activeTab
: Fornisce accesso temporaneo alla scheda attiva quando l’utente interagisce con l’estensione (es. click sull’icona). È un permesso più limitato rispetto a tabs e non richiede un’autorizzazione esplicita in fase di installazione.storage
: Permette all’estensione di memorizzare dati localmente utilizzando l’API chrome.storage, indispensabile per salvare le preferenze sui siti con la modalità “inversa” attiva.webNavigation
: Consente di monitorare la navigazione dell’utente, cruciale per eseguire lo script content.js ogni volta che una nuova pagina viene caricata o un URL cambia, assicurando l’applicazione/rimozione dinamica della classe .inverse-mode.contextMenus
: Permette di aggiungere voci personalizzate al menu contestuale (tasto destro del mouse), abilitando la funzionalità bonus di conteggio del testo.
La Pagina “Options”: Il Centro di Controllo
Le estensioni spesso includono una pagina “Options”: un’interfaccia utente dedicata alla configurazione e alla gestione delle impostazioni. Nella nostra estensione, questa pagina serve a mostrare e gestire la lista dei siti per cui la modalità “inversa” è stata attivata.
Per lo sviluppo di questa pagina, è stato utilizzato un framework moderno come React 19, TypeScript, SCSS e Vite. Sebbene possa sembrare un approccio “overkill” per una semplice pagina di opzioni, questa scelta è stata fatta per esplorare le capacità di integrazione di queste tecnologie nello sviluppo di estensioni Chrome.
Per accedere alla pagina “Options”, basta fare clic con il pulsante destro sull’icona dell’estensione nella barra degli strumenti di Chrome e selezionare la voce “Opzioni”.

Attivazione della Pagina “Options”
L’attivazione della pagina “Options” avviene nel manifest.json
, specificando il file HTML che funge da interfaccia per le opzioni dell’estensione.

Configurazione di Vite per la Build
Dato l’utilizzo di React e di diversi file per le diverse funzionalità dell’estensione (gli script di background, gli stili, la pagina delle opzioni), è stata necessaria una configurazione specifica di Vite. Questo tool di build è stato configurato per generare separatamente i file dell’applicazione React (la pagina delle opzioni) e gli altri file come style.css, content.js e service-worker.js
, ottimizzando il processo di compilazione e deployment.

Contare Parole e Lettere con il Menu Contestuale
Come bonus aggiuntivo, l’estensione include una funzionalità per contare il numero di parole o lettere in un testo selezionato direttamente da una voce del menu contestuale di Chrome.
L’obiettivo è semplice:
- Aggiungere una voce al menu contestuale di Chrome, sotto il nome dell’estensione (“Inverse Dark/Light Mode”).
- Quando l’utente seleziona del testo sulla pagina, fa clic destro e sceglie la voce “Count Words”, un semplice alert mostrerà il totale delle parole nel testo selezionato.

Aggiunta dell’Elemento al Menu Contestuale
Questa funzionalità è implementata nel service-worker.ts
, dove viene aggiunta la voce specifica al menu contestuale utilizzando l’API chrome.contextMenus.

Conteggio delle Parole
Una volta che l’utente seleziona la voce “Count Words” dal menu contestuale, il service-worker.ts
esegue la logica di conteggio. Il testo selezionato viene acquisito e, tramite una regular expression accuratamente definita, le parole vengono identificate e contate. Il risultato viene poi visualizzato in un alert.

Vuoi Vedere il Codice?
L’intero progetto è disponibile su GitHub, dove potrai esplorare il codice sorgente completo e approfondire ogni aspetto implementativo:
https://github.com/danielzotti/chrome-extension-react-typescript-vite
Se sei interessato a provare l’estensione direttamente, puoi scaricarla dal Chrome Web Store:
https://chromewebstore.google.com/detail/inverse-darklight-mode/bddlmhjdondkdinihlncinlgeddemidc
Autore: Daniel Zotti, Team Lead Front-end @ Bitrock