I am working on a React.js/Next.js project using a Sanity headless CMS.
I have a hero element that accepts an array of images but want to be able to cycle through this automatically to create a background slider effect. I was tempted to use a slick slider or similar but would like to try and do this with pure CSS if possible as the webpack config for the project doesn't make importing external css files very easy.
My component...
import React from "react";
import PropTypes from "prop-types";
import styles from "./Hero.module.css";
import client from "../../client";
import SimpleBlockContent from "../SimpleBlockContent";
import Cta from "../Cta";
import imageUrlBuilder from "@sanity/image-url";
const builder = imageUrlBuilder(client);
function Hero(props) {
const { heading, image, tagline, ctas } = props;
const images = props.image;
return (
<div className={styles.root}>
<div className={styles.content}>
<h1 className={styles.title}>{heading}</h1>
<div className={styles.tagline}>{tagline && <SimpleBlockContent blocks={tagline} />}</div>
<div>
{images.map((image) => (
<img
className={styles.image}
src={builder.image(image).url()}
className={styles.image}
alt={heading}
/>
))}
</div>
</div>
</div>
);
}
Hero.propTypes = {
heading: PropTypes.string,
backgroundImage: PropTypes.object,
tagline: PropTypes.array,
ctas: PropTypes.arrayOf(PropTypes.object),
};
export default Hero;
My CSS
@import "../../styles/custom-properties.css";
.root {
composes: center from "../../styles/shared.module.css";
position: relative;
color: var(--color-white, #fff);
background: none;
padding-bottom: 2rem;
@media (--media-min-medium) {
padding-bottom: 1rem;
}
}
.content {
width: 100vw;
min-height: 100vh;
padding: 0 1.5em;
box-sizing: border-box;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
}
.image {
position: absolute;
z-index: -1;
left: 0;
top: 0;
overflow: hidden;
display: block;
width: 100vw;
height: 100vh;
object-fit: cover;
animation: fade 2s infinite;
}
.title {
text-align: center;
text-transform: uppercase;
letter-spacing: 2px;
position: relative;
font-weight: 300;
font-size: var(--font-title2-size);
line-height: var(--font-title2-line-height);
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
margin: 0;
padding: 0;
@media (--media-min-medium) {
font-size: var(--font-title1-size);
line-height: var(--font-title1-line-height);
padding-top: 0;
}
}
@keyframes fade {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
This code does fade the first image in the array in and out but doesn't effect the other images, which are 'sitting' behind the first one.
Hope that makes sense, any help would be appreciated!
EDIT - Simplified StackBlitz Mock Up