Member
Account Settings
Share AgencyGenius
Know someone who might benefit from AgencyGenius? We'd love it if you shared our platform with your networking group!

Documentation
Step 1: Add HTML, Css & JavaScript
<!-- Image Cycling Widget - Start This is a self-contained widget that cycles through images automatically when in viewport. The widget has smooth transitions between images. --> <div id="unique-image-cycler-widget"> <div class="image-cycle-collection"> <div class="image-cycle-collection__before"></div> <div class="image-cycle-collection__list" data-image-cycle> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/macos-sonoma-wallpapers-5120x2160-v0-j9vwvbq8h5wb1.jpg" loading="lazy" alt="macOS Sonoma Wallpaper"> </div> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/macOS-Mojave-Day-wallpaper.jpg" loading="lazy" alt="macOS Mojave Day Wallpaper"> </div> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/da68i50-00fbde21-b0fa-49cc-a0ca-cdebca7b0730.jpg" loading="lazy" alt="macOS Wallpaper"> </div> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/macos-big-sur-ysfrml6k0il45zd8.jpg" loading="lazy" alt="macOS Big Sur Wallpaper"> </div> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/mountain-scenery-macos-4k-wallpaper-uhdpaper.com-106-0-h.jpg" loading="lazy" alt="Mountain Scenery macOS Wallpaper"> </div> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/mountain-scenery-macos-4k-wallpaper-uhdpaper.com-108-0-h.jpg" loading="lazy" alt="Mountain Scenery macOS Wallpaper 2"> </div> </div> </div> </div> <!-- Image Cycling Widget - End -->
/* Main container styling */ #unique-image-cycler-widget { width: 100%; max-width: 100%; height: 100%; } /* Image cycle collection container */ #unique-image-cycler-widget .image-cycle-collection { width: 100%; height: 100%; position: relative; } /* Creates aspect ratio space holder */ #unique-image-cycler-widget .image-cycle-collection__before { padding-top: 50%; /* Default aspect ratio, container can override */ } /* Image list container */ #unique-image-cycler-widget .image-cycle-collection__list { z-index: 0; border-radius: 10px; width: 100%; height: 100%; position: absolute; top: 0; left: 0; overflow: hidden; } /* Image item positioning */ #unique-image-cycler-widget .image-cycle-collection__img { width: 100%; height: 100%; position: absolute; top: 0; left: 0; object-fit: cover; } /* Image inside container */ #unique-image-cycler-widget .image-cycle-collection__img img { width: 100%; height: 100%; object-fit: cover; } /* Active image state */ #unique-image-cycler-widget [data-image-cycle-item="active"] { transition: opacity 0.4s ease 0s, visibility 0s ease 0s; opacity: 1; visibility: visible; z-index: 3; } /* Previous image state (fading out) */ #unique-image-cycler-widget [data-image-cycle-item="previous"] { transition: opacity 0.4s ease 0.4s, visibility 0s ease 0.4s; opacity: 0; visibility: visible; z-index: 2; } /* Inactive image state */ #unique-image-cycler-widget [data-image-cycle-item="not-active"] { opacity: 0; visibility: hidden; z-index: 1; } /* Responsive adjustments for mobile */ @media screen and (max-width: 767px) { #unique-image-cycler-widget .image-cycle-collection__list { border-radius: 10px; /* Maintain 10px radius on mobile */ } }
// Self-executing function to avoid global scope pollution (function() { // Initialize when DOM is fully loaded document.addEventListener('DOMContentLoaded', function() { initImageCycle(); }); /** * Initialize image cycling functionality * Finds all image cycle containers and sets up automatic cycling */ function initImageCycle() { // Find all image cycle containers within our widget const widgetContainer = document.getElementById('unique-image-cycler-widget'); const cycleElements = widgetContainer.querySelectorAll("[data-image-cycle]"); cycleElements.forEach(cycleElement => { // Get all items in this cycle group const items = cycleElement.querySelectorAll("[data-image-cycle-item]"); // Skip if there aren't enough items to cycle if (items.length < 2) return; let currentIndex = 0; let intervalId; const duration = 2000; // Time between transitions in milliseconds const isTwoItems = items.length === 2; // Initialize: First item active, others not-active items.forEach((item, i) => { item.setAttribute("data-image-cycle-item", i === 0 ? "active" : "not-active"); }); /** * Cycle to the next image in the collection */ function cycleImages() { const prevIndex = currentIndex; currentIndex = (currentIndex + 1) % items.length; if (isTwoItems) { // Special case: Only two images - toggle between "previous" and "active" items[prevIndex].setAttribute("data-image-cycle-item", "previous"); } else { // Normal case: Three or more images items[prevIndex].setAttribute("data-image-cycle-item", "previous"); // Set to not-active after transition completes setTimeout(() => { items[prevIndex].setAttribute("data-image-cycle-item", "not-active"); }, duration); } // Set new active item items[currentIndex].setAttribute("data-image-cycle-item", "active"); } // Use IntersectionObserver to start/stop cycling when in/out of viewport const observer = new IntersectionObserver(([entry]) => { if (entry.isIntersecting && !intervalId) { // Start cycling when element is visible intervalId = setInterval(cycleImages, duration); } else if (!entry.isIntersecting && intervalId) { // Stop cycling when element is not visible clearInterval(intervalId); intervalId = null; } }, { threshold: 0 }); // Start observing the element observer.observe(cycleElement); }); } })();
<div id="snippet-zl1ztacc"> <!-- HTML SECTION START --> <!-- Image Cycling Widget - Start This is a self-contained widget that cycles through images automatically when in viewport. The widget has smooth transitions between images. --> <div id="unique-image-cycler-widget"> <div class="image-cycle-collection"> <div class="image-cycle-collection__before"></div> <div class="image-cycle-collection__list" data-image-cycle> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/macos-sonoma-wallpapers-5120x2160-v0-j9vwvbq8h5wb1.jpg" loading="lazy" alt="macOS Sonoma Wallpaper"> </div> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/macOS-Mojave-Day-wallpaper.jpg" loading="lazy" alt="macOS Mojave Day Wallpaper"> </div> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/da68i50-00fbde21-b0fa-49cc-a0ca-cdebca7b0730.jpg" loading="lazy" alt="macOS Wallpaper"> </div> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/macos-big-sur-ysfrml6k0il45zd8.jpg" loading="lazy" alt="macOS Big Sur Wallpaper"> </div> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/mountain-scenery-macos-4k-wallpaper-uhdpaper.com-106-0-h.jpg" loading="lazy" alt="Mountain Scenery macOS Wallpaper"> </div> <div class="image-cycle-collection__img" data-image-cycle-item> <img src="https://irp.cdn-website.com/a778beb9/dms3rep/multi/mountain-scenery-macos-4k-wallpaper-uhdpaper.com-108-0-h.jpg" loading="lazy" alt="Mountain Scenery macOS Wallpaper 2"> </div> </div> </div> </div> <!-- Image Cycling Widget - End --> <!-- HTML SECTION END --> <!-- CSS SECTION START --> <style> /* Main container styling */ #unique-image-cycler-widget { width: 100%; max-width: 100%; height: 100%; } /* Image cycle collection container */ #unique-image-cycler-widget .image-cycle-collection { width: 100%; height: 100%; position: relative; } /* Creates aspect ratio space holder */ #unique-image-cycler-widget .image-cycle-collection__before { padding-top: 50%; /* Default aspect ratio, container can override */ } /* Image list container */ #unique-image-cycler-widget .image-cycle-collection__list { z-index: 0; border-radius: 10px; width: 100%; height: 100%; position: absolute; top: 0; left: 0; overflow: hidden; } /* Image item positioning */ #unique-image-cycler-widget .image-cycle-collection__img { width: 100%; height: 100%; position: absolute; top: 0; left: 0; object-fit: cover; } /* Image inside container */ #unique-image-cycler-widget .image-cycle-collection__img img { width: 100%; height: 100%; object-fit: cover; } /* Active image state */ #unique-image-cycler-widget [data-image-cycle-item="active"] { transition: opacity 0.4s ease 0s, visibility 0s ease 0s; opacity: 1; visibility: visible; z-index: 3; } /* Previous image state (fading out) */ #unique-image-cycler-widget [data-image-cycle-item="previous"] { transition: opacity 0.4s ease 0.4s, visibility 0s ease 0.4s; opacity: 0; visibility: visible; z-index: 2; } /* Inactive image state */ #unique-image-cycler-widget [data-image-cycle-item="not-active"] { opacity: 0; visibility: hidden; z-index: 1; } /* Responsive adjustments for mobile */ @media screen and (max-width: 767px) { #unique-image-cycler-widget .image-cycle-collection__list { border-radius: 10px; /* Maintain 10px radius on mobile */ } } </style> <!-- CSS SECTION END --> <!-- JAVASCRIPT SECTION START --> <script> // Self-executing function to avoid global scope pollution (function() { // Initialize when DOM is fully loaded document.addEventListener('DOMContentLoaded', function() { initImageCycle(); }); /** * Initialize image cycling functionality * Finds all image cycle containers and sets up automatic cycling */ function initImageCycle() { // Find all image cycle containers within our widget const widgetContainer = document.getElementById('unique-image-cycler-widget'); const cycleElements = widgetContainer.querySelectorAll("[data-image-cycle]"); cycleElements.forEach(cycleElement => { // Get all items in this cycle group const items = cycleElement.querySelectorAll("[data-image-cycle-item]"); // Skip if there aren't enough items to cycle if (items.length < 2) return; let currentIndex = 0; let intervalId; const duration = 2000; // Time between transitions in milliseconds const isTwoItems = items.length === 2; // Initialize: First item active, others not-active items.forEach((item, i) => { item.setAttribute("data-image-cycle-item", i === 0 ? "active" : "not-active"); }); /** * Cycle to the next image in the collection */ function cycleImages() { const prevIndex = currentIndex; currentIndex = (currentIndex + 1) % items.length; if (isTwoItems) { // Special case: Only two images - toggle between "previous" and "active" items[prevIndex].setAttribute("data-image-cycle-item", "previous"); } else { // Normal case: Three or more images items[prevIndex].setAttribute("data-image-cycle-item", "previous"); // Set to not-active after transition completes setTimeout(() => { items[prevIndex].setAttribute("data-image-cycle-item", "not-active"); }, duration); } // Set new active item items[currentIndex].setAttribute("data-image-cycle-item", "active"); } // Use IntersectionObserver to start/stop cycling when in/out of viewport const observer = new IntersectionObserver(([entry]) => { if (entry.isIntersecting && !intervalId) { // Start cycling when element is visible intervalId = setInterval(cycleImages, duration); } else if (!entry.isIntersecting && intervalId) { // Stop cycling when element is not visible clearInterval(intervalId); intervalId = null; } }, { threshold: 0 }); // Start observing the element observer.observe(cycleElement); }); } })(); </script> <!-- JAVASCRIPT SECTION END --> </div>
Implementation
The Image Cycling Widget creates a smooth, automated slideshow that transitions between images with elegant fade effects. When in the viewport, the widget automatically cycles through images at a set interval, providing a visually engaging experience while conserving resources when not visible.
HTML Structure
Use the following HTML structure:
- The main container unique-image-cycler-widget holds all cycling components
- The image-cycle-collection div creates the proportional container
- The image-cycle-collection__before element establishes the aspect ratio
- The image-cycle-collection__list with data-image-cycle attribute contains all images
- Each image is wrapped in a image-cycle-collection__img div with data-image-cycle-item attribute
CSS Styling
The CSS manages layout, transitions, and state management:
- Uses absolute positioning for image overlay and smooth transitions
- Implements three distinct states for images:
- active : Currently visible image
- previous : Recently active image transitioning out
- not-active : All other images not currently in transition
- Uses object-fit: cover to maintain proper image proportions
- Controls border radius (10px) for a clean, modern appearance
- Implements staggered opacity transitions for smooth fading between images
- Contains responsive adjustments for different screen sizes
JavaScript Functionality
The JavaScript handles cycling logic and viewport detection:
- Initialization: Sets up image states with first image active
- Cycling Logic: Manages transitions between images at regular intervals
- Viewport Detection: Uses IntersectionObserver to detect when the widget is visible
- Resource Management: Pauses cycling when not in viewport to save resources
- Special Case Handling: Different behavior for two-image galleries vs. multiple images
- State Management: Properly applies CSS classes for managing transitions
Customization Tips
You can easily customize various aspects of the widget:
- Transition Speed: Modify the duration variable (currently 2000ms) to change cycling speed
- Border Radius: Adjust the border-radius property on .image-cycle-collection__list
- Aspect Ratio: Change the padding-top percentage on .image-cycle-collection__before
- Transition Effects: Modify the transition properties for different fade effects
- Image Count: Add or remove image elements in the HTML structure
- Container Size: The widget fills 100% of its parent container, so control size by adjusting the parent
CMS Integration
To integrate with a CMS:
- Create a collection for image items with fields for:
- Image file (recommend consistent aspect ratios)
- Alt text for accessibility
- Optional caption or description
- Implement a loop in your template to generate each image element
- Use a unique ID if multiple cyclers appear on one page
- Adjust the document.getElementById() selector in JavaScript to match your unique ID
- For optimal performance, use appropriately sized images and enable lazy loading

How to edit code using AI →
Resource Details:
Image Cycling Widget creates a responsive, automatic image slideshow with smooth fade transitions. Images cycle through a sequence with elegant opacity animations when in viewport. Features include resource-saving viewport detection, customizable transition timing, responsive design, and browser compatibility. Simple HTML/CSS/JS implementation with adjustable border radius, aspect ratio, and container dimensions. Self-contained code requires no dependencies and works in any HTML environment.

NO-ACCESS
Only for Desktop Users
This page is only available on desktop.
Please Log in on a desktop to gain access.