Search code examples
javascriptcssreactjscarouselcumulative-layout-shift

Why the sizes of those images are causing the layout shift? CSS? JavaScript?


https://codesandbox.io/s/stackoverflow2-bdiq2r

I really don't get it why the different sizes of the images are causing the layout shift. I wrote the code considering the difference in size of image for the responsive layout.

The problem is really strange that when you slide the carousel using the button on there, and the whole carousel is inside the viewport, there's no problem. But when you do slide it when part of the carousel is outside the viewport, that layout shift problem occurs.

I've been holding this bug for the whole day already, but really don't know why that size difference is causing the problem in this code, and how to make this work exactly as it is working when the whole carousel is inside the viewport. Is this my React code problem? or my CSS? There's no problem if I set height: 100% for .img but the way of this carousel working gets different.

I attach 2 images to describe the problem more intuitively. enter image description here enter image description here As you can see the carousel gets moved down as soon as you slide to the image of different size (The only purple image has a different size).


Solution

  • It looks like this might be caused by align-items behavior when the images have different natural height.

    In styles.module.css, try set align-items: stretch on .img-container and set object-fit: scale-down on .img to fix this.

    Example: (with live demo on: codesandbox)

    .img-container {
      width: 100%;
      display: flex;
      justify-content: center;
    
      /* 👇 Changed from 'center' to 'stretch' */
      align-items: stretch;
    
      text-align: center;
      position: relative;
      transform: skewY(0.001deg);
      color: white;
      font-weight: bold;
      font-size: 2rem;
    }
    
    .img {
      max-width: 100%;
      max-height: 100%;
    
      /* 👇 Changed from 'contain' to 'scale-down' */
      object-fit: scale-down;
    }