OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

How to Prevent Layout Shift When Loading Images?

  • Thread starter Thread starter specialtygirl
  • Start date Start date
S

specialtygirl

Guest
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:

Code:
"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:

Code:
.slideshow {
  display: flex;
  overflow: hidden;
}

.slideshow__slide {
  flex-shrink: 0;
  width: 100%;
}
<p>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. <a href="https://www.fycartists.com/kent-andreasen" rel="nofollow noreferrer">Here is a good reference</a> for something similar to what I'm trying to achieve.</p>
<p>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.</p>
<p>Here are the details of my setup:</p>
<ul>
<li>Fully visible images load without any layout shift.</li>
<li>On load, upcoming images start loading below the carousel, then snap into position, causing a flicker effect.</li>
<li>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</li>
</ul>
<p>Any suggestions on how to prevent this layout shift and ensure smooth loading of images in the carousel would be greatly appreciated.</p>
<p>Thank you!</p>
<p>My carousel component:</p>
<pre><code>"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>
);
};

</code></pre>
<p>and the CSS:</p>
<pre><code>.slideshow {
display: flex;
overflow: hidden;
}

.slideshow__slide {
flex-shrink: 0;
width: 100%;
}

</code></pre>
Continue reading...
 

Latest posts

Top