Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/rushmark/gb-image-comparison-slider/archive/refs/heads/main.zipA before/after image comparison block for GenerateBlocks 2.x. Two images sit on top of each other with a slider between them, so visitors can drag to compare.
Everything you see is a real GenerateBlocks block: the images, the handle, the grip and the labels. You style them in GB's Styles panel or with GB Pro Global Styles, the same way you style everything else. The plugin adds the behaviour; GenerateBlocks does the looks.
- Requires WordPress 6.6+, PHP 7.4+ and GenerateBlocks 2.0+. GenerateBlocks Pro is optional (it's used for the starting layouts' styles).
- Block name:
ccws/image-compare, in the GenerateBlocks category.
Using it
- Add an Image Compare block and choose a starting layout:
- Classic: a line with a round grip, and labels in the top corners.
- Minimal line: just the dividing line.
- Vertical: before on top, after below.
- Follow the mouse: the line follows the mouse, and labels appear on hover.
- Choose the before and after images. Use two images with the same shape (aspect ratio), and give each one alt text.
- Adjust the settings in the block sidebar. Restyle any part by selecting it.
Settings
| Setting | Options | Default |
|---|---|---|
| Starting position | 0–100% of the before image showing | 50 |
| Orientation | Side by side, or stacked | Side by side |
| How visitors move it | Drag the handle (a click on the images also jumps there) · Click or drag anywhere · Follow the mouse (touch screens: click or drag) | Click or drag anywhere |
| Labels | Always shown · Shown on hover or focus (always on touch screens) · Hidden | Always shown |
| Hint that it moves | Nudges the handle once when the block first comes into view | Off |
| Return to start | Glides back to the starting position when the mouse leaves | Off |
| Keyboard | Arrow-key step (1–25%), Page Up/Down step (1–50%) | 5%, 20% |
| Screen readers | Slider name, and names for the before and after images | "Before and after comparison", "Before", "After" |
Plus the usual HTML anchor, additional CSS class, and margin.
Parts
Each part is marked with a data-ccws-compare-part attribute in the GB block's HTML attributes. You can see and change it under Image Compare part when a block inside the Image Compare is selected. You can rearrange, restyle or replace parts freely.
| Part | Block | What it does |
|---|---|---|
frame |
Element | Holds everything; style its size, corners and border. Optional: without it the block itself is the frame. |
before |
Image | Sets the size of the comparison. |
after |
Image (or an Element holding one) | Laid exactly over the before image and cut at the slider position. |
handle |
Element (a <div>) |
The slider: dragging it and the keyboard move it, and screen readers announce it. Without one, the whole block becomes the slider, and screen readers then don't hear the images' alt text, so keep a handle. |
label-before, label-after |
Text | Captions over the images. Clicks pass through them. |
Styling
-
The position is the CSS variable
--ccws-compare-pos(e.g.50%) on the block. Use it in your own styles if you like. -
Style keyboard focus on the handle with the nested selector
&:focus-visible. -
The starting layouts use these GB Pro Global Styles, created once when an admin page loads (only with GB Pro). They're yours to edit or delete, and the plugin never overwrites them:
ccws-image-compare__frame,__handle,__handle--vertical,__grip,__grip--vertical,__label,__label--before,__label--after,__label--after-vertical -
Without GB Pro the layouts still work, just unstyled: style the parts with GB's Styles panel instead.
-
Switching Orientation also swaps the
--verticalclasses on those parts, so the handle and labels turn with it.
Accessibility
- The handle follows the WAI-ARIA slider pattern. The server adds
role="slider",aria-valuenow/min/max,aria-valuetext(e.g. "40% Before, 60% After"),aria-orientationand a name before any JavaScript runs. None of it is saved in your content, so kses can't strip it. - Keys: Arrow keys move by the small step, Page Up/Down by the large step, Home/End go to either end. Side by side, the value is the share of the before image: Right and Up increase it (Left and Right are mirrored in right-to-left languages). Stacked, the value is the share of the after image, so Up and Page Up increase it, as assistive tech expects, and every key moves the line the way it points.
- Clicking or dragging focuses the handle, so you can carry on with the keyboard.
- Every mode works with a single click or tap as well as a drag (WCAG 2.5.7). Pinch-zoom keeps working on the images.
- The intro hint is under 2 seconds and never plays for visitors who prefer reduced motion. Return-to-start is instant for them too.
- In the default styles, the handle and grip are white with a dark edge, so they stay visible on light and dark photos. Labels are white on a dark panel, and they work in forced-colours (high contrast) mode.
Performance
- Pages without the block load nothing from this plugin.
- Pages with it load one small script (about 1.8 KB gzipped) and one stylesheet (about 0.7 KB gzipped). On classic themes like GeneratePress the stylesheet goes in
<head>. - The starting position is rendered by the server, so there's no flash or layout shift. Pointer moves are batched once per frame, and the cut is a CSS
clip-path, so dragging never triggers a layout.
Known limitations
- Don't link the images (GB's image link option): the overlay needs the
<img>itself. - The handle should be an Element (
<div>), not a button or link. A<button>can't take the slider role. - On touch screens, a stacked (vertical) comparison moves by tapping the images or dragging the handle. Swiping over the images scrolls the page as normal.
- On classic themes (GeneratePress), the stylesheet goes in
<head>when the block is in the page's own content. For a block in a synced pattern, a GP Element, a widget or an archive, the stylesheet arrives with the block, so the images may show side by side for a moment while the page loads. - The grip in the editor shows GB's "add block" button inside it. That's only in the editor.
Development
npm install
npm run build # or: npm start (watch)
npm run lint # JS + SCSS
npm run playground # local WordPress with GenerateBlocks + GeneratePress on http://127.0.0.1:9400
npm run test:e2e # Playwright tests (starts Playground if it isn't running)
npm run zip # dist/ccws-image-compare.zip
The Playground site (playground/blueprint.json) installs free GenerateBlocks and GeneratePress, adds two sample images, and creates an Image Compare demo page. The page is saved through kses (as an Author's would be), so the editor-validity test catches stripped attributes. GB Pro can't be installed in Playground, so the test site prints the default Global Styles itself (see CCWS_IMAGE_COMPARE_PRINT_DEFAULT_STYLES in playground/setup.php; never define it on a real site).
To use an already-installed Chromium for the tests, set PW_CHROMIUM_PATH.
PHP coding standards: phpcs with phpcs.xml.dist (WordPress-Extra, WordPress-Docs, PHPCompatibilityWP). CI runs everything in .github/workflows/ci.yml.
Release
Use npm run build && npm run zip, then attach dist/ccws-image-compare.zip to a GitHub release. Don't use GitHub's "Download ZIP": it has no build/ folder and the wrong folder name.
Licence
GPL-2.0-or-later.