Add Image Sliders to Gravity Forms with JetSloth Image Choices
Want to make your Gravity Forms stand out? In this quick tutorial, we’ll show you how to combine JetSloth’s Image Choices with Swiper.js to turn static form options into beautiful, swipeable image sliders. Follow along to add smooth navigation, responsive layouts, and optional pagination to your visual form fields.
Turn Boring Forms into Visual Experiences: Add Image Sliders to Gravity Forms
If you use Gravity Forms to collect leads or product preferences on your WordPress site, you already know how powerful it is. But let’s face it — most forms look… pretty plain.
That’s where JetSloth’s Image Choices add-on comes in. It transforms standard radio buttons and checkboxes into beautiful, clickable image-based options, letting users see what they’re choosing — not just read about it.
In this tutorial, we’ll take Image Choices one step further by enhancing it with a Swiper.js slider layout, perfect for showing large sets of image options in a neat, scrollable format.
What you’ll need to follow along
A copy of Gravity Forms Image Choices
Easily add images to choices for radio buttons or checkbox fields within Gravity Forms. Supports Survey, Poll, Quiz, Product and Options fields.
Gravity Wiz Code Chest
Gravity Wiz Code Chest is a free Gravity Forms add-on that lets you inject custom CSS and Javascript to individual forms.
Adding Swiper to JetSloth’s Image Choices
Using a small JavaScript snippet, we can detect any Image Choices field with a .swiper-choices class and automatically wrap its choices in a Swiper slider.
You can even make the setup smarter:
- Only initialize Swiper when the class
swiper-choicesis present - Support multiple sliders per page
- Conditionally show pagination using the
show-pagnationclass
This flexibility means you can drop the same script into any form — product configurators, quizzes, or surveys — and instantly get a polished, swipeable layout.
Add the JavaScript Snippet
Copy and paste the below JavaScript snippet into your theme via a plugin, or directly into your theme. We suggest something like Code Chest by Gravity Wizz.
(function () {
const LOAD_SWIPER = true; // Set to false if your theme already imports and uses swiper.js
function getImageChoicesColumns(el) {
const DEFAULT_COLS = 3;
if (!el || !el.classList) return { default: DEFAULT_COLS, md: DEFAULT_COLS, sm: DEFAULT_COLS };
const classes = Array.from(el.classList);
const result = { default: null, md: null, sm: null };
const extractNumber = (cls, prefix) => {
const match = cls.match(new RegExp(`^${prefix}--(\\d+|auto)$`));
return match ? match[1] : null;
};
classes.forEach(cls => {
if (cls.startsWith('ic-cols--')) {
const val = extractNumber(cls, 'ic-cols');
result.default = val !== 'auto' ? parseInt(val, 10) : null;
} else if (cls.startsWith('ic-cols-md--')) {
const val = extractNumber(cls, 'ic-cols-md');
result.md = val !== 'auto' ? parseInt(val, 10) : null;
} else if (cls.startsWith('ic-cols-sm--')) {
const val = extractNumber(cls, 'ic-cols-sm');
result.sm = val !== 'auto' ? parseInt(val, 10) : null;
}
});
const fallback = result.default ?? DEFAULT_COLS;
return {
default: fallback,
md: result.md ?? fallback,
sm: result.sm ?? fallback
};
}
function loadScript(url, callback) {
const script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
script.onload = callback;
document.head.appendChild(script);
}
function loadStylesheet(url) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = url;
document.head.appendChild(link);
}
function initImageChoicesSwiper() {
// Find all .swiper-choices instances
const fields = document.querySelectorAll(".swiper-choices");
if (!fields.length) return;
fields.forEach((field, index) => {
const choicesContainer = field.querySelector(".gfield_radio, .gfield_checkbox");
if (!choicesContainer) return;
const choices = choicesContainer.querySelectorAll(".image-choices-choice");
if (!choices.length) return;
// Check if this field has .show_pagnation class
const showPagination = field.classList.contains("show-pagnation");
// Unique class per instance
const swiperId = `swiper-${index}`;
// Create Swiper container
const swiperContainer = document.createElement("div");
swiperContainer.classList.add("swiper", "swiper-container", swiperId);
// Create Swiper wrapper
const swiperWrapper = document.createElement("div");
swiperWrapper.classList.add("swiper-wrapper");
// Convert each choice into a Swiper slide
choices.forEach(choice => {
const slide = document.createElement("div");
slide.classList.add("swiper-slide");
slide.appendChild(choice);
swiperWrapper.appendChild(slide);
});
// Navigation buttons
const prevButton = document.createElement("div");
prevButton.classList.add("swiper-button-prev");
const nextButton = document.createElement("div");
nextButton.classList.add("swiper-button-next");
// Append elements
swiperContainer.appendChild(swiperWrapper);
swiperContainer.appendChild(prevButton);
swiperContainer.appendChild(nextButton);
// Pagination (conditionally create)
if (showPagination) {
const pagination = document.createElement("div");
pagination.classList.add("swiper-pagination");
swiperContainer.appendChild(pagination);
}
// Replace old container content
choicesContainer.innerHTML = '';
choicesContainer.appendChild(swiperContainer);
const cols = getImageChoicesColumns(field);
// Initialize Swiper instance
new Swiper(`.${swiperId}`, {
slidesPerView: cols.sm,
slidesPerGroup: cols.sm,
spaceBetween: 10,
breakpoints: {
640: {
slidesPerView: cols.md,
slidesPerGroup: cols.md,
},
1080: {
slidesPerView: cols.default,
slidesPerGroup: cols.md,
}
},
breakpointsBase: 'window',
resizeObserver: false,
navigation: {
nextEl: `.${swiperId} .swiper-button-next`,
prevEl: `.${swiperId} .swiper-button-prev`,
},
allowTouchMove: true,
preventClicks: false,
preventClicksPropagation: false,
slideToClickedSlide: false,
noSwipingSelector: 'input, select, textarea, a',
...(showPagination && {
pagination: {
el: `.${swiperId} .swiper-pagination`,
clickable: true,
}
})
});
});
}
if (LOAD_SWIPER) {
loadStylesheet("https://cdn.jsdelivr.net/npm/swiper/swiper-bundle.min.css");
loadScript("https://cdn.jsdelivr.net/npm/swiper/swiper-bundle.min.js", initImageChoicesSwiper);
} else {
gform.addAction('gfic_setup', initImageChoicesSwiper);
}
})();
Snippet options
We’ve included some smart options in the above JS snippet.
| Option/Setting | Description |
|---|---|
LOAD_SWIPER = true | If your website theme or plugin already imports and uses Swiper.js on page, turn this to false so you're not loading in an instance of swiper.js more than once. |
breakpointsBase: 'window' | By default swiper.js will resize the swiper based on the 'container' size. You can also set it to 'window' which will resize when the browser window does. We suggest setting to the 'window' option. |
swiper-choices | Add this class name to active the swiper.js on your form or forms. |
show-pagination | Add this class name to also show swiper's pagination in your swipper. |
resizeObserver | We suggest setting this to true. |
Add the CSS
The CSS below will help set up and style the swiper slides.
/* =========================================================
Global Swiper + Image Choices Resets
========================================================= */
.image-choices-field[class*="ic-cols--"] .swiper-slide .image-choices-choice {
width: 100%;
}
.swiper {
width: 100%;
--swiper-theme-color: var(--ic-feature-color);
--swiper-navigation-size: 20px;
--swiper-navigation-sides-offset: 10px;
--swiper-navigation-top-offset: calc(100% - 109px);
}
.image-choices-field[class*="ic-theme--"] .image-choices-choice-text {
text-align: initial !important;
}
.swiper,
.swiper-container {
padding-top: 5px;
padding-bottom: 40px;
}
/* =========================================================
Swiper Navigation Arrows - Circle Shape
========================================================= */
.swiper-button-next,
.swiper-button-prev {
background: #fff;
width: 40px;
height: 40px;
border-radius: 100%;
overflow: hidden;
box-shadow:
rgba(0, 0, 0, 0.16) 0px 10px 36px 0px,
rgba(0, 0, 0, 0.06) 0px 0px 0px 1px;
}
.swiper-button-next::after,
.swiper-button-prev::after {
font-weight: bold;
}
/* Hide buttons when at ends of swiper */
.swiper-button-next.swiper-button-disabled,
.swiper-button-prev.swiper-button-disabled {
opacity: 0;
}
/* =========================================================
Swiper Pagination
========================================================= */
.swiper-pagination-bullet.swiper-pagination-bullet-active {
--swiper-pagination-color: var(--ic-feature-color);
}
/* =========================================================
Cover Tile Shadow Fix Used only if theme = Cover Tile. Prevents shadow cutoff.
========================================================= */
.ic-theme--cover-tile .image-choices-choice-image-wrap {
box-shadow:
rgba(50, 50, 93, 0.25) 0px 2px 5px -1px,
rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
}
/* =========================================================
Optional Hover Effect
========================================================= */
.image-choices-choice .image-choices-choice-image-wrap {
transition: transform 0.2s ease-in-out;
transform: translateY(0);
}
.image-choices-choice-hover .image-choices-choice-image-wrap {
transform: translateY(-5px);
}
CSS and JS added to Code Chest
Column Control
We’ve connected the above JavaScript snippet to control swiper.js column widths based on our Image Choices settings options. Use the Image Choices form settings to control how many columns you want your images to show on desktop, tablet and mobile.
Required class names
Make sure you add the swiper-choices class name to your appearance field in form settings. You can also add the show-pagnation if you wish to also show the clickable pagination navigation below the swiper.
Taking it further
Let’s take things a step further. Beyond the basic setup, you can unlock even more customization by tapping into the available JavaScript options and layering in a few clever CSS enhancements. With just a bit of tweaking, you can transform your Gravity Forms Image Choices into a sleek, swipeable experience — complete with responsive layouts, hover effects, and subtle animations that feel right at home in modern web design.
Demo 2 CSS
CSS – Pagination + vertically centred navigation arrows + Lightbox
This example makes the left/right navigation vertically centred and makes the buttons square instead of circular. It also enables the built-in Image Choices lightbox feature. It’s using the Cover Tile theme.
/* =========================================================
Demo 2 - Global Swiper + Image Choices Resets
========================================================= */
.image-choices-field[class*="ic-cols--"] .swiper-slide .image-choices-choice {
width: 100%;
}
.swiper {
width: 100%;
--swiper-theme-color: var(--ic-feature-color);
--swiper-navigation-size: 20px;
--swiper-navigation-sides-offset: 10px;
--swiper-navigation-top-offset: calc(50% - 10px);
}
.image-choices-field[class*="ic-theme--"] .image-choices-choice-text {
text-align: initial !important;
}
.swiper,
.swiper-container {
padding-top: 5px;
padding-bottom: 40px;
}
/* =========================================================
Swiper Navigation Arrows
========================================================= */
.swiper-button-next,
.swiper-button-prev {
background: #fff;
width: 40px;
height: 40px;
border-radius: 5px;
overflow: hidden;
box-shadow:
rgba(0, 0, 0, 0.16) 0px 10px 36px 0px,
rgba(0, 0, 0, 0.06) 0px 0px 0px 1px;
}
.swiper-button-next::after,
.swiper-button-prev::after {
font-weight: bold;
}
/* Hide buttons when at ends of swiper */
.swiper-button-next.swiper-button-disabled,
.swiper-button-prev.swiper-button-disabled {
opacity: 0;
}
/* =========================================================
Swiper Pagination
========================================================= */
.swiper-pagination-bullet.swiper-pagination-bullet-active {
--swiper-pagination-color: var(--ic-feature-color);
}
/* =========================================================
Cover Tile Shadow Fix
=========================================================
Used only if theme = Cover Tile. Prevents shadow cutoff.
========================================================= */
.ic-theme--cover-tile .image-choices-choice-image-wrap {
box-shadow:
rgba(50, 50, 93, 0.25) 0px 2px 5px -1px,
rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
}
.ic-theme--cover-tile .image-choices-choice .gform-field-label:after {
background: linear-gradient(198deg, transparent 63.8%, rgba(0, 0, 0, .51) 78.61%);
}
/* =========================================================
Optional Hover Effect - SLight blur
========================================================= */
.image-choices-choice .image-choices-choice-image-wrap{
filter:blur(0px);
transition: all 0.2s ease-in-out;
overflow:hidden;
}
.image-choices-choice.image-choices-choice-hover .image-choices-choice-image-wrap{
filter:blur(2px);
}
Demo 3 CSS
CSS – Glass Theme
This example (badly) draws inspiration from the new iOS glass theme. It’s using the Polaroid theme.
In this example, we’d consider a more advanced demo, but still totally doable. Just note, we’re showing only 1 Image Choice at a time, and the glass effect needs a background image to really get that glass effect to work, so it might not be suitable for everyone.
/* =========================================================
Demo 3 - Global Swiper + Image Choices Resets
========================================================= */
.swiper-choices {
--border-radius-jetsloth: 20px;
}
.image-choices-field[class*="ic-cols--"] .swiper-slide .image-choices-choice {
width: 100%;
}
.swiper {
width: 100%;
--swiper-theme-color: white;
--swiper-navigation-size: 20px;
--swiper-navigation-sides-offset: 10px;
--swiper-navigation-top-offset: 70%;
}
.swiper,
.swiper-container {
padding-top: 5px;
padding-bottom: 40px;
}
/* =========================================================
Swiper Navigation Arrows
========================================================= */
.swiper-button-next,
.swiper-rtl .swiper-button-prev {
right: 20px;
left: unset;
}
.swiper-button-prev,
.swiper-rtl .swiper-button-next {
left: unset;
right: 70px;
}
.swiper-button-next,
.swiper-button-prev {
background: #ffffff47;
width: 40px;
height: 40px;
border-radius: var(--border-radius-jetsloth);
overflow: hidden;
}
.swiper-button-next::after,
.swiper-button-prev::after {
font-weight: bold;
}
/* Hide buttons when at ends of swiper */
.swiper-button-next.swiper-button-disabled,
.swiper-button-prev.swiper-button-disabled {
opacity: 0;
}
/* =========================================================
Swiper Pagination
========================================================= */
.swiper-pagination-bullet.swiper-pagination-bullet-active {
--swiper-pagination-color: white;
}
.swiper-pagination.swiper-pagination-clickable.swiper-pagination-bullets.swiper-pagination-horizontal {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(15px);
border-radius: var(--border-radius-jetsloth);
border: 1px solid rgba(255, 255, 255, 0.3);
overflow: hidden;
width: auto;
padding: 15px 10px;
position: relative;
display: inline-flex;
justify-content: center;
align-items: center;
top: unset;
left: unset;
bottom: unset;
margin-top: 10px;
}
.swiper-pagination.swiper-pagination-clickable.swiper-pagination-bullets.swiper-pagination-horizontal::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.8),
transparent
);
}
.swiper-pagination.swiper-pagination-clickable.swiper-pagination-bullets.swiper-pagination-horizontal::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 1px;
height: 100%;
background: linear-gradient(
180deg,
rgba(255, 255, 255, 0.8),
transparent,
rgba(255, 255, 255, 0.3)
);
}
/* =========================================================
Glass Styles
========================================================= */
.image-choices-choice-image-wrap {
border-radius: var(--border-radius-jetsloth);
mask-image: linear-gradient(to bottom, transparent, black 0%, black 75%, transparent);
mask-repeat: no-repeat;
mask-size: 100% 100%;
}
.image-choices-choice .gform-field-label {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(25px);
-webkit-backdrop-filter: blur(25px);
border-radius: var(--border-radius-jetsloth);
border: 1px solid rgba(255, 255, 255, 0.3);
position: relative;
overflow: hidden;
}
/* =========================================================
Limit the Swiper Width (Single Image Choice View)
========================================================= */
.swiper-choices {
max-width: 350px;
width: 100%;
margin: 0 auto;
}
/* =========================================================
Text Settings
========================================================= */
.image-choices-field {
--ic-text-font: system-ui;
--ic-text-weight: 600;
--ic-text-color: white;
--ic-text-size: 19px;
}
legend.gfield_label.gform-field-label {
color: white;
} Beyond Image Choices: Making Your Forms Beautiful
Whether you’re a designer, marketer, or developer, improving how your forms look can dramatically impact how they perform.
Using JetSloth’s Image Choices with a Swiper slider adds a touch of modern UX — giving your users a smoother, more intuitive way to engage with your forms.Ready to give your forms a visual upgrade? Get started with JetSloth’s Image Choices today and start turning your Gravity Forms into scrollable galleries of options that convert.