En algunas ocasiones necesitamos que cada diapositiva tenga HTML, en lugar de ser únicamente una imagen. Queremos añadir textos, títulos, etc. Es relativamente sencillo de construir gracias a CSS3 con un extra de JavaScript para automatizar el cambio entre ellas y su retardo. Entre sus características:
Demo
Mi título 1
Mi HTML 1
Mi título 2
Mi HTML 2
Mi título 3
Mi HTML 3
Código
El HTML es mínimo. Puedes añadir más diapositivas, o cambiar el HTML dentro del <article>
. Solo debes mantener las clases en su lugar para que coincida con los selectores de JavaScript.
<section class="carousel">
<div class="carousel__container">
<article class="carousel__slider carousel__slider--1">
<h1>Mi título 1</h1>
<p>Mi HTML 1</p>
</article>
<article class="carousel__slider carousel__slider--2">
<h1>Mi título 2</h1>
<p>Mi HTML 2</p>
</article>
<article class="carousel__slider carousel__slider--3">
<h1>Mi título 3</h1>
<p>Mi HTML 3</p>
</article>
</div>
</section>
El CSS solo esta de ejemplo para maquetarlo mínimamente. Estiliza a tu gusto.
:root {
--carousel-height: 20rem;
--carousel-width: 40rem;
}
/* Oculta el scroll horizontal */
.carousel {
height: var(--carousel-height);
overflow: hidden;
width: var(--carousel-width);
}
.carousel__container {
scroll-snap-type: x mandatory;
display: flex;
overflow-x: auto;
}
.carousel__slider {
height: var(--carousel-height);
min-width: var(--carousel-width);
background-repeat: no-repeat;
background-size: cover;
background-position: center;
scroll-snap-align: start;
}
.carousel__slider--1 {
background-image: url("https://source.unsplash.com/featured/1000x400/?fish");
}
.carousel__slider--2 {
background-image: url("https://source.unsplash.com/featured/1000x400/?cat");
}
.carousel__slider--3 {
background-image: url("https://source.unsplash.com/featured/1000x400/?dog");
}
/* Estilos para la demo, pueden ser borrados */
.carousel__slider h1,
.carousel__slider p {
color: white;
text-shadow: 1px 1px 5px black;
}
/* Fin Estilos para la demo, pueden ser borrados */
Dentro del JavaScript te interesa revisar la variables.
// Variables
const SEGUNDOS_ENTRE_DIAPOSITIVAS = 2; // <---- IMPORTANTE
const CAROUSEL = document.querySelector(".carousel");
const SLIDERS = CAROUSEL.querySelectorAll(".carousel__slider");
// Funciones
async function autoPlay(posicionPartida = SLIDERS.length) {
// Obtiene el siguiente indice
const SIGUIENTE_POSICION =
SLIDERS.length - 1 > posicionPartida ? posicionPartida + 1 : 0;
// Mueve el scroll al siguiente slider
SLIDERS[SIGUIENTE_POSICION].scrollIntoView({ block: "center" });
// Retardo antes de volver a ejecutarse
await new Promise((res) => {
setTimeout(res, SEGUNDOS_ENTRE_DIAPOSITIVAS * 1000);
});
// Creamos un objeto IntersectionObserver
observerCarousel = new IntersectionObserver((entries) => {
// Comprobamos todas las intesecciones.
entries.forEach((entry) => {
// Si es observable, entra
if (entry.isIntersecting) {
// Activamos
autoPlay(SIGUIENTE_POSICION)
}
});
});
// Añado a mi Observable que quiero observar. En este caso el carousel
observerCarousel.observe(CAROUSEL);
}
// Ejecuta
autoPlay();
Ejemplo completo
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Ejemplo</title>
<style type="text/css" media="screen">
:root {
--carousel-height: 20rem;
--carousel-width: 40rem;
}
/* Oculta el scroll horizontal */
.carousel {
height: var(--carousel-height);
overflow: hidden;
width: var(--carousel-width);
}
.carousel__container {
scroll-snap-type: x mandatory;
display: flex;
overflow-x: auto;
}
.carousel__slider {
height: var(--carousel-height);
min-width: var(--carousel-width);
background-repeat: no-repeat;
background-size: cover;
background-position: center;
scroll-snap-align: start;
}
.carousel__slider--1 {
background-image: url("https://source.unsplash.com/featured/1000x400/?fish");
}
.carousel__slider--2 {
background-image: url("https://source.unsplash.com/featured/1000x400/?cat");
}
.carousel__slider--3 {
background-image: url("https://source.unsplash.com/featured/1000x400/?dog");
}
/* Estilos para la demo, pueden ser borrados */
.carousel__slider h1,
.carousel__slider p {
color: white;
text-shadow: 1px 1px 5px black;
}
/* Fin Estilos para la demo, pueden ser borrados */
</style>
</head>
<body>
<section class="carousel">
<div class="carousel__container">
<article class="carousel__slider carousel__slider--1">
<h1>Mi título 1</h1>
<p>Mi HTML 1</p>
</article>
<article class="carousel__slider carousel__slider--2">
<h1>Mi título 2</h1>
<p>Mi HTML 2</p>
</article>
<article class="carousel__slider carousel__slider--3">
<h1>Mi título 3</h1>
<p>Mi HTML 3</p>
</article>
</div>
</section>
<script>
// Variables
const SEGUNDOS_ENTRE_SLIDERS = 2; // <---- IMPORTANT
const CAROUSEL = document.querySelector(".carousel");
const SLIDERS = CAROUSEL.querySelectorAll(".carousel__slider");
let observerCarousel;
// Funciones
async function autoPlay(posicionPartida = SLIDERS.length) {
// Elimina los IntersectionObserver para evitar que se reproduzca si no mira el usuario
if(observerCarousel !== undefined) observerCarousel.unobserve(CAROUSEL)
// Obtiene el siguiente indice
const SIGUIENTE_POSICION =
SLIDERS.length - 1 > posicionPartida ? posicionPartida + 1 : 0;
// Mueve el scroll al siguiente slider
SLIDERS[SIGUIENTE_POSICION].scrollIntoView({ block: "center" });
// Retardo antes de volver a ejecutarse
await new Promise((res) => {
setTimeout(res, SEGUNDOS_ENTRE_SLIDERS * 1000);
});
// Ejecutamos el autoPlay únicamente cuando sea visible
// Creamos un objeto IntersectionObserver
observerCarousel = new IntersectionObserver((entries) => {
// Comprobamos todas las intesecciones.
entries.forEach((entry) => {
// Si es observable, entra
if (entry.isIntersecting) {
// Activamos
autoPlay(SIGUIENTE_POSICION)
}
});
});
// Añado a mi Observable que quiero observar. En este caso el carousel
observerCarousel.observe(CAROUSEL);
}
// Ejecuta
autoPlay();
</script>
</body>
</html>
Si quieres un ejemplo sin bloques de HTML y mucho más simple: Sencillo carousel con controles y autoreproducción.
{{ comments.length }} comentarios