Nuovo sportello digitale
Prenota un appuntamento con l'anagrafe direttamente online.
Componente
Caroselli di card o immagini su daisyUI carousel (scroll-snap). Pulsanti avanti/indietro e punti di navigazione sono pseudo-elementi CSS (::scroll-button, ::scroll-marker): nessuno script.
<it-carousel>, <it-carousel-item>ita-carouselita-carousel-imageita-carousel-peekita-carousel-captionita-carousel-titleita-carousel-pagercarouselcarousel-itemcardit-carouselPrenota un appuntamento con l'anagrafe direttamente online.
Quaranta nuove stazioni di bike sharing in tutta la città.
Iscrizioni ai servizi di mensa e trasporto fino al 30 settembre.
Il programma completo degli eventi culturali nei parchi.
Cambiano i giorni di ritiro nei quartieri nord.
<section class="ita-carousel" aria-roledescription="carosello" aria-labelledby="carousel-1-title">
<h2 id="carousel-1-title" class="ita-carousel-title">Notizie in evidenza</h2>
<div>
<div class="carousel it-carousel" tabindex="0">
<div id="carousel-1-1" role="group" aria-roledescription="slide" aria-label="1 di 5" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1031/800/450" alt="Edificio comunale" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Nuovo sportello digitale</a>
</h3>
<p class="ita-card-text">Prenota un appuntamento con l'anagrafe direttamente online.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Servizi</a></div>
<time>18 set 2026</time>
</footer>
</div>
</article>
</div>
<div id="carousel-1-2" role="group" aria-roledescription="slide" aria-label="2 di 5" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1067/800/450" alt="Strada cittadina" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Mobilità sostenibile</a>
</h3>
<p class="ita-card-text">Quaranta nuove stazioni di bike sharing in tutta la città.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Mobilità</a></div>
<time>12 set 2026</time>
</footer>
</div>
</article>
</div>
<div id="carousel-1-3" role="group" aria-roledescription="slide" aria-label="3 di 5" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1073/800/450" alt="Aula scolastica" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Scuole aperte</a>
</h3>
<p class="ita-card-text">Iscrizioni ai servizi di mensa e trasporto fino al 30 settembre.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Scuola</a></div>
<time>5 set 2026</time>
</footer>
</div>
</article>
</div>
<div id="carousel-1-4" role="group" aria-roledescription="slide" aria-label="4 di 5" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1044/800/450" alt="Parco cittadino" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Estate in città</a>
</h3>
<p class="ita-card-text">Il programma completo degli eventi culturali nei parchi.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Cultura</a></div>
<time>1 set 2026</time>
</footer>
</div>
</article>
</div>
<div id="carousel-1-5" role="group" aria-roledescription="slide" aria-label="5 di 5" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1018/800/450" alt="Paesaggio verde" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Raccolta differenziata</a>
</h3>
<p class="ita-card-text">Cambiano i giorni di ritiro nei quartieri nord.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Ambiente</a></div>
<time>28 ago 2026</time>
</footer>
</div>
</article>
</div>
</div>
</div>
</section>Nuovo sportello digitale
Prenota un appuntamento con l'anagrafe direttamente online.
Mobilità sostenibile
Quaranta nuove stazioni di bike sharing in tutta la città.
Scuole aperte
Iscrizioni ai servizi di mensa e trasporto fino al 30 settembre.
Estate in città
Il programma completo degli eventi culturali nei parchi.
Raccolta differenziata
Cambiano i giorni di ritiro nei quartieri nord.
<section class="ita-carousel ita-carousel-image" aria-roledescription="carosello" aria-label="Galleria del territorio">
<div>
<div class="carousel it-carousel" tabindex="0">
<figure id="carousel-2-1" role="group" aria-roledescription="slide" aria-label="1 di 5" class="carousel-item">
<img src="https://picsum.photos/id/1031/1200/600" alt="Edificio comunale" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Nuovo sportello digitale</p>
<p>Prenota un appuntamento con l'anagrafe direttamente online.</p>
</figcaption>
</figure>
<figure id="carousel-2-2" role="group" aria-roledescription="slide" aria-label="2 di 5" class="carousel-item">
<img src="https://picsum.photos/id/1067/1200/600" alt="Strada cittadina" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Mobilità sostenibile</p>
<p>Quaranta nuove stazioni di bike sharing in tutta la città.</p>
</figcaption>
</figure>
<figure id="carousel-2-3" role="group" aria-roledescription="slide" aria-label="3 di 5" class="carousel-item">
<img src="https://picsum.photos/id/1073/1200/600" alt="Aula scolastica" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Scuole aperte</p>
<p>Iscrizioni ai servizi di mensa e trasporto fino al 30 settembre.</p>
</figcaption>
</figure>
<figure id="carousel-2-4" role="group" aria-roledescription="slide" aria-label="4 di 5" class="carousel-item">
<img src="https://picsum.photos/id/1044/1200/600" alt="Parco cittadino" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Estate in città</p>
<p>Il programma completo degli eventi culturali nei parchi.</p>
</figcaption>
</figure>
<figure id="carousel-2-5" role="group" aria-roledescription="slide" aria-label="5 di 5" class="carousel-item">
<img src="https://picsum.photos/id/1018/1200/600" alt="Paesaggio verde" loading="lazy">
<figcaption class="ita-carousel-caption">
<p>Raccolta differenziata</p>
<p>Cambiano i giorni di ritiro nei quartieri nord.</p>
</figcaption>
</figure>
</div>
</div>
</section>Prenota un appuntamento con l'anagrafe direttamente online.
Quaranta nuove stazioni di bike sharing in tutta la città.
Iscrizioni ai servizi di mensa e trasporto fino al 30 settembre.
Il programma completo degli eventi culturali nei parchi.
Cambiano i giorni di ritiro nei quartieri nord.
<section class="ita-carousel ita-carousel-peek" aria-roledescription="carosello" aria-label="Servizi">
<div>
<div class="carousel it-carousel" tabindex="0">
<div id="carousel-3-1" role="group" aria-roledescription="slide" aria-label="1 di 5" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1031/800/450" alt="Edificio comunale" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Nuovo sportello digitale</a>
</h3>
<p class="ita-card-text">Prenota un appuntamento con l'anagrafe direttamente online.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Servizi</a></div>
<time>18 set 2026</time>
</footer>
</div>
</article>
</div>
<div id="carousel-3-2" role="group" aria-roledescription="slide" aria-label="2 di 5" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1067/800/450" alt="Strada cittadina" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Mobilità sostenibile</a>
</h3>
<p class="ita-card-text">Quaranta nuove stazioni di bike sharing in tutta la città.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Mobilità</a></div>
<time>12 set 2026</time>
</footer>
</div>
</article>
</div>
<div id="carousel-3-3" role="group" aria-roledescription="slide" aria-label="3 di 5" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1073/800/450" alt="Aula scolastica" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Scuole aperte</a>
</h3>
<p class="ita-card-text">Iscrizioni ai servizi di mensa e trasporto fino al 30 settembre.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Scuola</a></div>
<time>5 set 2026</time>
</footer>
</div>
</article>
</div>
<div id="carousel-3-4" role="group" aria-roledescription="slide" aria-label="4 di 5" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1044/800/450" alt="Parco cittadino" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Estate in città</a>
</h3>
<p class="ita-card-text">Il programma completo degli eventi culturali nei parchi.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Cultura</a></div>
<time>1 set 2026</time>
</footer>
</div>
</article>
</div>
<div id="carousel-3-5" role="group" aria-roledescription="slide" aria-label="5 di 5" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1018/800/450" alt="Paesaggio verde" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Raccolta differenziata</a>
</h3>
<p class="ita-card-text">Cambiano i giorni di ritiro nei quartieri nord.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Ambiente</a></div>
<time>28 ago 2026</time>
</footer>
</div>
</article>
</div>
</div>
</div>
</section>Link ad ancora numerati: funzionano in ogni browser, ma aggiornano l'hash dell'URL.
Prenota un appuntamento con l'anagrafe direttamente online.
Quaranta nuove stazioni di bike sharing in tutta la città.
Iscrizioni ai servizi di mensa e trasporto fino al 30 settembre.
Il programma completo degli eventi culturali nei parchi.
<section class="ita-carousel" aria-roledescription="carosello" aria-label="Notizie">
<div>
<div class="carousel" tabindex="0">
<div id="carousel-4-1" role="group" aria-roledescription="slide" aria-label="1 di 4" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1031/800/450" alt="Edificio comunale" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Nuovo sportello digitale</a>
</h3>
<p class="ita-card-text">Prenota un appuntamento con l'anagrafe direttamente online.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Servizi</a></div>
<time>18 set 2026</time>
</footer>
</div>
</article>
</div>
<div id="carousel-4-2" role="group" aria-roledescription="slide" aria-label="2 di 4" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1067/800/450" alt="Strada cittadina" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Mobilità sostenibile</a>
</h3>
<p class="ita-card-text">Quaranta nuove stazioni di bike sharing in tutta la città.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Mobilità</a></div>
<time>12 set 2026</time>
</footer>
</div>
</article>
</div>
<div id="carousel-4-3" role="group" aria-roledescription="slide" aria-label="3 di 4" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1073/800/450" alt="Aula scolastica" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Scuole aperte</a>
</h3>
<p class="ita-card-text">Iscrizioni ai servizi di mensa e trasporto fino al 30 settembre.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Scuola</a></div>
<time>5 set 2026</time>
</footer>
</div>
</article>
</div>
<div id="carousel-4-4" role="group" aria-roledescription="slide" aria-label="4 di 4" class="carousel-item">
<article class="card ita-card">
<figure><img src="https://picsum.photos/id/1044/800/450" alt="Parco cittadino" loading="lazy"></figure>
<div class="card-body">
<h3 class="card-title">
<a href="#">Estate in città</a>
</h3>
<p class="ita-card-text">Il programma completo degli eventi culturali nei parchi.</p>
<footer class="ita-card-footer">
<div><a href="#" class="ita-card-category">Cultura</a></div>
<time>1 set 2026</time>
</footer>
</div>
</article>
</div>
</div>
</div>
<nav class="ita-carousel-pager" aria-label="Scegli la slide">
<a href="#carousel-4-1">1</a>
<a href="#carousel-4-2">2</a>
<a href="#carousel-4-3">3</a>
<a href="#carousel-4-4">4</a>
</nav>
</section>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.
Aggiunge i pulsanti solo dove mancano quelli CSS.
// Prev/next buttons for browsers without ::scroll-button (Safari, Firefox).
// Skipped where the CSS buttons exist, so the two never show together.
if (!CSS.supports("selector(::scroll-button(*))")) {
document.querySelectorAll(".it-carousel").forEach((track) => {
const make = (dir, label, glyph) => {
const b = document.createElement("button");
b.type = "button";
b.className = `ita-btn ita-btn-primary ita-btn-circle absolute top-1/2 -translate-y-1/2 ${dir < 0 ? "start-2" : "end-2"}`;
b.setAttribute("aria-label", label);
b.textContent = glyph;
b.addEventListener("click", () => track.scrollBy({ left: dir * track.clientWidth }));
return b;
};
track.parentElement.append(make(-1, "Precedente", "‹"), make(1, "Successivo", "›"));
});
}bootstrap-italia non lo fa di default: se ti serve, si ferma al passaggio del mouse, al focus e con «riduci movimento».
// Autoplay that stops on hover, on focus and with "reduce motion".
// Works with or without the CSS scroll buttons.
document.querySelectorAll("[aria-roledescription='carosello']").forEach((region) => {
const track = region.querySelector(".carousel");
if (!track || matchMedia("(prefers-reduced-motion: reduce)").matches) return;
let paused = false;
for (const [on, off] of [["mouseenter", "mouseleave"], ["focusin", "focusout"]]) {
region.addEventListener(on, () => (paused = true));
region.addEventListener(off, () => (paused = false));
}
setInterval(() => {
if (paused) return;
const atEnd = track.scrollLeft + track.clientWidth >= track.scrollWidth - 1;
track.scrollTo({ left: atEnd ? 0 : track.scrollLeft + track.clientWidth });
}, 6000);
});import { useRef, type ReactNode } from "react";
/** The recipe's markup as a component; buttons use scrollBy, so they work in every browser. */
export function Carousel({ label, children }: { label: string; children: ReactNode[] }) {
const track = useRef<HTMLDivElement>(null);
const go = (dir: 1 | -1) => track.current?.scrollBy({ left: dir * track.current.clientWidth });
return (
<section className="ita-carousel" aria-roledescription="carosello" aria-label={label}>
<div>
<div ref={track} className="carousel" tabIndex={0}>
{children.map((child, i) => (
<div key={i} role="group" aria-roledescription="slide" aria-label={`${i + 1} di ${children.length}`}
className="carousel-item">
{child}
</div>
))}
</div>
<button type="button" className="ita-btn ita-btn-primary ita-btn-circle absolute start-2 top-1/2 -translate-y-1/2" aria-label="Precedente" onClick={() => go(-1)}>‹</button>
<button type="button" className="ita-btn ita-btn-primary ita-btn-circle absolute end-2 top-1/2 -translate-y-1/2" aria-label="Successivo" onClick={() => go(1)}>›</button>
</div>
</section>
);
}