A Pen by joncreative on CodePen.
Created
June 9, 2025 12:47
-
-
Save jonnyvpc/38d85f0439821cb2cccd1b7f3e7c1bcb to your computer and use it in GitHub Desktop.
compare to the previous example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<style> | |
.ba-comparison-widget * { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
.ba-comparison-widget { | |
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; | |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
min-height: 100vh; | |
padding: 20px; | |
} | |
.ba-main-wrapper { | |
max-width: 1200px; | |
margin: 0 auto; | |
background: white; | |
border-radius: 20px; | |
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); | |
overflow: hidden; | |
} | |
.ba-hero-section { | |
text-align: center; | |
padding: 40px 20px; | |
background: linear-gradient(135deg, #2c3e50, #34495e); | |
color: white; | |
} | |
.ba-hero-section h1 { | |
font-size: 2.5rem; | |
margin-bottom: 10px; | |
font-weight: 700; | |
} | |
.ba-hero-section p { | |
font-size: 1.2rem; | |
opacity: 0.9; | |
} | |
.ba-content-area { | |
padding: 40px; | |
position: relative; | |
} | |
/* Desktop Slider View */ | |
.ba-desktop-slider { | |
position: relative; | |
width: 100%; | |
height: 800px; | |
overflow: hidden; | |
border-radius: 15px; | |
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); | |
cursor: col-resize; | |
} | |
.ba-before-img, | |
.ba-after-img { | |
position: absolute; | |
top: 0; | |
width: 100%; | |
height: 100%; | |
background-size: cover; | |
background-position: center; | |
transition: all 0.3s ease; | |
} | |
.ba-before-img { | |
background-image: linear-gradient(45deg, #ff6b6b, #ee5a52); | |
background-size: cover; | |
z-index: 1; | |
} | |
.ba-after-img { | |
background-image: linear-gradient(45deg, #4ecdc4, #44a08d); | |
background-size: cover; | |
z-index: 2; | |
clip-path: inset(0 50% 0 0); | |
} | |
/* Mock content for demonstration */ | |
.ba-img-content { | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
height: 100%; | |
color: white; | |
font-size: 2rem; | |
font-weight: bold; | |
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); | |
} | |
.ba-drag-handle { | |
position: absolute; | |
top: 0; | |
left: 50%; | |
width: 4px; | |
height: 100%; | |
background: white; | |
z-index: 10; | |
transform: translateX(-50%); | |
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); | |
} | |
.ba-drag-handle::before { | |
content: ''; | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
width: 40px; | |
height: 40px; | |
background: white; | |
border-radius: 50%; | |
transform: translate(-50%, -50%); | |
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
} | |
.ba-drag-handle::after { | |
content: '⟷'; | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
color: #333; | |
font-size: 16px; | |
font-weight: bold; | |
} | |
/* Mobile Toggle View */ | |
.ba-mobile-toggle { | |
display: none; | |
} | |
.ba-toggle-btns { | |
display: flex; | |
margin-bottom: 20px; | |
border-radius: 10px; | |
overflow: hidden; | |
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); | |
} | |
.ba-toggle-btn { | |
flex: 1; | |
padding: 15px 20px; | |
background: #f8f9fa; | |
border: none; | |
font-size: 1.1rem; | |
font-weight: 600; | |
cursor: pointer; | |
transition: all 0.3s ease; | |
} | |
.ba-toggle-btn.ba-active { | |
background: #007bff; | |
color: white; | |
} | |
.ba-toggle-display { | |
width: 100%; | |
height: 700px; | |
border-radius: 15px; | |
overflow: hidden; | |
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); | |
} | |
/* Callouts */ | |
.ba-callout { | |
position: absolute; | |
background: rgba(255, 255, 255, 0.95); | |
padding: 12px 16px; | |
border-radius: 8px; | |
font-size: 0.9rem; | |
font-weight: 600; | |
color: #333; | |
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); | |
backdrop-filter: blur(10px); | |
border-left: 4px solid #007bff; | |
max-width: 200px; | |
z-index: 5; | |
transition: all 0.3s ease; | |
} | |
.ba-callout::before { | |
content: ''; | |
position: absolute; | |
width: 12px; | |
height: 12px; | |
background: #007bff; | |
border-radius: 50%; | |
transform: translate(-50%, -50%); | |
} | |
.ba-callout-1 { | |
top: 20%; | |
left: 25%; | |
} | |
.ba-callout-1::before { | |
top: -6px; | |
left: -10px; | |
} | |
.ba-callout-2 { | |
top: 60%; | |
right: 20%; | |
} | |
.ba-callout-2::before { | |
top: -6px; | |
right: -10px; | |
} | |
.ba-callout-3 { | |
bottom: 20%; | |
left: 30%; | |
} | |
.ba-callout-3::before { | |
bottom: -6px; | |
left: -10px; | |
} | |
/* Stats Section */ | |
.ba-stats-area { | |
background: #f8f9fa; | |
padding: 40px; | |
text-align: center; | |
} | |
.ba-stats-grid { | |
display: grid; | |
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); | |
gap: 30px; | |
margin-top: 30px; | |
} | |
.ba-stat-card { | |
background: white; | |
padding: 25px; | |
border-radius: 15px; | |
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); | |
transition: transform 0.3s ease; | |
} | |
.ba-stat-card:hover { | |
transform: translateY(-5px); | |
} | |
.ba-stat-value { | |
font-size: 2.5rem; | |
font-weight: 700; | |
color: #007bff; | |
display: block; | |
} | |
.ba-stat-desc { | |
color: #666; | |
font-size: 1.1rem; | |
margin-top: 5px; | |
} | |
/* Responsive Design */ | |
@media (max-width: 768px) { | |
.ba-desktop-slider { | |
display: none; | |
} | |
.ba-mobile-toggle { | |
display: block; | |
} | |
.ba-hero-section h1 { | |
font-size: 2rem; | |
} | |
.ba-content-area { | |
padding: 20px; | |
} | |
.ba-callout { | |
font-size: 0.8rem; | |
padding: 8px 12px; | |
max-width: 150px; | |
} | |
.ba-stats-grid { | |
grid-template-columns: 1fr; | |
gap: 20px; | |
} | |
.ba-stat-value { | |
font-size: 2rem; | |
} | |
.ba-comparison-widget { | |
padding: 10px; | |
min-height: auto; | |
} | |
} | |
/* Accessibility */ | |
.ba-desktop-slider:focus { | |
outline: 3px solid #007bff; | |
outline-offset: 2px; | |
} | |
.ba-toggle-btn:focus { | |
outline: 2px solid #007bff; | |
outline-offset: 2px; | |
} | |
/* Animation for smooth transitions */ | |
.ba-fade-in { | |
animation: baFadeIn 0.5s ease-in; | |
} | |
@keyframes baFadeIn { | |
from { | |
opacity: 0; | |
transform: translateY(20px); | |
} | |
to { | |
opacity: 1; | |
transform: translateY(0); | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div class="ba-comparison-widget"> | |
<div class="ba-main-wrapper"> | |
<div class="ba-hero-section"> | |
<h1>Before vs After</h1> | |
<p>See the transformation in action</p> | |
</div> | |
<div class="ba-content-area"> | |
<!-- Desktop Slider View --> | |
<div class="ba-desktop-slider" id="baSliderContainer" tabindex="0" role="img" aria-label="Before and after comparison slider"> | |
<div class="ba-before-img"> | |
<div class="ba-img-content"> | |
<div> | |
<h3>BEFORE</h3> | |
<p style="font-size: 1rem; margin-top: 10px;">Old Design</p> | |
</div> | |
</div> | |
</div> | |
<div class="ba-after-img" id="baAfterImage"> | |
<div class="ba-img-content"> | |
<div> | |
<h3>AFTER</h3> | |
<p style="font-size: 1rem; margin-top: 10px;">New & Improved</p> | |
</div> | |
</div> | |
</div> | |
<div class="ba-drag-handle" id="baSliderHandle"></div> | |
<!-- Callouts for Desktop --> | |
<div class="ba-callout ba-callout-1" id="baCallout1"> | |
<strong>Tiny Text</strong><br> | |
Hard to read on mobile | |
</div> | |
<div class="ba-callout ba-callout-2" id="baCallout2"> | |
<strong>Cluttered Layout</strong><br> | |
Information overload | |
</div> | |
<div class="ba-callout ba-callout-3" id="baCallout3"> | |
<strong>Poor Contrast</strong><br> | |
Accessibility issues | |
</div> | |
</div> | |
<!-- Mobile Toggle View --> | |
<div class="ba-mobile-toggle"> | |
<div class="ba-toggle-btns"> | |
<button class="ba-toggle-btn ba-active" id="baBeforeBtn" aria-pressed="true">Before</button> | |
<button class="ba-toggle-btn" id="baAfterBtn" aria-pressed="false">After</button> | |
</div> | |
<div class="ba-toggle-display" id="baToggleImage"> | |
<div class="ba-before-img"> | |
<div class="ba-img-content"> | |
<div> | |
<h3>BEFORE</h3> | |
<p style="font-size: 1rem; margin-top: 10px;">Old Design</p> | |
</div> | |
</div> | |
</div> | |
<!-- Mobile Callouts --> | |
<div class="ba-callout ba-callout-1" id="baMobileCallout1"> | |
<strong>Tiny Text</strong><br> | |
Hard to read | |
</div> | |
<div class="ba-callout ba-callout-2" id="baMobileCallout2"> | |
<strong>Cluttered</strong><br> | |
Too much info | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="ba-stats-area"> | |
<h2 style="font-size: 2rem; margin-bottom: 10px; color: #333;">Proven Results</h2> | |
<p style="color: #666; font-size: 1.1rem;">Real improvements, measurable impact</p> | |
<div class="ba-stats-grid"> | |
<div class="ba-stat-card"> | |
<span class="ba-stat-value">73%</span> | |
<div class="ba-stat-desc">Better User Experience</div> | |
</div> | |
<div class="ba-stat-card"> | |
<span class="ba-stat-value">2.4x</span> | |
<div class="ba-stat-desc">Faster Load Times</div> | |
</div> | |
<div class="ba-stat-card"> | |
<span class="ba-stat-value">89%</span> | |
<div class="ba-stat-desc">Mobile Optimization</div> | |
</div> | |
<div class="ba-stat-card"> | |
<span class="ba-stat-value">95%</span> | |
<div class="ba-stat-desc">Accessibility Score</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
(function() { | |
// Desktop Slider Functionality | |
const sliderContainer = document.getElementById('baSliderContainer'); | |
const afterImage = document.getElementById('baAfterImage'); | |
const sliderHandle = document.getElementById('baSliderHandle'); | |
const callout1 = document.getElementById('baCallout1'); | |
const callout2 = document.getElementById('baCallout2'); | |
const callout3 = document.getElementById('baCallout3'); | |
let isDragging = false; | |
let currentPosition = 50; // Start at 50% | |
function updateSlider(percentage) { | |
percentage = Math.max(0, Math.min(100, percentage)); | |
currentPosition = percentage; | |
// Update after image clip-path | |
afterImage.style.clipPath = `inset(0 ${100 - percentage}% 0 0)`; | |
// Update slider handle position | |
sliderHandle.style.left = `${percentage}%`; | |
// Update callouts based on position | |
updateCallouts(percentage); | |
} | |
function updateCallouts(percentage) { | |
if (percentage < 30) { | |
// Mostly "before" showing | |
callout1.innerHTML = '<strong>Tiny Text</strong><br>Hard to read on mobile'; | |
callout2.innerHTML = '<strong>Cluttered Layout</strong><br>Information overload'; | |
callout3.innerHTML = '<strong>Poor Contrast</strong><br>Accessibility issues'; | |
} else if (percentage > 70) { | |
// Mostly "after" showing | |
callout1.innerHTML = '<strong>Large Text</strong><br>Easy to read anywhere'; | |
callout2.innerHTML = '<strong>Clean Design</strong><br>Focused experience'; | |
callout3.innerHTML = '<strong>High Contrast</strong><br>WCAG compliant'; | |
} else { | |
// Transition state | |
callout1.innerHTML = '<strong>Text Size</strong><br>Before vs After'; | |
callout2.innerHTML = '<strong>Layout</strong><br>Comparing designs'; | |
callout3.innerHTML = '<strong>Accessibility</strong><br>Major improvement'; | |
} | |
} | |
// Mouse events | |
sliderContainer.addEventListener('mousedown', (e) => { | |
isDragging = true; | |
updateSliderPosition(e); | |
}); | |
sliderContainer.addEventListener('mousemove', (e) => { | |
if (isDragging) { | |
updateSliderPosition(e); | |
} | |
}); | |
document.addEventListener('mouseup', () => { | |
isDragging = false; | |
}); | |
// Touch events for mobile | |
sliderContainer.addEventListener('touchstart', (e) => { | |
e.preventDefault(); | |
isDragging = true; | |
updateSliderPosition(e.touches[0]); | |
}); | |
sliderContainer.addEventListener('touchmove', (e) => { | |
e.preventDefault(); | |
if (isDragging) { | |
updateSliderPosition(e.touches[0]); | |
} | |
}); | |
sliderContainer.addEventListener('touchend', () => { | |
isDragging = false; | |
}); | |
// Keyboard accessibility | |
sliderContainer.addEventListener('keydown', (e) => { | |
switch (e.key) { | |
case 'ArrowLeft': | |
e.preventDefault(); | |
updateSlider(currentPosition - 5); | |
break; | |
case 'ArrowRight': | |
e.preventDefault(); | |
updateSlider(currentPosition + 5); | |
break; | |
case 'Home': | |
e.preventDefault(); | |
updateSlider(0); | |
break; | |
case 'End': | |
e.preventDefault(); | |
updateSlider(100); | |
break; | |
} | |
}); | |
function updateSliderPosition(event) { | |
const rect = sliderContainer.getBoundingClientRect(); | |
const x = event.clientX - rect.left; | |
const percentage = (x / rect.width) * 100; | |
updateSlider(percentage); | |
} | |
// Mobile Toggle Functionality | |
const beforeBtn = document.getElementById('baBeforeBtn'); | |
const afterBtn = document.getElementById('baAfterBtn'); | |
const toggleImage = document.getElementById('baToggleImage'); | |
function showBefore() { | |
beforeBtn.classList.add('ba-active'); | |
afterBtn.classList.remove('ba-active'); | |
beforeBtn.setAttribute('aria-pressed', 'true'); | |
afterBtn.setAttribute('aria-pressed', 'false'); | |
toggleImage.innerHTML = ` | |
<div class="ba-before-img"> | |
<div class="ba-img-content"> | |
<div> | |
<h3>BEFORE</h3> | |
<p style="font-size: 1rem; margin-top: 10px;">Old Design</p> | |
</div> | |
</div> | |
</div> | |
<div class="ba-callout ba-callout-1"> | |
<strong>Tiny Text</strong><br> | |
Hard to read | |
</div> | |
<div class="ba-callout ba-callout-2"> | |
<strong>Cluttered</strong><br> | |
Too much info | |
</div> | |
`; | |
toggleImage.classList.add('ba-fade-in'); | |
} | |
function showAfter() { | |
afterBtn.classList.add('ba-active'); | |
beforeBtn.classList.remove('ba-active'); | |
afterBtn.setAttribute('aria-pressed', 'true'); | |
beforeBtn.setAttribute('aria-pressed', 'false'); | |
toggleImage.innerHTML = ` | |
<div class="ba-after-img" style="clip-path: none;"> | |
<div class="ba-img-content"> | |
<div> | |
<h3>AFTER</h3> | |
<p style="font-size: 1rem; margin-top: 10px;">New & Improved</p> | |
</div> | |
</div> | |
</div> | |
<div class="ba-callout ba-callout-1"> | |
<strong>Large Text</strong><br> | |
Easy to read | |
</div> | |
<div class="ba-callout ba-callout-2"> | |
<strong>Clean Design</strong><br> | |
Focused UI | |
</div> | |
`; | |
toggleImage.classList.add('ba-fade-in'); | |
} | |
beforeBtn.addEventListener('click', showBefore); | |
afterBtn.addEventListener('click', showAfter); | |
// Initialize | |
updateSlider(50); | |
// Remove animation class after animation completes | |
toggleImage.addEventListener('animationend', () => { | |
toggleImage.classList.remove('ba-fade-in'); | |
}); | |
})(); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment