I am new to web development and I'm learning to use React and Tailwind.
I am trying to do the "About us" section that should be made in the following way.
There are two components: a slideshow of images that automatically change every second and a paragraph with some text.
The two should be arranged like this:
This is the code I have at the moment. It works but there is a problem: it seems like for case 2, it is not understanding correctly the height of the slideshow so the paragraph text is going on top of the slideshow images.
Is there any way to solve this? Thanks.
const [currentSlide, setCurrentSlide] = useState(0);
useEffect(() => {
const interval2 = setInterval(() => {
setCurrentSlide((prevSlide) =>
prevSlide === images.length - 1 ? 0 : prevSlide + 1
);
}, 3000);
return () => {
clearInterval(interval2);
};
}, []);
<div className="grid grid-cols-1 grid-rows-2 lg:grid-rows-1 lg:grid-cols-2 w-full">
{/* Images */}
<div className="images lg:order-1" data-aos="fade-up">
<div className="relative">
{images.map((image, index) => (
<div
key={image.id}
className={`absolute top-0 left-0 w-full h-full transition-opacity duration-1000 ${
index === currentSlide ? "opacity-100" : "opacity-0"
}`}
>
<img src={image.img} className="rounded-md" alt="" />
</div>
))}
</div>
</div>
{/* About us */}
<div className="lg:order-2 lg:mt-0 mx-auto space-y-4 lg:w-3/4 text-black" data-aos="fade-up">
<h2 className="text-2xl font-semibold"> Title</h2>
<p className="text-justify lg:text-start">
About us 1.
</p>
<p className="text-justify lg:text-start">
About us 2.
</p>
<p className="text-justify lg:text-start">
About us 3.
</p>
</div>
</div>
The div.relative
element has 0
height, since all elements inside have position: absolute
. If all the images are the same size, you could consider not applying position: absolute
to the first image. This then gives layout rectangle spacing, ensuring the text flows below the slider.
const { useEffect, useState } = React;
const images = [
{ img: 'https://picsum.photos/1920/1080' },
{ img: 'https://picsum.photos/1920/1080?' },
{ img: 'https://picsum.photos/1920/1080?0' },
];
function App() {
const [currentSlide, setCurrentSlide] = useState(0);
useEffect(() => {
const interval2 = setInterval(() => {
setCurrentSlide((prevSlide) =>
prevSlide === images.length - 1 ? 0 : prevSlide + 1,
);
}, 3000);
return () => {
clearInterval(interval2);
};
}, []);
return (
<div className="grid grid-cols-1 grid-rows-2 lg:grid-rows-1 lg:grid-cols-2 w-full">
{/* Images */}
<div className="images lg:order-1" data-aos="fade-up">
<div className="relative">
{images.map((image, index) => (
<div
key={image.id}
className={`top-0 left-0 w-full h-full transition-opacity duration-1000 ${
index === currentSlide ? 'opacity-100' : 'opacity-0'
} ${index > 0 ? 'absolute' : ''}`}
>
<img src={image.img} className="rounded-md" alt="" />
</div>
))}
</div>
</div>
{/* About us */}
<div
className="lg:order-2 lg:mt-0 mx-auto space-y-4 lg:w-3/4 text-black"
data-aos="fade-up"
>
<h2 className="text-2xl font-semibold"> Title</h2>
<p className="text-justify lg:text-start">About us 1.</p>
<p className="text-justify lg:text-start">About us 2.</p>
<p className="text-justify lg:text-start">About us 3.</p>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById('app')).render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.tailwindcss.com/3.4.3"></script>
<div id="app"></div>