Un buon toggle light/dark in Webflow non è una singola feature — è un piccolo sistema: una palette costruita su variabili, un’interazione GSAP che inverte una singola classe, una transizione di colore fluida che non sabota le altre animazioni, e un tocco di JavaScript perché la scelta sopravviva a reload e cambi di pagina. Costruiscilo una volta, nel modo giusto, e potrai metterlo in qualsiasi progetto.
Il vantaggio di fare il lavoro preparatorio è quasi magico: un intero cambio di tema si riduce al toggle di una sola classe. Questa lezione è anche un’ottima occasione per vedere la action set di GSAP — la cugina istantanea e senza durata di animate — e come dialoga con i variable modes di Webflow.
Come funziona
Variabili e variable modes sono le fondamenta. Metti ogni colore che il tema deve toccare in una collezione di variabili (raggruppati, es. sfondi e font). Il base mode di default è il tuo tema chiaro; aggiungi un secondo variable mode manuale chiamato dark mode e sovrascrivi lì i valori. Poi collega quelle variabili a tutto ciò che usa colore — parti dal tag Body (All Pages) per font e sfondo (la maggior parte degli elementi eredita da lì), poi classi e stati specifici dove serve. Fatto questo, applicare una classe dark-mode che porta il variable mode scuro inverte l’intera palette all’istante.
La set action di GSAP inverte la classe. Il toggle usa due interazioni, entrambe con control toggle play/reverse (così ogni click inverte): una anima il piccolo knob dello switch lungo il binario, l’altra usa una action set sulla classe. Set è diversa da animate — invece della sezione “animated properties” ha set properties, e sotto un’opzione class con add / remove / toggle. Fare toggle della classe dark-mode è l’intero cambio di tema. (Set gira sulla pagina in cui l’hai costruita — ricorda di impostare runs on: all pages così un toggle copiato funziona ovunque, e tieni la classe dark-mode attaccata a qualcosa nello style guide così Webflow non la elimina come inutilizzata.)
Ammorbidire il cambio senza rompere tutto. Di default il tema si inverte all’istante. Potresti aggiungere transizioni CSS a ogni elemento colorato, ma è poco pratico e peggio — quelle transizioni si scontrerebbero con qualsiasi animazione GSAP di scroll/hover che tocca le stesse proprietà. La mossa più intelligente è una classe theme-transition definita in CSS custom nell’head che applica transizioni di colore a tutti gli elementi solo mentre è presente:
<!-- Site Settings → Custom Code → Head -->
<style>
.theme-transition,
.theme-transition *,
.theme-transition *::before,
.theme-transition *::after {
transition:
color 0.8s cubic-bezier(0.16, 1, 0.3, 1),
background-color 0.8s cubic-bezier(0.16, 1, 0.3, 1),
border-color 0.8s cubic-bezier(0.16, 1, 0.3, 1),
outline-color 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}
</style>
Nell’interazione dello switch, set la classe theme-transition a 0s e set via a 0.8s. Ora i colori sfumano su 800ms durante lo switch, e la transizione sparisce il resto del tempo così non interferisce mai con nient’altro.
La persistenza richiede JavaScript — e qui torna, nello spirito, il fix del flicker della lezione 2. Due piccoli script in Site Settings: uno nell’head che gira prima del paint, legge il tema salvato da localStorage (con fallback al prefers-color-scheme di sistema) e applica la classe dark-mode; e uno nel footer che salva la scelta corrente in localStorage a ogni toggle. Fondamentale: la classe di persistenza va sull’elemento <html>, non su <body> — html esiste prima che il body venga renderizzato, quindi applicare la classe prima del primo paint significa nessun flash del tema sbagliato. (Per questo, cambia anche il target della set-class del toggle da body a html.)
Lo script nell’head legge il tema salvato prima che la pagina venga renderizzata:
<!-- Site Settings → Custom Code → Head -->
<script>
/**
* THEME CHECKER
* Executed before the body renders to prevent the "white flash" (flicker).
*/
(function () {
const savedTheme = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
// Dark if the user chose it before, or has no choice but their system prefers dark
if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
document.documentElement.classList.add('dark-mode');
}
})();
</script>
Lo script nel footer salva la scelta a ogni toggle (sostituisci .mode-toggle con la classe del tuo pulsante):
<!-- Site Settings → Custom Code → Before </body> tag -->
<script>
/**
* THEME TOGGLE MANAGER
* Handles the click event and persistence.
*/
document.addEventListener("DOMContentLoaded", () => {
const themeToggle = document.querySelector('.mode-toggle');
const htmlElement = document.documentElement;
if (themeToggle) {
themeToggle.addEventListener('click', () => {
// Read the class on documentElement to stay consistent with the head script
const isGoingToDark = !htmlElement.classList.contains('dark-mode');
if (isGoingToDark) {
localStorage.setItem('theme', 'dark');
} else {
localStorage.setItem('theme', 'light');
}
});
}
});
</script>
Come si usa
- Imposta le variabili. Crea una collezione di variabili colore, raggruppa i colori e aggiungi un variable mode manuale chiamato dark mode con valori sovrascritti.
- Collega i colori al sistema. Assegna le variabili prima a livello Body (All Pages), poi a classi/stati specifici così tutto ciò che il tema tocca è guidato dalle variabili.
- Costruisci le interazioni del toggle. Un’interazione muove il knob dello switch (anima X, toggle play/reverse). Un’altra usa una action set → class → toggle su
dark-mode(targethtml), toggle play/reverse, runs on all pages. - Aggiungi la transizione fluida. Incolla il CSS
theme-transitionnell’head. Nell’interazione dello switch, settheme-transitionon a 0s e off a 0.8s. Tieni un elementotheme-transitionnello style guide così Webflow mantiene la classe. - Aggiungi la persistenza. Aggiungi gli script head + footer (dal cloneable) per localStorage + prefers-color-scheme, poi rendi il toggle un componente e riusalo su tutte le pagine. Pubblica e prova sul link live (il codice custom non gira sempre in preview).
Entrambi gli script qui sopra sono quelli del cloneable — basta sostituire
.mode-togglecon la classe del tuo toggle e tenere allineato il nome della classedark-mode.