A before/after image comparison slider in ~3 KB of vanilla JavaScript. No jQuery, no Swiper, no build step.
Most before/after sliders drag in a carousel library for one drag handle, or break the moment you drop them into a flex or grid parent. This one is two files, keyboard accessible, and sized in CSS so it behaves inside any layout.
- Mouse, touch and pen through Pointer Events
- Full keyboard control with proper
role="slider"semantics - No horizontal overflow — clipping is done with
clip-path, not negative margins - Vertical page scrolling still works when you swipe over it on mobile
- Respects
prefers-reduced-motion - Theme it with CSS custom properties
Copy the two files into your project:
<link rel="stylesheet" href="assets/css/ba-slider.css">
<script src="assets/js/ba-slider.js" defer></script>Then start every slider on the page:
<script>
document.addEventListener('DOMContentLoaded', function () {
BASlider.init();
});
</script><div class="ba" data-ba-slider data-ba-start="50">
<img src="before.jpg" alt="Before">
<div class="ba__layer--after" data-ba-after>
<img src="after.jpg" alt="After">
</div>
<div class="ba__handle" data-ba-handle>
<span class="ba__grip"></span>
</div>
</div>Both images need the same aspect ratio. The first one sets the height of the frame.
| Attribute | Default | What it does |
|---|---|---|
data-ba-start |
50 |
Where the split sits on load, 0–100 |
data-ba-step |
2 |
How far one arrow-key press moves the handle |
data-ba-label |
— | Screen-reader name for the handle |
data-ba-readout |
— | A selector, e.g. #split. That element gets the live percentage |
const slider = new BASlider('#hero-compare', { start: 30 });
slider.set(80); // move it yourself
slider.destroy(); // unbind everythingIt fires a ba:change event while dragging:
slider.root.addEventListener('ba:change', (e) => {
console.log(e.detail.value); // 0–100
});| Key | Action |
|---|---|
← ↓ |
Move left one step |
→ ↑ |
Move right one step |
Page Up / Page Down |
Move ten steps |
Home / End |
Jump to either end |
.ba {
--ba-line: #ffffff; /* the divider */
--ba-handle-bg: #ffffff; /* the grip circle */
--ba-handle-fg: #14201c; /* the arrows */
--ba-radius: 4px;
}Any browser with Pointer Events and clip-path — Chrome, Edge, Firefox, Safari 13.1+.
MIT