Media Components
JavaScript components for carousels, galleries, image comparison, lazy loading, and lightbox.
Carousel Manager
Carousel/slider for cycling through items with autoplay and looping.
HTML
<!-- Basic carousel -->
<div
data-ss="carousel"
data-ss-carousel-loop="true"
data-ss-carousel-autoplay="5000"
style="
position: relative;
max-width: 600px;
border-radius: 12px;
overflow: hidden;
"
>
<div
class="ss-c-carousel-track"
style="display: flex; transition: transform 0.5s ease"
>
<div
class="ss-c-carousel-item active"
style="
min-width: 100%;
height: 300px;
background: linear-gradient(
135deg,
#667eea 0%,
#764ba2 100%
);
display: flex;
align-items: center;
justify-content: center;
color: white;
"
>
<div style="text-align: center">
<h3 style="margin: 0 0 8px">Slide 1</h3>
<p style="margin: 0; opacity: 0.8">
First slide content
</p>
</div>
</div>
<div
class="ss-c-carousel-item"
style="
min-width: 100%;
height: 300px;
background: linear-gradient(
135deg,
#f093fb 0%,
#f5576c 100%
);
display: flex;
align-items: center;
justify-content: center;
color: white;
"
>
<div style="text-align: center">
<h3 style="margin: 0 0 8px">Slide 2</h3>
<p style="margin: 0; opacity: 0.8">
Second slide content
</p>
</div>
</div>
<div
class="ss-c-carousel-item"
style="
min-width: 100%;
height: 300px;
background: linear-gradient(
135deg,
#4facfe 0%,
#00f2fe 100%
);
display: flex;
align-items: center;
justify-content: center;
color: white;
"
>
<div style="text-align: center">
<h3 style="margin: 0 0 8px">Slide 3</h3>
<p style="margin: 0; opacity: 0.8">
Third slide content
</p>
</div>
</div>
</div>
<!-- Navigation arrows -->
<button
class="ss-c-carousel-prev"
style="
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.9);
border: none;
cursor: pointer;
font-size: 18px;
"
>
←
</button>
<button
class="ss-c-carousel-next"
style="
position: absolute;
right: 16px;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.9);
border: none;
cursor: pointer;
font-size: 18px;
"
>
→
</button>
<!-- Indicators -->
<div
class="ss-c-carousel-indicators"
style="
position: absolute;
bottom: 16px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 8px;
"
>
<span
class="active"
style="
width: 24px;
height: 4px;
border-radius: 2px;
background: white;
cursor: pointer;
"
></span>
<span
style="
width: 12px;
height: 4px;
border-radius: 2px;
background: rgba(255, 255, 255, 0.5);
cursor: pointer;
"
></span>
<span
style="
width: 12px;
height: 4px;
border-radius: 2px;
background: rgba(255, 255, 255, 0.5);
cursor: pointer;
"
></span>
</div>
</div>
Gallery Manager
Image gallery with navigation, selection, and lightbox integration.
HTML
<!-- Gallery with lightbox -->
<div
data-ss="gallery"
data-ss-gallery-lightbox="true"
style="
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 12px;
"
>
<div
style="
aspect-ratio: 1;
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 8px;
cursor: pointer;
overflow: hidden;
transition: transform 0.2s;
"
>
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect fill='%23667eea' width='100' height='100'/%3E%3C/svg%3E"
alt="Image 1"
style="width: 100%; height: 100%; object-fit: cover"
/>
</div>
<div
style="
aspect-ratio: 1;
background: linear-gradient(135deg, #f093fb, #f5576c);
border-radius: 8px;
cursor: pointer;
overflow: hidden;
transition: transform 0.2s;
"
>
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect fill='%23f093fb' width='100' height='100'/%3E%3C/svg%3E"
alt="Image 2"
style="width: 100%; height: 100%; object-fit: cover"
/>
</div>
<div
style="
aspect-ratio: 1;
background: linear-gradient(135deg, #4facfe, #00f2fe);
border-radius: 8px;
cursor: pointer;
overflow: hidden;
transition: transform 0.2s;
"
>
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect fill='%234facfe' width='100' height='100'/%3E%3C/svg%3E"
alt="Image 3"
style="width: 100%; height: 100%; object-fit: cover"
/>
</div>
<div
style="
aspect-ratio: 1;
background: linear-gradient(135deg, #43e97b, #38f9d7);
border-radius: 8px;
cursor: pointer;
overflow: hidden;
transition: transform 0.2s;
"
>
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect fill='%2343e97b' width='100' height='100'/%3E%3C/svg%3E"
alt="Image 4"
style="width: 100%; height: 100%; object-fit: cover"
/>
</div>
<div
style="
aspect-ratio: 1;
background: linear-gradient(135deg, #fa709a, #fee140);
border-radius: 8px;
cursor: pointer;
overflow: hidden;
transition: transform 0.2s;
"
>
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect fill='%23fa709a' width='100' height='100'/%3E%3C/svg%3E"
alt="Image 5"
style="width: 100%; height: 100%; object-fit: cover"
/>
</div>
<div
style="
aspect-ratio: 1;
background: linear-gradient(135deg, #a8edea, #fed6e3);
border-radius: 8px;
cursor: pointer;
overflow: hidden;
transition: transform 0.2s;
"
>
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect fill='%23a8edea' width='100' height='100'/%3E%3C/svg%3E"
alt="Image 6"
style="width: 100%; height: 100%; object-fit: cover"
/>
</div>
</div>
Image Compare Slider
Before/after image comparison slider with drag support.
HTML
<!-- Image comparison -->
<div
class="ss-c-image__compare"
data-ss="image-compare"
data-ss-image-compare-position="50"
style="
position: relative;
max-width: 600px;
aspect-ratio: 16/9;
overflow: hidden;
border-radius: 12px;
cursor: ew-resize;
"
>
<!-- After image (bottom layer) -->
<div
class="ss-c-image__compare--image"
style="
position: absolute;
inset: 0;
background: linear-gradient(135deg, #667eea, #764ba2);
"
>
<div
style="
position: absolute;
bottom: 16px;
right: 16px;
padding: 8px 16px;
background: rgba(0, 0, 0, 0.6);
color: white;
border-radius: 4px;
font-size: 14px;
"
>
After
</div>
</div>
<!-- Before image (top layer, clipped) -->
<div
class="ss-c-image__compare--overlay"
style="
position: absolute;
inset: 0;
background: linear-gradient(135deg, #1a1a2e, #16213e);
clip-path: inset(0 50% 0 0);
"
>
<div
style="
position: absolute;
bottom: 16px;
left: 16px;
padding: 8px 16px;
background: rgba(0, 0, 0, 0.6);
color: white;
border-radius: 4px;
font-size: 14px;
"
>
Before
</div>
</div>
<!-- Slider handle -->
<div
class="ss-c-image__compare--slider"
style="
position: absolute;
top: 0;
bottom: 0;
left: 50%;
width: 4px;
background: white;
cursor: ew-resize;
transform: translateX(-50%);
"
>
<div
style="
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 40px;
height: 40px;
background: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
"
>
<span style="font-size: 16px">⟷</span>
</div>
</div>
</div>
<!-- With indicator labels -->
<div
class="ss-c-image__compare"
data-ss="image-compare"
data-ss-image-compare-position="30"
style="
position: relative;
max-width: 600px;
aspect-ratio: 4/3;
overflow: hidden;
border-radius: 12px;
margin-top: 24px;
"
>
<div
style="
position: absolute;
inset: 0;
background: #22c55e;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 24px;
"
>
Edited
</div>
<div
style="
position: absolute;
inset: 0;
background: #ef4444;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 24px;
clip-path: inset(0 70% 0 0);
"
>
Original
</div>
<div
style="
position: absolute;
top: 0;
bottom: 0;
left: 30%;
width: 3px;
background: white;
"
></div>
</div>
Lazy Load Manager
Lazy loading of images via IntersectionObserver.
Background loading...
HTML
<!-- Lazy loaded image -->
<img
class="ss-c-lazy-image"
data-ss="lazy"
data-src="https://picsum.photos/800/400"
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 400'%3E%3Crect fill='%23e5e7eb' width='800' height='400'/%3E%3C/svg%3E"
alt="Lazy loaded image"
style="
width: 100%;
max-width: 600px;
height: auto;
border-radius: 12px;
transition: opacity 0.3s;
"
/>
<!-- Lazy loaded background -->
<div
class="ss-c-lazy-bg"
data-ss="lazy"
data-src="https://picsum.photos/1200/600"
style="
width: 100%;
max-width: 600px;
height: 300px;
background: var(--color_fill_secondary);
border-radius: 12px;
margin-top: 16px;
display: flex;
align-items: center;
justify-content: center;
color: var(--color_text_secondary);
"
>
<span>Background loading...</span>
</div>
<!-- Skeleton placeholder -->
<div
style="
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
max-width: 600px;
margin-top: 24px;
"
>
<div
class="ss-c-lazy-image"
data-ss="lazy"
style="
aspect-ratio: 1;
background: linear-gradient(
90deg,
var(--color_fill_secondary) 0%,
#e5e7eb 50%,
var(--color_fill_secondary) 100%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 8px;
"
></div>
<div
class="ss-c-lazy-image"
data-ss="lazy"
style="
aspect-ratio: 1;
background: linear-gradient(
90deg,
var(--color_fill_secondary) 0%,
#e5e7eb 50%,
var(--color_fill_secondary) 100%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 8px;
"
></div>
<div
class="ss-c-lazy-image"
data-ss="lazy"
style="
aspect-ratio: 1;
background: linear-gradient(
90deg,
var(--color_fill_secondary) 0%,
#e5e7eb 50%,
var(--color_fill_secondary) 100%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 8px;
"
></div>
</div>
<style>
@keyframes shimmer {
0% {
background-position: -200% 0;
}
100% {
background-position: 200% 0;
}
}
</style>
Lightbox Manager
Fullscreen lightbox overlay for viewing content.
HTML
<!-- Lightbox triggers -->
<div style="display: flex; gap: 16px">
<button
data-ss="lightbox"
data-ss-lightbox-src="https://picsum.photos/1200/800"
style="
padding: 0;
border: none;
cursor: pointer;
border-radius: 8px;
overflow: hidden;
"
>
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 150'%3E%3Crect fill='%23667eea' width='200' height='150'/%3E%3C/svg%3E"
alt="Thumbnail 1"
style="
width: 200px;
height: 150px;
object-fit: cover;
display: block;
"
/>
</button>
<button
data-ss="lightbox"
data-ss-lightbox-src="https://picsum.photos/1200/900"
style="
padding: 0;
border: none;
cursor: pointer;
border-radius: 8px;
overflow: hidden;
"
>
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 150'%3E%3Crect fill='%23f093fb' width='200' height='150'/%3E%3C/svg%3E"
alt="Thumbnail 2"
style="
width: 200px;
height: 150px;
object-fit: cover;
display: block;
"
/>
</button>
</div>
<!-- Lightbox overlay structure -->
<div
class="ss-c-lightbox"
style="
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.95);
display: flex;
align-items: center;
justify-content: center;
z-index: 2000;
opacity: 0;
pointer-events: none;
"
>
<button
class="ss-c-lightbox__close"
style="
position: absolute;
top: 20px;
right: 20px;
width: 48px;
height: 48px;
background: rgba(255, 255, 255, 0.1);
border: none;
border-radius: 50%;
color: white;
font-size: 24px;
cursor: pointer;
"
>
×
</button>
<button
class="ss-c-lightbox__prev"
style="
position: absolute;
left: 20px;
top: 50%;
transform: translateY(-50%);
width: 48px;
height: 48px;
background: rgba(255, 255, 255, 0.1);
border: none;
border-radius: 50%;
color: white;
font-size: 24px;
cursor: pointer;
"
>
←
</button>
<button
class="ss-c-lightbox__next"
style="
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
width: 48px;
height: 48px;
background: rgba(255, 255, 255, 0.1);
border: none;
border-radius: 50%;
color: white;
font-size: 24px;
cursor: pointer;
"
>
→
</button>
<img
class="ss-c-lightbox__image"
src=""
alt=""
style="max-width: 90vw; max-height: 90vh; object-fit: contain"
/>
<div
class="ss-c-lightbox__caption"
style="
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
color: white;
text-align: center;
"
></div>
</div>
JavaScript API
Programmatic control of media components.
JavaScript
<script>
// CarouselManager
import { CarouselManager } from "stylescape";
const carousel = new CarouselManager(element, {
loop: true,
autoplay: 5000,
pauseOnHover: true,
slidesToShow: 1,
slidesToScroll: 1,
onChange: (index) => console.log("Slide changed:", index),
});
carousel.next(); // Go to next slide
carousel.prev(); // Go to previous slide
carousel.goTo(2); // Go to specific slide
carousel.play(); // Start autoplay
carousel.pause(); // Pause autoplay
carousel.getCurrentIndex();
// GalleryManager
import { GalleryManager } from "stylescape";
const gallery = new GalleryManager(element, {
lightbox: true,
thumbs: true,
zoom: true,
onSelect: (index, image) => {
console.log("Selected:", index);
},
});
gallery.select(0); // Select image
gallery.openLightbox(1); // Open lightbox at index
gallery.closeLightbox();
// ImageCompareSlider
import { ImageCompareSlider } from "stylescape";
const compare = new ImageCompareSlider(element, {
position: 50,
vertical: false,
onChange: (position) => {
console.log("Position:", position + "%");
},
});
compare.setPosition(75); // Set slider position
// LazyLoadManager
import { LazyLoadManager } from "stylescape";
const lazyLoader = new LazyLoadManager({
root: null,
rootMargin: "100px",
threshold: 0.1,
onLoad: (element) => {
element.classList.add("loaded");
},
});
lazyLoader.observe(element);
lazyLoader.unobserve(element);
lazyLoader.refresh();
// LightboxManager
import { LightboxManager } from "stylescape";
const lightbox = new LightboxManager({
animation: "fade",
closeOnBackdrop: true,
keyboard: true,
captions: true,
});
lightbox.open(imageSrc, caption);
lightbox.close();
lightbox.next();
lightbox.prev();
</script>