AleksandrHovhannisyan/aleksandrhovhannisyan.com

Creating an Accessible Image Carousel

AleksandrHovhannisyan opened this issue · 10 comments

Creating an Accessible Image Carousel

Hi Alexander,

Firstly, great article. There was only one thing I found that wasn't correct in your article.

For improved performance, I’m also using the loading="lazy" attribute to enable native lazy loading, which defers loading images that aren’t currently visible. Once we enable overflow scrolling with CSS in a future section, this will defer loading images that are overflowing horizontally beyond the carousel’s client window.

By setting loading=lazy, all images with this attribute will be loaded later. This should only be applied to images that are offscreen.

Therefore, if you are using the carousel in the first view, this attribute should only be set on the + 4th images. Otherwise it will also defer the loading of images 1, 2 & 3.

Your scroll snap problem is probably also caused by this.

Regards,

Sander van Surksum

@sandersu Thanks for the feedback!

I didn't want to get into the details of how loading="lazy" works to keep the article focused, but to clarify: Browsers use a certain threshold from the viewport to detect whether an image should be loaded into view. You can find the thresholds for Chrome in this article: https://web.dev/browser-level-image-lazy-loading/#distance-from-viewport-thresholds. This also applies to scroll containers.

If the carousel is in view on page load and you inspect the network tab, you should see that only the first two images or so get requested (the bottom two images in the following screenshot):

Inspecting network requests for a page load, with a horizontal image carousel in view. Only two images are requested.

Once you scroll the carousel, the remaining images get requested:

Inspecting network requests for a page load, with a horizontal image carousel in view that has been scrolled to the right. Two additional images are requested.

@sandersu Thanks for the feedback!

I didn't want to get into the details of how loading="lazy" works to keep the article focused, but to clarify: Browsers use a certain threshold from the viewport to detect whether an image should be loaded into view. You can find the thresholds for Chrome in this article: https://web.dev/browser-level-image-lazy-loading/#distance-from-viewport-thresholds. This also applies to scroll containers.

If the carousel is in view on page load and you inspect the network tab, you should see that only the first two images or so get requested (the bottom two images in the following screenshot):

Inspecting network requests for a page load, with a horizontal image carousel in view. Only two images are requested.

Once you scroll the carousel, the remaining images get requested:

Inspecting network requests for a page load, with a horizontal image carousel in view that has been scrolled to the right. Two additional images are requested.

The problem lies in the fact that the browser has to detect whether an image is in the viewport, which takes time. Because the browser has to wait until the IntersectionObserver is available.

Generally, do not lazy load images images visible in the viewport

See this comparison between lazy in viewport vs non lazy in viewport.

https://www.webpagetest.org/video/compare.php?tests=220817_BiDc5N_9MT%2C220817_AiDcGV_9PB&thumbSize=200&ival=100&end=visual

Also see
https://web.dev/browser-level-image-lazy-loading/#avoid-lazy-loading-images-that-are-in-the-first-visible-viewport

Generally, do not lazy load images images visible in the viewport

@sandersu Yup, this is a good point! I had to do that at one point on my own site because Lighthouse was flagging it (LCP images were lazily loaded). If you have control over your carousel (i.e., users aren't uploading dynamic images), and you have control over where on a page it is positioned, it's definitely worth taking this into consideration.

shyke commented

Hi Alexander
Thanks for the wonderful article. It helped me a lot.
I can't seem to find any way to set the initial scrolLeft value on the scrolable container (this.scrollContainer).
The value always stays 0 (RTL), no matter how I set the value in the class. The only solution I could find for it was to change the value in the window.load event listener. However, the result is that the gallery scrolls upon load. This isn't what I want.
Can you please explain how to set the scrollable position of the gallery to the center in the class constructor ?

@shyke I should've probably clarified this in the article, but scrollLeft is a bit of a misnomer in the DOM. It should really be called scrollStart. In RTL, scrollLeft will be 0 if the container has not been scrolled. Once you start scrolling, the values increase in magnitude but will be negative. I'd recommend taking a look at the CodePen demo linked in the article: https://codepen.io/AleksandrHovhannisyan/pen/zYRVoeb.

shyke commented

@shyke Oh, I see. I don't think it's possible to programmatically center the carousel on a particular image initially without the user noticing. There's no CSS solution for this that I know of, so you'd need to scroll to that image on window load like you said.

Hey @AleksandrHovhannisyan Great article!!, I was wondering since you followed the approach of disabling the
previous next buttons , How
would you change the solution to adapt a continous scroll, ie on last image click it scrolls to first and vice-versa

@Pooja22singh I wouldn't recommend taking that approach, as it could confuse users who normally expect the next button to take them to the next image (e.g., an image to the right).