Javascript Before and After Slider
A simple lightweight pure JavaScript script to create before and after image comparisons.
Javascript Before and After Slider
A simple lightweight pure JavaScript script to create before and after image comparisons.
This is fully compatible with modern browsers and requires no external dependencies.
You can view this project on Ben's GitHub account: https://github.com/benhall14/javascript-before-and-after-slider
Javascript Before & After Slider
A lightweight, dependency-free before/after comparison slider for plain JavaScript projects.
This package ships a browser-ready build in the dist folder and supports npm module imports as well as CDN or static-file use.
Installation
npm install javascript-before-and-after-slider
Package contents
The published package includes:
dist/before-and-after-slider.jsdist/before-and-after-slider.css
The JavaScript entry is configured as the package entry in package.json. In a browser, it initializes [data-slider] elements automatically when the page loads.
Quick start
<link rel="stylesheet" href="./dist/before-and-after-slider.css" />
<script src="./dist/before-and-after-slider.js"></script>
<div
data-slider
data-slider-media-1="./images/before.jpg"
data-slider-media-2="./images/after.jpg"
></div>
The script discovers every element with data-slider and builds the slider UI for you.
npm module usage
The package can also be imported as a module. The default export provides initSlider, initAll, and observe:
// ES Modules
import Slider from 'javascript-before-and-after-slider';
Slider.initAll();
// CommonJS
const Slider = require('javascript-before-and-after-slider');
Slider.initAll();
The module does not initialize anything when imported outside a browser. In a browser, it still supports the plain <script> usage and automatically initializes [data-slider] elements.
The script also injects its own CSS automatically if needed, so including the CSS file is optional for basic use. Keeping the stylesheet in the page is still recommended when you want explicit control over styling and asset loading.
Basic usage
<div
data-slider
data-slider-media-1="before.jpg"
data-slider-media-2="after.jpg"
data-start="50"
data-orientation="horizontal"
></div>
Supported attributes
data-slider— marks the element as a sliderdata-slider-media-1— first media sourcedata-slider-media-2— second media sourcedata-start— initial comparison position in percent, default50data-orientation—horizontalorverticaldata-label-before— show a before labeldata-label-after— show an after labeldata-label-text-before— custom before label textdata-label-text-after— custom after label textdata-autoslide— enable automatic slidingdata-autoslide-interval— interval in secondsdata-move-on-hover— move the comparison on hoverdata-slide-on-scroll— tie movement to page scroll
Example with labels
<div
data-slider
data-slider-media-1="before.jpg"
data-slider-media-2="after.jpg"
data-label-before="yes"
data-label-after="yes"
data-label-text-before="Before"
data-label-text-after="After"
></div>
Images, videos and embeds
The library supports image sources, video sources, and embedded media such as YouTube or Vimeo URLs.
<div
data-slider
data-slider-media-1="./images/before.mp4"
data-slider-media-2="./images/after.mp4"
data-media-1-type="video"
data-media-2-type="video"
></div>
<div
data-slider
data-slider-media-1="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
data-slider-media-2="https://example.com/after.jpg"
></div>
Manual initialization
When using npm, the default export provides the initialization API:
import Slider from 'javascript-before-and-after-slider';
const slider = Slider.initSlider(document.querySelector('[data-slider]'));
// slider.destroy() to remove the generated slider
The equivalent CommonJS form is:
const Slider = require('javascript-before-and-after-slider');
const slider = Slider.initSlider(document.querySelector('[data-slider]'));
For a browser script or CDN installation, the same API is available through window:
<script src="./dist/before-and-after-slider.js"></script>
<script>
const slider = CBASP_initSlider(document.querySelector('[data-slider]'));
// slider.destroy() to remove the generated slider
</script>
You can also initialize all sliders on a page. With npm:
Slider.initAll();
With a browser script:
CBASP_initAll();
To observe dynamically inserted sliders, use Slider.observe(document.body) with npm or:
CBASP_observe(document.body);
Styling
The package exposes CSS variables for common customisation:
[data-slider] {
--cbasp-max-width: 900px;
--cbasp-aspect: 16 / 9;
--cbasp-bar-color: #ffffff;
--cbasp-bar-width: 4px;
--cbasp-handle-bg: #ffffff;
--cbasp-handle-border: #3b82f6;
--cbasp-icon-color: #3b82f6;
--cbasp-label-bg: rgba(0, 0, 0, 0.6);
--cbasp-label-color: #ffffff;
--cbasp-radius: 12px;
}
Notes for npm release
- The package is intentionally small and dependency-free.
- The public API is HTML-first: create a
[data-slider]container and providedata-slider-media-*attributes. - The browser bundle lives under
distand is what npm consumers should import. - This repository is best used as a static asset package or a simple JavaScript library for non-module sites.
License
MIT
The value is specified in seconds.
Example:
<div
data-slider
data-slider-media-1="before.jpg"
data-slider-media-2="after.jpg"
data-autoslide="yes"
data-autoslide-interval="5"
></div>
For a faster demonstration:
data-autoslide-interval="2"
For a slower presentation:
data-autoslide-interval="8"
Recommended auto-slide configuration
For a landing-page demonstration:
<div
data-slider
data-slider-media-1="images/before.jpg"
data-slider-media-2="images/after.jpg"
data-start="50"
data-autoslide="yes"
data-autoslide-interval="5"
data-label-before="yes"
data-label-after="yes"
data-label-text-before="BEFORE"
data-label-text-after="AFTER"
></div>
Scroll-Driven Sliding
The slider can also respond to page scrolling.
Enable:
data-slide-on-scroll="yes"
Example:
<div
data-slider
data-slider-media-1="before.jpg"
data-slider-media-2="after.jpg"
data-slide-on-scroll="yes"
></div>
This is particularly useful for:
- long landing pages
- case studies
- portfolio pages
- product demonstrations
- animated storytelling sections
Scroll + labels
<div
data-slider
data-slider-media-1="images/before.jpg"
data-slider-media-2="images/after.jpg"
data-slide-on-scroll="yes"
data-label-before="yes"
data-label-after="yes"
data-label-text-before="BEFORE"
data-label-text-after="AFTER"
></div>
Images
The normal use case is two images with matching dimensions/aspect ratios.
<div
data-slider
data-slider-media-1="/images/before.jpg"
data-slider-media-2="/images/after.jpg"
></div>
Best practice
For the cleanest comparison:
- use the same dimensions
- use the same crop
- use the same aspect ratio
- use images showing the same subject
- avoid changing the camera position between Before and After
For example:
before.jpg 1600 × 900
after.jpg 1600 × 900
is preferable to:
before.jpg 1600 × 900
after.jpg 1200 × 1200
Video
The same media configuration can be used for video where supported by the build.
Example:
<div
data-slider
data-slider-media-1="/video/before.mp4"
data-slider-media-2="/video/after.mp4"
></div>
Where explicit media type configuration is required, use the media-type attributes supported by the build.
A video comparison is useful for:
- motion graphics
- animation
- restoration
- video colour grading
- property walkthroughs
- visual effects
- editing demonstrations
YouTube and Vimeo
For hosted video platforms, provide the relevant URL as the media source where supported.
Example:
<div
data-slider
data-slider-media-1="https://www.youtube.com/watch?v=VIDEO_ID_1"
data-slider-media-2="https://www.youtube.com/watch?v=VIDEO_ID_2"
></div>
Vimeo example:
<div
data-slider
data-slider-media-1="https://vimeo.com/VIDEO_ID_1"
data-slider-media-2="https://vimeo.com/VIDEO_ID_2"
></div>
Platform video behaviour can differ from local
<video>elements because playback, autoplay, browser policies and cross-origin restrictions are controlled by the video provider.
Appearance and Styling
The self-contained build supports configuration through data attributes for common visual settings.
Bar colour
data-bar-color="#b9f4ff"
Example:
<div
data-slider
data-slider-media-1="before.jpg"
data-slider-media-2="after.jpg"
data-bar-color="#b9f4ff"
></div>
Bar width
data-bar-width="4"
Example:
data-bar-width="4"
A thinner divider:
data-bar-width="2"
A heavier divider:
data-bar-width="6"
Handle size
data-handle-size="44"
Example:
<div
data-slider
data-slider-media-1="before.jpg"
data-slider-media-2="after.jpg"
data-handle-size="44"
></div>
Larger handle:
data-handle-size="56"
Smaller handle:
data-handle-size="36"
Handle background
data-handle-bg="#ffffff"
Example:
data-handle-bg="#ffffff"
Handle border
data-handle-border="#b9f4ff"
Example:
data-handle-border="#b9f4ff"
Handle icon colour
data-icon-color="#b9f4ff"
Example:
data-icon-color="#b9f4ff"
Handle icon
The build supports the configured handle icon styles.
Example:
data-icon="arrows"
Border radius
data-border-radius="16"
Example:
<div
data-slider
data-slider-media-1="before.jpg"
data-slider-media-2="after.jpg"
data-border-radius="16"
></div>
Square corners:
data-border-radius="0"
Rounded:
data-border-radius="24"
Shadow
Enable:
data-shadow="yes"
Disable:
data-shadow="no"
Example:
<div
data-slider
data-slider-media-1="before.jpg"
data-slider-media-2="after.jpg"
data-shadow="yes"
></div>
Complete Examples
Example 1 — Minimal
<div
data-slider
data-slider-media-1="before.jpg"
data-slider-media-2="after.jpg"
></div>
Example 2 — Standard Before & After
<div
data-slider
data-slider-media-1="images/before.jpg"
data-slider-media-2="images/after.jpg"
data-start="50"
data-label-before="yes"
data-label-after="yes"
data-label-text-before="BEFORE"
data-label-text-after="AFTER"
></div>
Example 3 — Website redesign
<div
data-slider
data-slider-media-1="images/website-old.jpg"
data-slider-media-2="images/website-new.jpg"
data-start="50"
data-label-before="yes"
data-label-after="yes"
data-label-text-before="OLD WEBSITE"
data-label-text-after="NEW WEBSITE"
data-border-radius="16"
data-shadow="yes"
></div>
Example 4 — Move on hover
<div
data-slider
data-slider-media-1="images/before.jpg"
data-slider-media-2="images/after.jpg"
data-start="50"
data-move-on-hover="yes"
data-label-before="yes"
data-label-after="yes"
></div>
Example 5 — Auto-sliding
<div
data-slider
data-slider-media-1="images/before.jpg"
data-slider-media-2="images/after.jpg"
data-autoslide="yes"
data-autoslide-interval="5"
data-label-before="yes"
data-label-after="yes"
></div>
Example 6 — Scroll-controlled
<div
data-slider
data-slider-media-1="images/before.jpg"
data-slider-media-2="images/after.jpg"
data-slide-on-scroll="yes"
data-label-before="yes"
data-label-after="yes"
></div>
Example 7 — Vertical
<div
data-slider
data-slider-media-1="images/top.jpg"
data-slider-media-2="images/bottom.jpg"
data-orientation="vertical"
data-start="50"
data-label-before="yes"
data-label-after="yes"
></div>
Example 8 — Branded styling
<div
data-slider
data-slider-media-1="images/before.jpg"
data-slider-media-2="images/after.jpg"
data-start="50"
data-label-before="yes"
data-label-after="yes"
data-label-text-before="BEFORE"
data-label-text-after="AFTER"
data-bar-color="#b9f4ff"
data-bar-width="4"
data-handle-size="48"
data-handle-bg="#ffffff"
data-handle-border="#b9f4ff"
data-icon-color="#b9f4ff"
data-icon="arrows"
data-border-radius="16"
data-shadow="yes"
></div>
Multiple Sliders on One Page
Multiple sliders can use the same JavaScript file.
<div
data-slider
data-slider-media-1="images/kitchen-before.jpg"
data-slider-media-2="images/kitchen-after.jpg"
></div>
<div
data-slider
data-slider-media-1="images/bathroom-before.jpg"
data-slider-media-2="images/bathroom-after.jpg"
></div>
<div
data-slider
data-slider-media-1="images/garden-before.jpg"
data-slider-media-2="images/garden-after.jpg"
></div>
<script src="/assets/conobe-before-after-slider.js"></script>
Each element is initialised independently.
This means every slider can have different settings:
<div
data-slider
data-slider-media-1="before-1.jpg"
data-slider-media-2="after-1.jpg"
data-move-on-hover="yes"
></div>
<div
data-slider
data-slider-media-1="before-2.jpg"
data-slider-media-2="after-2.jpg"
data-autoslide="yes"
data-autoslide-interval="4"
></div>
<div
data-slider
data-slider-media-1="before-3.jpg"
data-slider-media-2="after-3.jpg"
data-orientation="vertical"
></div>
Using JavaScript Dynamically
Because the slider is generated by JavaScript, it can also be added to the DOM dynamically.
For example:
<div id="my-slider"></div>
Then populate the configuration:
const element = document.getElementById('my-slider');
element.setAttribute('data-slider', '');
element.setAttribute('data-slider-media-1', 'before.jpg');
element.setAttribute('data-slider-media-2', 'after.jpg');
After adding a slider dynamically, call the library's initialisation function if the build is not automatically observing DOM changes.
Initialisation and API
The library exposes initialisation functionality for pages that need more control.
Automatic initialisation
For normal HTML pages, simply include:
<script src="/assets/conobe-before-after-slider.js"></script>
The library will automatically discover [data-slider] elements.
Manual initialisation
Where supported by the build, the public initialisation methods can be used:
CBASP_initAll();
This tells the library to initialise all matching slider elements.
For a specific element:
CBASP_initSlider(document.querySelector('[data-slider]'));
Example:
const slider = document.querySelector('#my-slider');
CBASP_initSlider(slider);
Destroying a Slider
When removing a slider from a page, it can be useful to destroy its generated state first.
Where supported:
sliderInstance.destroy();
This is particularly useful for:
- SPA navigation
- modal windows
- AJAX content
- Livewire updates
- Vue/React components
- dynamically replaced content
Recommended HTML Patterns
Recommended production pattern
Keep the markup simple:
<div
data-slider
data-slider-media-1="/images/project-before.webp"
data-slider-media-2="/images/project-after.webp"
data-label-before="yes"
data-label-after="yes"
data-label-text-before="BEFORE"
data-label-text-after="AFTER"
></div>
Avoid recreating the internal slider structure yourself.
The point of this build is that the internal structure belongs to the library.
Embedding on a Demo Site
A very simple demo page can be:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Conobe Before & After Slider Demo</title>
</head>
<body>
<h1>Before & After Slider</h1>
<div
data-slider
data-slider-media-1="/images/before.jpg"
data-slider-media-2="/images/after.jpg"
data-label-before="yes"
data-label-after="yes"
data-label-text-before="BEFORE"
data-label-text-after="AFTER"
></div>
<script src="/assets/conobe-before-after-slider.js"></script>
</body>
</html>
No:
<link rel="stylesheet" href="slider.css">
is required when using the self-contained build.
No:
<script src="jquery.js"></script>
is required.
No:
<script src="wordpress.js"></script>
is required.
The demo site therefore has a very small integration footprint.
Accessibility
When implementing sliders on a production site, consider:
- meaningful image content
- useful alternative text
- keyboard interaction
- sufficient contrast
- visible focus states
- avoiding motion that cannot be paused where appropriate
For example, the surrounding page can provide context:
<figure>
<div
data-slider
data-slider-media-1="/images/before.jpg"
data-slider-media-2="/images/after.jpg"
data-label-before="yes"
data-label-after="yes"
data-label-text-before="BEFORE"
data-label-text-after="AFTER"
></div>
<figcaption>
Kitchen renovation — comparison of the original and completed room.
</figcaption>
</figure>
Troubleshooting
Slider does not appear
Check that the container has:
data-slider
and that both media attributes are present:
data-slider-media-1="before.jpg"
data-slider-media-2="after.jpg"
Also check the browser developer console for JavaScript errors.
Images are not loading
Check the image URL directly.
For example:
data-slider-media-1="/images/before.jpg"
must point to a real accessible resource.
Common problems include:
- incorrect relative path
- case-sensitive filename mismatch
- missing image
- server permissions
- HTTPS/HTTP mixed content
- hotlink protection
The images do not line up
Use images with matching:
- width
- height
- aspect ratio
- crop
- camera position
For example:
Before: 1600 × 900
After: 1600 × 900
The slider is too small
The slider fills its containing element, so give the parent/container an appropriate width.
For example:
<div style="max-width: 1200px; margin: 0 auto;">
<div
data-slider
data-slider-media-1="before.jpg"
data-slider-media-2="after.jpg"
></div>
</div>
The slider is too tall or short
Use media with the desired aspect ratio and make sure the containing layout is not imposing an unexpected height.
Auto-slide is not working
Check:
data-autoslide="yes"
and, if required:
data-autoslide-interval="5"
Also check whether browser/user motion policies or the specific media type affect the behaviour.
Attribute Reference
The following is the intended public configuration surface.
| Attribute | Example | Purpose |
|---|---|---|
data-slider |
data-slider |
Marks an element as a slider |
data-slider-media-1 |
before.jpg |
First media source |
data-slider-media-2 |
after.jpg |
Second media source |
data-start |
50 |
Initial slider position |
data-orientation |
horizontal |
Horizontal or vertical slider |
data-label-before |
yes |
Enable Before label |
data-label-after |
yes |
Enable After label |
data-label-text-before |
BEFORE |
Before label text |
data-label-text-after |
AFTER |
After label text |
data-label-position |
top |
Label placement |
data-move-on-hover |
yes |
Move slider with mouse position |
data-slide-on-scroll |
yes |
Link slider movement to scrolling |
data-autoslide |
yes |
Enable automatic movement |
data-autoslide-interval |
5 |
Auto-slide interval |
data-bar-color |
#b9f4ff |
Divider colour |
data-bar-width |
4 |
Divider width |
data-handle-size |
44 |
Handle size |
data-handle-bg |
#ffffff |
Handle background |
data-handle-border |
#b9f4ff |
Handle border |
data-icon-color |
#b9f4ff |
Handle icon colour |
data-icon |
arrows |
Handle icon |
data-border-radius |
16 |
Corner radius |
data-shadow |
yes |
Slider shadow |
Recommended Default
For most Before & After demonstrations, this is a good starting point:
<div
data-slider
data-slider-media-1="/images/before.jpg"
data-slider-media-2="/images/after.jpg"
data-start="50"
data-orientation="horizontal"
data-label-before="yes"
data-label-after="yes"
data-label-text-before="BEFORE"
data-label-text-after="AFTER"
data-move-on-hover="no"
data-slide-on-scroll="no"
data-autoslide="no"
data-bar-color="#b9f4ff"
data-bar-width="4"
data-handle-size="44"
data-handle-bg="#ffffff"
data-handle-border="#b9f4ff"
data-icon-color="#b9f4ff"
data-icon="arrows"
data-border-radius="16"
data-shadow="yes"
></div>
This gives a conventional, manually controlled comparison with clear labels and branded styling.
One-File Installation
The final intended integration is:
your-website/
├── assets/
│ └── conobe-before-after-slider.js
├── images/
│ ├── before.jpg
│ └── after.jpg
└── index.html
index.html:
<div
data-slider
data-slider-media-1="/images/before.jpg"
data-slider-media-2="/images/after.jpg"
data-label-before="yes"
data-label-after="yes"
data-label-text-before="BEFORE"
data-label-text-after="AFTER"
></div>
<script src="/assets/conobe-before-after-slider.js"></script>
That is the key advantage of the self-contained build:
One JavaScript file + one simple HTML element = complete Before & After slider.
Requirements
None
License
Copyright (c) Benjamin Hall, ben@conobe.co.uk https://conobe.co.uk
Licensed under the MIT license
Donate?
If you find this project helpful or useful in anyway, please consider getting me a cup of coffee - It's really appreciated :)