Experience the powerful AI writing right inside WordPress
Show stunning before-and-after transformations with image sliders.
Improve user engagement by showing estimated reading time.
Written by Mahmuda Akter Isha
Showcase Designs Using Before After Slider.
You can create a before-and-after image comparison slider without JavaScript by stacking two images inside the same container and applying the CSS resize property to the top image layer. Visitors can horizontally resize that layer to reveal the image underneath.
resize
Before-and-after images are one of the clearest ways to demonstrate visual change. They are commonly used for photo editing, website redesigns, home renovations, beauty treatments, fitness progress, product restoration, and many other transformation-based projects.
Displaying the two images next to each other works, but it often makes small differences difficult to notice. A before-and-after image comparison slider solves this problem by placing both images in the same area and allowing visitors to reveal more or less of each version.
In this tutorial, you will learn how to create a before-and-after image comparison slider using HTML and pure CSS. The method does not require JavaScript, an external library, or a complex framework.
You will also learn how the slider works, how to customize it, how to make its layout responsive, and how to fix common image-alignment problems.
A before-and-after image comparison slider is an interactive visual component that displays two versions of the same subject in one shared frame.
One image normally represents the original or “before” version, while the other represents the edited or “after” version. Visitors move or resize a divider to compare the two images.
Unlike a regular image slider or carousel, an image comparison slider does not move between unrelated images. Instead, it overlays two closely matched images so users can inspect the differences between them.
Common uses include:
Yes. A basic comparison slider can be created with HTML and CSS only.
The CSS-only method in this tutorial uses the resize property. The “before” image is placed on top of the “after” image inside a resizable container. When the visitor changes the width of the top layer, more or less of the bottom image becomes visible.
This method is useful when you need:
However, a pure CSS slider also has limitations. The native resize control can look different across browsers, may be less obvious on mobile devices, and does not provide the same keyboard or touch experience as a custom JavaScript slider.
For a production website that requires a traditional draggable handle, keyboard control, and consistent touch support, use an HTML, CSS, and JavaScript implementation instead.
The slider will contain:
The two images must show the same scene from the same angle. They should also have identical dimensions and aspect ratios.
Create a new project folder and add the following files:
before-after-slider/ │ ├── index.html ├── style.css ├── before.jpg └── after.jpg
You can use different image filenames, but remember to update the HTML code accordingly.
Open your index.html file and add the following code:
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0" > <title>Pure CSS Before and After Image Slider</title> <link rel="stylesheet" href="style.css"> </head> <body> <main class="page-content"> <section class="comparison-section"> <h1>Before and After Image Comparison</h1> <p class="comparison-instruction"> Drag the resize control at the bottom-right corner of the before image to reveal the result. </p> <figure class="comparison-slider"> <img class="comparison-slider__after" src="after.jpg" alt="Renovated room after the redesign" > <span class="comparison-slider__label comparison-slider__label--after"> After </span> <div class="comparison-slider__before"> <img src="before.jpg" alt="Room before the redesign" > <span class="comparison-slider__label comparison-slider__label--before"> Before </span> </div> <figcaption class="visually-hidden"> A comparison between the room before and after renovation. </figcaption> </figure> </section> </main> </body> </html>
The .comparison-slider element acts as the main frame for both images.
.comparison-slider
The after image is placed at the bottom and always fills the complete slider. The .comparison-slider__before element sits above it and initially covers half of the after image.
.comparison-slider__before
Because the before layer can be resized horizontally, visitors can reveal the image beneath it.
The <figure> and <figcaption> elements give the comparison additional semantic meaning. Each image also includes descriptive alternative text.
<figure>
<figcaption>
Open your style.css file and add the following code:
style.css
* { box-sizing: border-box; } html { color-scheme: light; } body { margin: 0; min-height: 100vh; font-family: Arial, Helvetica, sans-serif; line-height: 1.6; color: #1f2937; background: #f3f4f6; } img { display: block; max-width: 100%; } .page-content { width: min(100% - 32px, 1100px); margin-inline: auto; padding-block: 64px; } .comparison-section { text-align: center; } .comparison-section h1 { margin: 0 0 12px; font-size: clamp(2rem, 5vw, 3.5rem); line-height: 1.15; } .comparison-instruction { max-width: 650px; margin: 0 auto 28px; color: #4b5563; } .comparison-slider { container-type: inline-size; position: relative; width: min(100%, 900px); aspect-ratio: 16 / 9; margin: 0 auto; overflow: hidden; background: #d1d5db; border-radius: 16px; box-shadow: 0 20px 45px rgba(15, 23, 42, 0.18); isolation: isolate; } .comparison-slider__after, .comparison-slider__before img { position: absolute; inset: 0; height: 100%; object-fit: cover; object-position: center; } .comparison-slider__after { width: 100%; } .comparison-slider__before { position: absolute; inset: 0 auto 0 0; z-index: 2; width: 50%; min-width: 40px; max-width: 100%; height: 100%; overflow: hidden; resize: horizontal; border-right: 3px solid #ffffff; filter: drop-shadow(5px 0 8px rgba(15, 23, 42, 0.25)); } .comparison-slider__before img { width: 100cqw; max-width: none; } .comparison-slider__before::after { content: "↔"; position: absolute; top: 50%; right: 0; width: 42px; height: 42px; display: grid; place-items: center; transform: translate(50%, -50%); color: #111827; background: #ffffff; border-radius: 50%; font-size: 1.25rem; font-weight: 700; box-shadow: 0 4px 14px rgba(15, 23, 42, 0.3); pointer-events: none; } .comparison-slider__label { position: absolute; top: 18px; z-index: 3; padding: 7px 12px; color: #ffffff; background: rgba(15, 23, 42, 0.76); border-radius: 999px; font-size: 0.875rem; font-weight: 700; line-height: 1; letter-spacing: 0.04em; text-transform: uppercase; backdrop-filter: blur(5px); } .comparison-slider__label--before { left: 18px; } .comparison-slider__label--after { right: 18px; } .visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; } @media (max-width: 600px) { .page-content { width: min(100% - 20px, 1100px); padding-block: 40px; } .comparison-slider { border-radius: 10px; } .comparison-slider__label { top: 10px; padding: 6px 9px; font-size: 0.7rem; } .comparison-slider__label--before { left: 10px; } .comparison-slider__label--after { right: 10px; } .comparison-slider__before::after { width: 34px; height: 34px; font-size: 1rem; } }
Several important CSS techniques work together to create the comparison effect.
The .comparison-slider element uses position: relative. This allows both images to be positioned inside the same frame.
position: relative
.comparison-slider { position: relative; overflow: hidden; }
The overflow: hidden declaration prevents either image from appearing outside the rounded comparison container.
overflow: hidden
The before and after images are positioned in the same location:
position: absolute; inset: 0;
This places both images at the top, right, bottom, and left edges of the container.
Because they overlap perfectly, visitors see a direct comparison rather than two separate images.
The top image layer begins at half of the total slider width:
.comparison-slider__before { width: 50%; }
This creates an initial view in which half of the before image and half of the after image are visible.
You can change the starting position:
width: 30%;
A value of 30% reveals more of the after image, while 70% reveals more of the before image.
30%
70%
The main interactive behavior comes from:
resize: horizontal; overflow: hidden;
The resize: horizontal declaration allows the element to be resized from side to side.
resize: horizontal
The overflow: hidden property is required for the native resizing behavior and also clips the part of the before image that falls outside the layer.
A common mistake is setting the before image width to 100%. That causes the image itself to shrink as the overlay becomes narrower, creating distortion instead of a comparison effect.
100%
This tutorial uses:
.comparison-slider { container-type: inline-size; } .comparison-slider__before img { width: 100cqw; }
The 100cqw value makes the before image equal to the width of the complete comparison container, not the width of the resizable before layer.
100cqw
As the layer becomes narrower, the image remains the same size and is simply cropped.
object-fit
Both images use:
object-fit: cover;
This fills the comparison frame while preserving the original image proportions.
Some parts of an image may be cropped if its aspect ratio differs from the slider. For the most accurate result, prepare both images using the same aspect ratio as the container.
Here is a compact version you can copy into a single HTML file:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0" > <title>CSS Before and After Image Slider</title> <style> * { box-sizing: border-box; } body { margin: 0; min-height: 100vh; display: grid; place-items: center; padding: 20px; font-family: Arial, sans-serif; background: #f3f4f6; } img { display: block; } .comparison-slider { container-type: inline-size; position: relative; width: min(100%, 900px); aspect-ratio: 16 / 9; overflow: hidden; border-radius: 16px; box-shadow: 0 18px 40px rgba(0, 0, 0, 0.2); } .comparison-slider__after, .comparison-slider__before img { position: absolute; inset: 0; height: 100%; object-fit: cover; object-position: center; } .comparison-slider__after { width: 100%; } .comparison-slider__before { position: absolute; inset: 0 auto 0 0; width: 50%; min-width: 40px; max-width: 100%; height: 100%; overflow: hidden; resize: horizontal; border-right: 3px solid white; } .comparison-slider__before img { width: 100cqw; max-width: none; } .comparison-slider__before::after { content: "↔"; position: absolute; top: 50%; right: 0; width: 42px; height: 42px; display: grid; place-items: center; transform: translate(50%, -50%); color: #111827; background: white; border-radius: 50%; font-weight: bold; pointer-events: none; } .label { position: absolute; top: 15px; z-index: 3; padding: 7px 11px; color: white; background: rgba(0, 0, 0, 0.7); border-radius: 999px; font-size: 12px; font-weight: bold; text-transform: uppercase; } .label--before { left: 15px; } .label--after { right: 15px; } </style> </head> <body> <figure class="comparison-slider"> <img class="comparison-slider__after" src="after.jpg" alt="Kitchen after renovation" > <span class="label label--after">After</span> <div class="comparison-slider__before"> <img src="before.jpg" alt="Kitchen before renovation" > <span class="label label--before">Before</span> </div> </figure> </body> </html>
Replace before.jpg and after.jpg with your own image paths.
before.jpg
after.jpg
The main comparison container uses:
width: min(100%, 900px); aspect-ratio: 16 / 9;
This means the slider can grow up to 900 pixels wide but becomes smaller when the available screen width is limited.
The aspect-ratio property maintains a consistent shape as the slider changes size.
aspect-ratio
You can use another aspect ratio depending on your images:
aspect-ratio: 4 / 3;
For square images:
aspect-ratio: 1 / 1;
For portrait images:
aspect-ratio: 4 / 5;
Do not assign an unrelated fixed height on smaller devices. A fixed width and fixed height combination can distort the layout or create unnecessary cropping.
The quality of the comparison depends heavily on the images you use.
Both images should have exactly the same width and height.
For example:
before.jpg: 1600 × 900 pixels after.jpg: 1600 × 900 pixels
Using different dimensions can cause alignment problems even when the CSS is correct.
The two images should show the same subject from the same perspective.
For physical transformations, keep the following consistent:
perspective.
For physical transformations, keep the### Align the Important Details
Place the main subject in the same position in both images.
For example, if you are comparing a website redesign, the page header, content areas, and buttons should remain aligned across the screenshots.
Large images can slow down the page.
Before uploading, compress the images and consider using WebP or AVIF when your publishing workflow supports them.
Use descriptive filenames such as:
kitchen-before-renovation.webp kitchen-after-renovation.webp
Avoid generic filenames like:
IMG001.jpg final2.jpg new-image.jpg
The code already includes two labels:
<span class="comparison-slider__label comparison-slider__label--after"> After </span>
And:
<span class="comparison-slider__label comparison-slider__label--before"> Before </span>
You can change the words based on your content:
Keep each label short so it remains readable on mobile devices.
The circular handle is generated with the ::after pseudo-element:
::after
.comparison-slider__before::after { content: "↔"; }
You can use another Unicode character:
content: "⇔";
Or:
content: "◀ ▶";
width: 50px; height: 50px;
background: #111827; color: #ffffff;
border-right: 3px solid #3d5afe;
Remember that the visible circular handle is decorative. The browser’s native resize control is still responsible for resizing the layer.
The slider currently begins with the before layer covering 50% of the container:
width: 50%;
To show more of the before image:
width: 70%;
To show more of the after image:
Keep the value between 0% and 100%.
0%
A CSS-only comparison slider is lightweight, but it is not always the best option for every website.
The visual resize control is provided by the browser. Its appearance and usability may differ between operating systems and browsers.
The resize property is generally more natural to use with a mouse or trackpad. Some touch devices may make the control difficult to discover or operate.
The native resizable element does not provide the same predictable keyboard controls as an HTML range input.
A JavaScript slider can allow visitors to adjust the comparison using arrow keys and can provide better assistive-technology support.
You can create a decorative divider and circle, but the actual resize area The Handle Is Not Fully Customizable
is still controlled by the browser.
JavaScript is generally needed for features such as:
Use the pure CSS method when simplicity and low code weight are the main priorities.
Use JavaScript when the comparison experience must be consistent, accessible, and fully customizable.
For a more advanced implementation, read:
How to Create a Before After Image Slider with CSS and JavaScript
This usually happens when the two images have different dimensions, framing, or aspect ratios.
Solution: Resize and crop both images to the same width and height before adding them to the slider.
Before: 1200 × 675 After: 1200 × 675
CSS cannot fully correct two images that were captured from noticeably different angles.
This happens when the before image uses:
width: 100%;
The percentage is calculated from the resizable overlay, so the image becomes smaller as the overlay becomes narrower.
Solution: Make the image width equal to the complete comparison container:
The resize property normally requires an overflow value other than visible.
visible
Use:
Also test the component in your target browsers because native resize controls may look different.
This usually happens when both width and height are forced without preserving the image proportions.
Also make sure the slider’s aspect-ratio matches the original image dimensions.
A fixed width may extend beyond smaller screens.
Avoid:
width: 900px;
width: min(100%, 900px);
Also make sure the page has appropriate horizontal padding.
The handle extends beyond the edge of the before layer:
transform: translate(50%, -50%);
If it is clipped, check whether another parent element has overflow: hidden.
The main comparison container should hide image overflow, but additional wrappers should not cut off the component unexpectedly.
The pure CSS resize technique may not provide an ideal touch experience.
Possible solutions include:
The label is placed inside the resizable before layer. When the layer becomes extremely narrow, the label may be clipped.
You can hide it at smaller widths using a container query, or move the labels outside the slider.
A simple alternative is to keep the slider from becoming too narrow:
min-width: 80px;
You can add multiple sliders by repeating the same HTML structure:
<figure class="comparison-slider"> <!-- First comparison --> </figure> <figure class="comparison-slider"> <!-- Second comparison --> </figure>
Because the CSS uses classes rather than IDs, the same styles will apply to every comparison.
Add spacing between the sliders:
.comparison-slider + .comparison-slider { margin-top: 40px; }
Each comparison should have its own descriptive image alternative text and caption.
You can add the pure CSS slider manually to WordPress, although the available method depends on your theme and editor.
In the WordPress block editor:
A WordPress image URL may look similar to this:
<img src="https://example.com/wp-content/uploads/2026/07/before.webp" alt="Office before renovation" >
When using Elementor:
Manual CSS is suitable for a simple comparison. A plugin is usually more convenient when you need:
The WP Before After Image Slider plugin provides a more manageable option for WordPress users who do not want to maintain custom code.
Image comparisons are visual, so the information should not depend entirely on dragging the slider.
Avoid vague alternative text such as:
alt="Before image"
Use text that explains the visible subject:
alt="Living room before the flooring and lighting renovation"
alt="Living room after new flooring and lighting were installed"
Use a caption to explain what changed:
<figcaption> The office before and after new flooring, lighting, and wall panels were installed. </figcaption>
You can display the caption visually or hide it from sighted users while keeping it available to assistive technology.
The words “Before” and “After” do not explain the actual difference. Add supporting text near the slider when the transformation is important.
For important information, consider displaying both images separately below the comparison or adding links that open the complete images.
A properly implemented range input can provide better keyboard interaction. Users can adjust it using arrow keys, and its value can be described using accessible attributes.
A comparison slider can support a useful page experience when it genuinely helps visitors understand a transformation.
The slider itself is not a guaranteed ranking factor. Its SEO value depends on the quality of the surrounding page.
Use the following practices:
Do not add multiple large sliders purely to target keywords. Every comparison should serve a clear purpose.
Before-and-after sliders load at least two images, so they can increase page weight.
WebP and AVIF often produce smaller file sizes than uncompressed PNG or high-quality JPEG files.
Do not upload a 5000-pixel-wide image when the slider is displayed at a maximum of 900 pixels.
A larger source may be helpful for high-density screens, but the image should still be appropriately optimized.
When you know the original dimensions, add them to the HTML:
<img src="after.webp" width="1600" height="900" alt="Office after renovation" >
This helps the browser reserve space while the image loads.
For comparisons that appear farther down the page, use:
loading="lazy"
Example:
<img src="before.webp" alt="Building before restoration" loading="lazy" >
Do not automatically lazy-load a large comparison image that appears at the top of the page, because delaying it may hurt the initial visual experience.
For a clear and professional result:
A before-and-after image comparison slider helps visitors understand visual changes without switching between separate images. For a simple project, you can create one using only HTML and CSS by stacking the images and making the top layer horizontally resizable.
The pure CSS method is lightweight, straightforward, and useful for demonstrations. However, it also depends on the browser’s native resize behavior and offers limited keyboard and mobile control.
Use it when you need a basic no-JavaScript comparison. For a production WordPress website, advanced touch interaction, vertical comparison, or a fully customized handle, a JavaScript implementation or dedicated WordPress plugin will provide a more consistent experience.
Most importantly, prepare two well-aligned images, optimize their file sizes, add useful alternative text, and test the comparison on the devices your visitors use.
Yes. You can stack two images in the same container and apply resize: horizontal to the top image layer. Resizing the layer reveals the image underneath. This approach does not require JavaScript, although it provides fewer interaction and accessibility options than a JavaScript slider.
The after image fills the main container. The before image is placed above it inside a resizable layer. The layer uses overflow: hidden to crop the before image as its width changes, allowing the after image to appear underneath.
The images probably have different dimensions, aspect ratios, camera angles, or subject positions. Crop both files to the same width and height, then confirm that the important visual details occupy matching locations.
Give the main container a fluid width such as width: min(100%, 900px) and use an aspect-ratio. Set both images to fill the container with width: 100%, height: 100%, and object-fit: cover.
width: min(100%, 900px)
width: 100%
height: 100%
object-fit: cover
The layout can be responsive, but the native CSS resize interaction may not be equally convenient across all touch devices. For a consistent mobile experience, consider using a JavaScript range input or a dedicated comparison-slider plugin.
Yes. Use reusable classes and repeat the HTML structure for every comparison. Avoid duplicate IDs, optimize all images, and add enough space between sliders to keep the page easy to use.
The CSS resize property supports vertical resizing, but creating a polished vertical image-reveal experience can be difficult. JavaScript is usually a better choice when you need a traditional vertical draggable divider.
The top image may be using a percentage width based on the resizable layer. It should remain equal to the full comparison-container width and be clipped instead of scaled. Container query units such as 100cqw can solve this problem.
A pure CSS resize slider has accessibility limitations because the native resize action may not provide predictable keyboard controls. Use descriptive alt text, captions, supporting text, and a non-interactive alternative. Consider a JavaScript range input for better keyboard operation.
You can paste the HTML into a Custom HTML block and add the CSS through your theme or WordPress Customizer. For easier setup, reusable sliders, touch controls, and editor integration, use a dedicated WordPress before-and-after image slider plugin.
This page was last edited on 15 July 2026, at 5:49 pm
Your email address will not be published. Required fields are marked *
Comment *
Name *
Email *
Website
Save my name, email, and website in this browser for the next time I comment.
How many people work in your company?Less than 1010-5050-250250+
By proceeding, you agree to our Privacy Policy