Carousel embla basic
Embla Carousel(CDN)で左へ自動スクロールするカルーセル。
2021年9月以降、すべてのブラウザーで利用可能です。
- Baseline
- BaselineWidely available
- 対応ブラウザ
- Chrome88+Edge88+Firefox89+Safari15+
プレビューを読み込み中
<div class="carousel-embla-basic js-carousel-embla-basic">
<div class="carousel-embla-basic__viewport">
<div class="carousel-embla-basic__container">
<div class="carousel-embla-basic__slide">
<img
class="carousel-embla-basic__image"
src="/snippets/card-sample-01.jpg"
alt=""
width="640"
height="360"
decoding="async"
/>
</div>
<div class="carousel-embla-basic__slide">
<img
class="carousel-embla-basic__image"
src="/snippets/card-sample-01.jpg"
alt=""
width="640"
height="360"
decoding="async"
/>
</div>
<div class="carousel-embla-basic__slide">
<img
class="carousel-embla-basic__image"
src="/snippets/card-sample-01.jpg"
alt=""
width="640"
height="360"
decoding="async"
/>
</div>
<div class="carousel-embla-basic__slide">
<img
class="carousel-embla-basic__image"
src="/snippets/card-sample-01.jpg"
alt=""
width="640"
height="360"
decoding="async"
/>
</div>
<div class="carousel-embla-basic__slide">
<img
class="carousel-embla-basic__image"
src="/snippets/card-sample-01.jpg"
alt=""
width="640"
height="360"
decoding="async"
/>
</div>
</div>
</div>
</div>
<script src="https://unpkg.com/embla-carousel@8.6.0/embla-carousel.umd.js"></script>
<script src="https://unpkg.com/embla-carousel-auto-scroll@8.6.0/embla-carousel-auto-scroll.umd.js"></script>
<div class="carousel-embla-basic js-carousel-embla-basic">
<div class="carousel-embla-basic__viewport">
<div class="carousel-embla-basic__container">
<div class="carousel-embla-basic__slide">
<img
class="carousel-embla-basic__image"
src="/snippets/card-sample-01.jpg"
alt=""
width="640"
height="360"
decoding="async"
/>
</div>
<div class="carousel-embla-basic__slide">
<img
class="carousel-embla-basic__image"
src="/snippets/card-sample-01.jpg"
alt=""
width="640"
height="360"
decoding="async"
/>
</div>
<div class="carousel-embla-basic__slide">
<img
class="carousel-embla-basic__image"
src="/snippets/card-sample-01.jpg"
alt=""
width="640"
height="360"
decoding="async"
/>
</div>
<div class="carousel-embla-basic__slide">
<img
class="carousel-embla-basic__image"
src="/snippets/card-sample-01.jpg"
alt=""
width="640"
height="360"
decoding="async"
/>
</div>
<div class="carousel-embla-basic__slide">
<img
class="carousel-embla-basic__image"
src="/snippets/card-sample-01.jpg"
alt=""
width="640"
height="360"
decoding="async"
/>
</div>
</div>
</div>
</div>
<script src="https://unpkg.com/embla-carousel@8.6.0/embla-carousel.umd.js"></script>
<script src="https://unpkg.com/embla-carousel-auto-scroll@8.6.0/embla-carousel-auto-scroll.umd.js"></script>
/* Embla Carousel と Auto Scroll プラグインを CDN から読み込んでください(HTML 内 script 参照)。 */
/* 初期化 JS(script.js)は CDN 読み込みより後に配置してください。 */
/* --carousel-slide-size でスライド幅を変更できます。 */
/* --carousel-gap でスライド間隔を変更できます。 */
/* --carousel-radius で角丸を変更できます。 */
/* --carousel-scroll-speed で流れる速さ(px / frame)を変更できます。 */
/* reset */
:where(.carousel-embla-basic) {
box-sizing: border-box;
}
:where(img).carousel-embla-basic__image {
display: block;
}
/* snippet */
.carousel-embla-basic {
--carousel-slide-size: min(72%, 480px);
--carousel-gap: 16px;
--carousel-radius: 16px;
--carousel-scroll-speed: 0.5;
width: 100%;
margin-inline: auto;
}
.carousel-embla-basic__viewport {
overflow: hidden;
}
.carousel-embla-basic__container {
display: flex;
margin-left: calc(var(--carousel-gap) * -1);
}
.carousel-embla-basic__slide {
flex: 0 0 var(--carousel-slide-size);
min-width: 0;
padding-left: var(--carousel-gap);
}
.carousel-embla-basic__image {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: var(--carousel-radius);
}
/* Embla Carousel と Auto Scroll プラグインを CDN から読み込んでください(HTML 内 script 参照)。 */
/* 初期化 JS(script.js)は CDN 読み込みより後に配置してください。 */
/* --carousel-slide-size でスライド幅を変更できます。 */
/* --carousel-gap でスライド間隔を変更できます。 */
/* --carousel-radius で角丸を変更できます。 */
/* --carousel-scroll-speed で流れる速さ(px / frame)を変更できます。 */
/* reset */
:where(.carousel-embla-basic) {
box-sizing: border-box;
}
:where(img).carousel-embla-basic__image {
display: block;
}
/* snippet */
.carousel-embla-basic {
--carousel-slide-size: min(72%, 480px);
--carousel-gap: 16px;
--carousel-radius: 16px;
--carousel-scroll-speed: 0.5;
width: 100%;
margin-inline: auto;
}
.carousel-embla-basic__viewport {
overflow: hidden;
}
.carousel-embla-basic__container {
display: flex;
margin-left: calc(var(--carousel-gap) * -1);
}
.carousel-embla-basic__slide {
flex: 0 0 var(--carousel-slide-size);
min-width: 0;
padding-left: var(--carousel-gap);
}
.carousel-embla-basic__image {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: var(--carousel-radius);
}
(function () {
function init() {
if (typeof EmblaCarousel === "undefined") return;
const reducedMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)",
).matches;
document.querySelectorAll(".js-carousel-embla-basic").forEach((root) => {
if (root.dataset.carouselEmblaBasicInit) return;
root.dataset.carouselEmblaBasicInit = "true";
const viewport = root.querySelector(".carousel-embla-basic__viewport");
const container = root.querySelector(".carousel-embla-basic__container");
if (!viewport || !container) return;
const originalSlides = Array.from(
container.querySelectorAll(".carousel-embla-basic__slide"),
);
if (!originalSlides.length) return;
const speedValue = getComputedStyle(root)
.getPropertyValue("--carousel-scroll-speed")
.trim();
const speed = parseFloat(speedValue);
const plugins = [];
if (!reducedMotion && typeof EmblaCarouselAutoScroll !== "undefined") {
plugins.push(
EmblaCarouselAutoScroll({
direction: "forward",
speed: Number.isFinite(speed) ? speed : 1,
startDelay: 0,
stopOnInteraction: false,
stopOnMouseEnter: false,
playOnInit: true,
}),
);
}
const emblaApi = EmblaCarousel(
viewport,
{ loop: true, align: "start", watchDrag: false },
plugins,
);
const MAX_DUPLICATE_ROUNDS = 12;
function canLoop() {
return Boolean(emblaApi.internalEngine()?.slideLooper?.canLoop());
}
function appendOriginalSlides() {
originalSlides.forEach((slide) => {
const clone = slide.cloneNode(true);
clone.setAttribute("data-carousel-clone", "");
clone.setAttribute("aria-hidden", "true");
container.appendChild(clone);
});
}
function ensureLoop() {
let rounds = 0;
while (!canLoop() && rounds < MAX_DUPLICATE_ROUNDS) {
appendOriginalSlides();
emblaApi.reInit();
rounds += 1;
}
if (!reducedMotion && rounds > 0) {
emblaApi.plugins()?.autoScroll?.play();
}
}
ensureLoop();
emblaApi.on("resize", ensureLoop);
});
}
if (typeof EmblaCarousel !== "undefined") {
init();
return;
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init, { once: true });
} else {
init();
}
})();
(function () {
function init() {
if (typeof EmblaCarousel === "undefined") return;
const reducedMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)",
).matches;
document.querySelectorAll(".js-carousel-embla-basic").forEach((root) => {
if (root.dataset.carouselEmblaBasicInit) return;
root.dataset.carouselEmblaBasicInit = "true";
const viewport = root.querySelector(".carousel-embla-basic__viewport");
const container = root.querySelector(".carousel-embla-basic__container");
if (!viewport || !container) return;
const originalSlides = Array.from(
container.querySelectorAll(".carousel-embla-basic__slide"),
);
if (!originalSlides.length) return;
const speedValue = getComputedStyle(root)
.getPropertyValue("--carousel-scroll-speed")
.trim();
const speed = parseFloat(speedValue);
const plugins = [];
if (!reducedMotion && typeof EmblaCarouselAutoScroll !== "undefined") {
plugins.push(
EmblaCarouselAutoScroll({
direction: "forward",
speed: Number.isFinite(speed) ? speed : 1,
startDelay: 0,
stopOnInteraction: false,
stopOnMouseEnter: false,
playOnInit: true,
}),
);
}
const emblaApi = EmblaCarousel(
viewport,
{ loop: true, align: "start", watchDrag: false },
plugins,
);
const MAX_DUPLICATE_ROUNDS = 12;
function canLoop() {
return Boolean(emblaApi.internalEngine()?.slideLooper?.canLoop());
}
function appendOriginalSlides() {
originalSlides.forEach((slide) => {
const clone = slide.cloneNode(true);
clone.setAttribute("data-carousel-clone", "");
clone.setAttribute("aria-hidden", "true");
container.appendChild(clone);
});
}
function ensureLoop() {
let rounds = 0;
while (!canLoop() && rounds < MAX_DUPLICATE_ROUNDS) {
appendOriginalSlides();
emblaApi.reInit();
rounds += 1;
}
if (!reducedMotion && rounds > 0) {
emblaApi.plugins()?.autoScroll?.play();
}
}
ensureLoop();
emblaApi.on("resize", ensureLoop);
});
}
if (typeof EmblaCarousel !== "undefined") {
init();
return;
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init, { once: true });
} else {
init();
}
})();