I'm working on a Next.js project and implementing a carousel that spans the full width of the page, and shows media at either 30vw or 50vw, depending on the asset's aspect ratio. Here is a good reference for something similar to what I'm trying to achieve.
While the fully visible assets load without any issues, I'm experiencing a layout shift on load. The upcoming images initially load below the carousel and then snap into position, causing the carousel to flicker and shift.
Here are the details of my setup:
- Fully visible images load without any layout shift.
- On load, upcoming images start loading below the carousel, then snap into position, causing a flicker effect.
- I'm using custom Next image and video components to set the size of each item based on its aspect ratio to prevent layout shifting. They are lazy loaded
Any suggestions on how to prevent this layout shift and ensure smooth loading of images in the carousel would be greatly appreciated.
Thank you!
My carousel component:
"use client";import "slick-carousel/slick/slick.css";import "slick-carousel/slick/slick-theme.css";import { ReactNode, useRef } from "react";import Slider, { Settings } from "react-slick";import cn from "classnames";import styles from "./carousel.module.css";import React from "react";const carouselSettings: Settings = { infinite: true, variableWidth: true, autoplay: false, swipe: true, arrows: false, accessibility: true, swipeToSlide: true,};type ProjectCarouselProps = { children: ReactNode;};export const ProjectCarousel = ({ children }: ProjectCarouselProps) => { const sliderRef = useRef<Slider>(null); const handleSlideClick = (index: number) => { if (sliderRef.current) { sliderRef.current.slickGoTo(index); } }; return (<Slider {...carouselSettings} className={cn(styles.slideshow)} ref={sliderRef}> {React.Children.map(children, (child, index) => (<div key={index} className={cn(styles.slideshow__slide)} onClick={() => handleSlideClick(index)}> {child}</div> ))}</Slider> );};
and the CSS:
.slideshow { display: flex; overflow: hidden;}.slideshow__slide { flex-shrink: 0; width: 100%;}