DEV Community

Cover image for Creating practical Instagram-like galleries and horizontal lists with CSS scroll snapping

Creating practical Instagram-like galleries and horizontal lists with CSS scroll snapping

Joost Kiens on May 05, 2020

What's the difference between carousels and horizontally scrollable lists? Is it the gestures, snapping, or the number of visible items? They are v...
Collapse
 
jordachelouis profile image
Jordan

This is so great Joost, thank you! I'm new to JS and am looking to implement your gallery with indicators to display multiple carousels on a single webpage. The indicators were only working on the very first gallery, so I modified the "const list" to look at all lists. To ensure the first indicator on all galleries was selected at page load, I also added the .active class to the first indicator in html to serve as a default. This all "works", but as you scroll the indicators start to disappear and reappear. Was I on the right track or do you have any recommendations?

const lists = Array.from(document.querySelectorAll(".list"));
Enter fullscreen mode Exit fullscreen mode
<div class="indicatorsList" aria-hidden>
    <div class="indicator active"></div>
    <div class="indicator"></div>
    <div class="indicator"></div>
</div>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
elissavettriant profile image
Elissavet Triantafyllopoulou

Hello Joost and thank you!

So, I wanted to make a horizontal slider/carousel using the Intersection Observer API and came across your article.

I think this solution is really neat and can work even in production with a polyfill.

This is my testing demo: codepen.io/elisavetTriant/pen/OJWvOyr, which is actually for a CodePen challenge named "Scrolling Microinteraction" (codepen.io/challenges/2021/april/2)

I tried to make it work with responsive settings on the container/wrapper element so I made some adjustments on the observer callback function.

Collapse
 
joostkiens profile image
Joost Kiens

Nice work!

Collapse
 
electrifried profile image
Jaclyn Tan

Do you think it would be easy enough to add click events to the indicators or arrows to this implementation? To allow for the people that don't have magic mice or touch screens...

Collapse
 
joostkiens profile image
Joost Kiens • Edited

Yeah, of course! The indicators are easiest: if we know the index of the clicked indicator, we can tell the corresponding item to scrollIntoView.

indicators.forEach((x, i) =>
  x.addEventListener("click", () =>
    items[i].scrollIntoView({ inline: "start", behavior: "smooth" })
  )
);
Enter fullscreen mode Exit fullscreen mode

For the arrows we could keep track of the current active index:

const state = { active: 0 };
//...

function activateIndicator(index) {
  state.active = index;
  indicators.forEach((indicator, i) => {
    indicator.classList.toggle("active", i === state.active);
  });
}
Enter fullscreen mode Exit fullscreen mode

and scrollIntoView the prev or next one.

prev.addEventListener("click", () => {
  items[state.active - 1]?.scrollIntoView({
    inline: "start",
    behavior: "smooth"
  });
});

next.addEventListener("click", () => {
  items[state.active + 1]?.scrollIntoView({
    inline: "start",
    behavior: "smooth"
  });
});
Enter fullscreen mode Exit fullscreen mode

But the options of scrollIntoView are not supported by Safari 🙁. So no smooth scrolling.
We can add a polyfill, and it works across modern browsers:

<script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver,Element.prototype.scrollIntoView"></script>
Enter fullscreen mode Exit fullscreen mode

I made a quick demo.

Collapse
 
electrifried profile image
Jaclyn Tan

Ohh that is so cool. Thanks so much for the demo I really appreciate it!

Collapse
 
allmerovi profile image
Allmerovi

Hi, thak You werry much to stih solution. I ask You for help. It perfecty run on separate page Original But if I try to use this solution on my pension page Pension page indicators and prev and next buttons stop work after sirts clicking and do not run until i roll the page. After that it work 1 step and another page rolling is needed. Can You help me? Prese. If I have to send You the source, write me. Thanks.

Collapse
 
shtep profile image
jim shtepa • Edited

Hello Joost, thank you for the detailed step by step tutorial. I tried to reimplement the arrow button to scroll horizontally but am struggling to make it work. If you have 2 mins, could you please help to understand what I am doing wrong? here is the link to source code

Collapse
 
lyunya profile image
lyunya

hey Joost,

This is exactly what I was looking for! Thank you! I'm trying to implement the arrow buttons for desktop, but having some difficulty since i'm building this in react. Do you know of an easy way to implement this solution in react?

Collapse
 
codesandtags profile image
Edwin Torres

Heyyy Joost! Really nice your examples. :D I don't know if it is for the sandbox the I had to use the keys (left-right) to scroll it.

Cheers!

Collapse
 
joostkiens profile image
Joost Kiens

Hi Edwin, thanks so much for letting me know🙏!

They should be fine now😅