Come creare un effetto “Before & After” con due immagini (senza plugin) in WordPress
Vuoi mostrare ai visitatori il prima e dopo di una ristrutturazione, di un progetto grafico o di un restyling?
In questo tutorial ti spiego come creare un effetto Before / After interattivo utilizzando solo HTML, CSS e JavaScript, senza alcun plugin.
Funziona perfettamente anche su Brizy Cloud, Elementor, Divi o in un blocco HTML personalizzato di WordPress.
Clicca sulla linea e trascina il tuo mouse per scoprire l'immagine!
Trascina il tuo dito sulla linea per scoprire l'immagine!
PrimaDopo
Cosa realizzeremo
Il risultato finale è un’immagine in formato 16:9 con una linea verticale centrale:
a sinistra, la foto del “prima”;
a destra, la foto del “dopo”;
con la possibilità di trascinare la linea per confrontare le due immagini.
L’effetto è fluido, reattivo e mobile-friend
Il codice completo
Incolla questo codice in un blocco HTML o blocco “Codice” di Brizy Cloud / Divi / WordPress:
Di seguito trovi il codice completo da copiare per creare un confronto tra due immagini, una “prima” e una “dopo”, con trascinamento della linea centrale. Funziona anche su dispositivi mobili.
<!-- ========================================================= -->
<!-- EFFETTO IMMAGINE PRIMA/DOPO con Oscillazione e Ritorno Automatico -->
<!-- ========================================================= -->
<div class="before-after-container">
<img src="https://tuosito.com/path/dopo.jpg" alt="Dopo dei lavori" class="before-img">
<img src="https://tuosito.com/path/prima.jpg" alt="Prima dei lavori" class="after-img">
<div class="slider-handle"></div>
<span class="label before">Prima</span>
<span class="label after">Dopo</span>
</div>
<style>
.before-after-container {
position: relative;
width: 100%;
max-width: 800px;
aspect-ratio: 16 / 9;
overflow: hidden;
margin: 40px auto;
user-select: none;
touch-action: none;
}
.before-after-container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
pointer-events: none;
}
.after-img {
clip-path: inset(0 50% 0 0);
transition: none; /* Rimosso transition per lo script JS */
}
.slider-handle {
position: absolute;
top: 0;
left: 50%;
width: 3px;
height: 100%;
background: white;
border: 1px solid rgba(0,0,0,0.3);
box-shadow: 0 0 5px rgba(0,0,0,0.3);
cursor: ew-resize;
z-index: 10;
}
.label {
position: absolute;
top: 10px;
padding: 4px 8px;
background: rgba(0,0,0,0.6);
color: white;
font-size: 14px;
border-radius: 4px;
z-index: 20;
transition: opacity 0.3s ease;
}
.label.before { left: 10px; }
.label.after { right: 10px; }
/* Le etichette scompaiono durante il trascinamento e l'oscillazione */
.before-after-container.dragging .label {
opacity: 0;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", () => {
const container = document.querySelector('.before-after-container');
if (!container) return;
const afterImg = container.querySelector('.after-img');
const handle = container.querySelector('.slider-handle');
let isDragging = false;
let isAutoMoving = true;
// ? Parametri principali dell'oscillazione
const centerPercent = 50;
const amplitude = 7.5;
const speed = 0.030;
let theta = 0;
function setPercent(percent) {
const pct = Math.max(0, Math.min(100, percent));
afterImg.style.clipPath = `inset(0 ${100 - pct}% 0 0)`;
handle.style.left = pct + '%';
}
function percentFromClientX(clientX) {
const rect = container.getBoundingClientRect();
const x = clientX - rect.left;
return (x / rect.width) * 100;
}
function stopAuto() {
isAutoMoving = false;
// Qui potresti aggiungere o rimuovere una classe per un effetto visivo
}
// Ritorna la linea al centro con animazione e riavvia l'oscillazione
function resetAndStartAuto() {
if (isAutoMoving) return;
const currentPct = parseFloat(handle.style.left) || centerPercent;
const duration = 500;
const startTime = performance.now();
function easeBack() {
const elapsed = performance.now() - startTime;
const progress = Math.min(1, elapsed / duration);
// Easing cubico
const easedProgress = 1 - Math.pow(1 - progress, 3);
const newPct = currentPct + (centerPercent - currentPct) * easedProgress;
setPercent(newPct);
if (progress < 1) {
requestAnimationFrame(easeBack);
} else {
// Riavvia l'oscillazione dal centro
isAutoMoving = true;
theta = 0;
requestAnimationFrame(animateOscillation);
}
}
requestAnimationFrame(easeBack);
}
// ✨ Animazione sinusoidale standard
function animateOscillation() {
if (!isAutoMoving) {
return;
}
theta += speed;
const eased = Math.sin(theta);
const pct = centerPercent + eased * amplitude;
setPercent(pct);
requestAnimationFrame(animateOscillation);
}
requestAnimationFrame(animateOscillation);
// --- Interazioni Desktop ---
handle.addEventListener('mousedown', (e) => {
isDragging = true;
container.classList.add('dragging');
stopAuto();
e.preventDefault();
});
window.addEventListener('mouseup', () => {
isDragging = false;
container.classList.remove('dragging');
});
window.addEventListener('mousemove', (e) => {
if (!isDragging) return;
setPercent(percentFromClientX(e.clientX));
});
// --- Interazioni Touch ---
handle.addEventListener('touchstart', (e) => {
isDragging = true;
container.classList.add('dragging');
stopAuto();
}, { passive: true });
window.addEventListener('touchend', () => {
// 1. Controlla se l'utente stava effettivamente trascinando
if (isDragging) {
// 2. Resetta i flag di trascinamento
isDragging = false;
container.classList.remove('dragging');
// 3. Avvia il rientro al centro e l'oscillazione
resetAndStartAuto(); // <-- AGGIUNTO IL RIAVVIO
}
});
window.addEventListener('touchmove', (e) => {
if (!isDragging) return;
const touch = e.touches && e.touches[0];
if (!touch) return;
setPercent(percentFromClientX(touch.clientX));
}, { passive: true });
// ? Pausa all'ingresso del mouse/touch
container.addEventListener('mouseover', stopAuto);
container.addEventListener('touchstart', stopAuto, { once: true });
// ▶️ Ritorno al centro e Riavvio all'uscita del mouse
container.addEventListener('mouseleave', () => {
// Si riavvia solo se l'utente non sta trascinando attivamente
if (!isDragging) {
resetAndStartAuto();
}
});
});
</script>
Puoi incollare il codice sopra in un blocco “HTML personalizzato” di WordPress, Brizy o Divi.
Sostituisci semplicemente gli URL https://tuosito.com/path/prima.jpg e https://tuosito.com/path/dopo.jpg con le tue immagini.
Disclosure: i collegamenti in questo sito sono "link di affiliazione". Ciò significa che se fai clic sul collegamento e acquisti l'articolo, riceveremo una commissione di affiliazione. Divi è un marchio registrato di Elegant Themes, Inc. Questo sito non fa parte di Elegant Themes inc.