Componente
Thumbnav
Una fila di miniature per scegliere un'immagine: link ad ancora verso le slide di un carosello, con la miniatura corrente evidenziata durante lo scorrimento.
- Riferimento
<it-thumbnav>- Classi
ita-thumbnavita-thumbnav-smita-thumbnav-lgita-thumbnav-verticalita-thumbnav-spy- Basato su (daisyUI)
carouselcarousel-item- Solo CSS
- Ogni miniatura è un link alla sua slide (#galleria-3): il browser scorre il carosello fino all'immagine. La miniatura corrente usa scroll-target-group e :target-current (Chrome 140+), altrimenti aria-current dal server. Il salto dell'ancora può scorrere anche la pagina e aggiorna l'hash: il frammento JavaScript sotto lo evita.
- Storybook
- Apri le storie di Thumbnav
Esempio base
Mostra il codice HTMLNascondi il codice HTML
<nav aria-label="Miniature" class="ita-thumbnav">
<ul>
<li><a href="#" aria-current="true"><img src="https://picsum.photos/id/1015/200/200" alt="Paesaggio 1" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1016/200/200" alt="Paesaggio 2" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1018/200/200" alt="Paesaggio 3" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1019/200/200" alt="Paesaggio 4" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1020/200/200" alt="Paesaggio 5" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1021/200/200" alt="Paesaggio 6" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1022/200/200" alt="Paesaggio 7" loading="lazy"></a></li>
</ul>
</nav>Dimensioni
Mostra il codice HTMLNascondi il codice HTML
<div class="flex flex-col gap-6">
<nav aria-label="Miniature piccole" class="ita-thumbnav ita-thumbnav-sm">
<ul>
<li><a href="#" aria-current="true"><img src="https://picsum.photos/id/1015/200/200" alt="Paesaggio 1" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1016/200/200" alt="Paesaggio 2" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1018/200/200" alt="Paesaggio 3" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1019/200/200" alt="Paesaggio 4" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1020/200/200" alt="Paesaggio 5" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1021/200/200" alt="Paesaggio 6" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1022/200/200" alt="Paesaggio 7" loading="lazy"></a></li>
</ul>
</nav>
<nav aria-label="Miniature grandi" class="ita-thumbnav ita-thumbnav-lg">
<ul>
<li><a href="#" aria-current="true"><img src="https://picsum.photos/id/1015/200/200" alt="Paesaggio 1" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1016/200/200" alt="Paesaggio 2" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1018/200/200" alt="Paesaggio 3" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1019/200/200" alt="Paesaggio 4" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1020/200/200" alt="Paesaggio 5" loading="lazy"></a></li>
</ul>
</nav>
</div>Verticale
Mostra il codice HTMLNascondi il codice HTML
<nav aria-label="Miniature" class="ita-thumbnav ita-thumbnav-vertical">
<ul>
<li><a href="#" aria-current="true"><img src="https://picsum.photos/id/1015/200/200" alt="Paesaggio 1" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1016/200/200" alt="Paesaggio 2" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1018/200/200" alt="Paesaggio 3" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1019/200/200" alt="Paesaggio 4" loading="lazy"></a></li>
<li><a href="#"><img src="https://picsum.photos/id/1020/200/200" alt="Paesaggio 5" loading="lazy"></a></li>
</ul>
</nav>Con un carosello
Clicca una miniatura: il carosello va all'immagine e la miniatura si evidenzia mentre scorri.
Paesaggio 1
Paesaggio 2
Paesaggio 3
Paesaggio 4
Paesaggio 5
Paesaggio 6
Paesaggio 7
Mostra il codice HTMLNascondi il codice HTML
<div class="flex flex-col gap-4">
<section class="ita-carousel ita-carousel-image" aria-roledescription="carosello" aria-label="Galleria">
<div>
<div class="carousel" tabindex="0">
<figure id="galleria-1" role="group" aria-roledescription="slide" aria-label="1 di 7" class="carousel-item">
<img src="https://picsum.photos/id/1015/1200/675" alt="Paesaggio 1" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Paesaggio 1</p>
</figcaption>
</figure>
<figure id="galleria-2" role="group" aria-roledescription="slide" aria-label="2 di 7" class="carousel-item">
<img src="https://picsum.photos/id/1016/1200/675" alt="Paesaggio 2" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Paesaggio 2</p>
</figcaption>
</figure>
<figure id="galleria-3" role="group" aria-roledescription="slide" aria-label="3 di 7" class="carousel-item">
<img src="https://picsum.photos/id/1018/1200/675" alt="Paesaggio 3" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Paesaggio 3</p>
</figcaption>
</figure>
<figure id="galleria-4" role="group" aria-roledescription="slide" aria-label="4 di 7" class="carousel-item">
<img src="https://picsum.photos/id/1019/1200/675" alt="Paesaggio 4" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Paesaggio 4</p>
</figcaption>
</figure>
<figure id="galleria-5" role="group" aria-roledescription="slide" aria-label="5 di 7" class="carousel-item">
<img src="https://picsum.photos/id/1020/1200/675" alt="Paesaggio 5" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Paesaggio 5</p>
</figcaption>
</figure>
<figure id="galleria-6" role="group" aria-roledescription="slide" aria-label="6 di 7" class="carousel-item">
<img src="https://picsum.photos/id/1021/1200/675" alt="Paesaggio 6" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Paesaggio 6</p>
</figcaption>
</figure>
<figure id="galleria-7" role="group" aria-roledescription="slide" aria-label="7 di 7" class="carousel-item">
<img src="https://picsum.photos/id/1022/1200/675" alt="Paesaggio 7" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Paesaggio 7</p>
</figcaption>
</figure>
</div>
</div>
</section>
<nav aria-label="Scegli l'immagine" class="ita-thumbnav ita-thumbnav-spy">
<ul>
<li><a href="#galleria-1"><img src="https://picsum.photos/id/1015/200/200" alt="Paesaggio 1" loading="lazy"></a></li>
<li><a href="#galleria-2"><img src="https://picsum.photos/id/1016/200/200" alt="Paesaggio 2" loading="lazy"></a></li>
<li><a href="#galleria-3"><img src="https://picsum.photos/id/1018/200/200" alt="Paesaggio 3" loading="lazy"></a></li>
<li><a href="#galleria-4"><img src="https://picsum.photos/id/1019/200/200" alt="Paesaggio 4" loading="lazy"></a></li>
<li><a href="#galleria-5"><img src="https://picsum.photos/id/1020/200/200" alt="Paesaggio 5" loading="lazy"></a></li>
<li><a href="#galleria-6"><img src="https://picsum.photos/id/1021/200/200" alt="Paesaggio 6" loading="lazy"></a></li>
<li><a href="#galleria-7"><img src="https://picsum.photos/id/1022/200/200" alt="Paesaggio 7" loading="lazy"></a></li>
</ul>
</nav>
</div>Con JavaScript (opzionale)
La ricetta è solo CSS e funziona così com'è. Questi frammenti non sono inclusi nel pacchetto: mostrano come aggiungere il comportamento che richiede uno script, in JavaScript semplice o in React.
Miniatura corrente in tutti i browserjs
Aggiorna aria-current con IntersectionObserver e scorre il carosello senza muovere la pagina.
// Keep aria-current on the thumbnail of the visible slide (all browsers),
// and scroll the carousel without moving the page when a thumbnail is clicked.
document.querySelectorAll("nav[aria-label] ul").forEach((list) => {
const links = [...list.querySelectorAll("a[href^='#']")];
const slides = links.map((a) => document.querySelector(a.hash)).filter(Boolean);
if (!slides.length) return;
const io = new IntersectionObserver((entries) => {
for (const e of entries) {
if (e.intersectionRatio < 0.6) continue;
for (const a of links) {
if (a.hash === "#" + e.target.id) a.setAttribute("aria-current", "true");
else a.removeAttribute("aria-current");
}
}
}, { threshold: 0.6 });
slides.forEach((s) => io.observe(s));
list.addEventListener("click", (ev) => {
const a = ev.target.closest("a[href^='#']");
if (!a) return;
ev.preventDefault();
document.querySelector(a.hash)?.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "start" });
});
});Galleria in Reacttsx
import { useRef, useState } from "react";
type Photo = { src: string; thumb: string; alt: string };
/** Gallery with thumbnails: React owns the current index. */
export function Gallery({ photos }: { photos: Photo[] }) {
const [current, setCurrent] = useState(0);
const track = useRef<HTMLDivElement>(null);
const show = (i: number) => {
setCurrent(i);
track.current?.children[i]?.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "start" });
};
return (
<div className="flex flex-col gap-4">
<div ref={track} className="carousel w-full gap-4 rounded-box" tabIndex={0}
onScroll={(e) => setCurrent(Math.round(e.currentTarget.scrollLeft / e.currentTarget.clientWidth))}>
{photos.map((p) => (
<img key={p.src} src={p.src} alt={p.alt} className="carousel-item aspect-video w-full object-cover" />
))}
</div>
<nav aria-label="Scegli l'immagine" className="ita-thumbnav">
<ul>
{photos.map((p, i) => (
<li key={p.thumb}>
<button type="button" onClick={() => show(i)} aria-current={i === current || undefined}>
<img src={p.thumb} alt={p.alt} />
</button>
</li>
))}
</ul>
</nav>
</div>
);
}