The basics: display: flex plus overflow-x: auto, with every child set to flex: 0 0 auto — never shrinking, never growing, always its own size. Without flex-wrap, items never drop to a new line, so once their combined width exceeds the container, the overflow becomes horizontal scroll.
Add scroll-snap-type: x mandatory to the parent and scroll-snap-align: start to each child, and scrolling comes to rest exactly on an item boundary — no drag or swipe stops halfway. The scrollbar itself is commonly hidden with scrollbar-width: none (Firefox) and ::-webkit-scrollbar { display: none } (Chromium), replaced by a mask-image gradient at both edges that hints "there's more to scroll" without a visible bar.
A vertical reel — a stories list, say — works the same way with the axis flipped. Since keyboard and screen-reader users still need to reach every item one at a time, anything beyond a purely decorative carousel needs each item to be a focusable element (a link or a button), or the pattern quietly breaks accessibility.
When to use
Good for recommendation rails, category tabs, or gallery thumbnails — item counts that vary and don't all need to be visible at once. Not a fit for core navigation where every item must always be seen.