Need help with react-horizontal-scrolling-menu?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

439 Stars 66 Forks MIT License 251 Commits 0 Opened issues


Horizontal scrolling menu component for React.

Services available


Need anything else?

Contributors list

# 137,666
237 commits

React horizontal scrolling menu


npm Tests codebeat badge Codacy Badge Commitizen friendly npm bundle size (minified + gzip) Donate

Proud corner

performance-dashboard-on-aws | React status code



Basic example

Hidden scrollbar and arrows on bottom

Select item

Drag by mouse

Click and select multiple items

Scroll by 1 item

Center item

Dynamically add items when last is visible

apiRef - controling component outside

Add item and scroll to it

Previous version V1

This is a horizontal scrolling menu component for React. Menu component has adaptive width, just set width for parent container. Items width will be determined from CSS styles.

For navigation, you can use scrollbar, native touch scroll, mouse wheel or drag by mouse.

Component provide context with visible items and helpers.

Possible set default position on initialization.

:star: if you like the project :)

Quick start

yarn add react-horizontal-scrolling-menu

In project: ```javascript import React from "react"; import { ScrollMenu, VisibilityContext } from "react-horizontal-scrolling-menu";

const getItems = () => Array(20) .fill(0) .map((_, ind) => ({ id:


function App() { const [items, setItems] = React.useState(getItems); const [selected, setSelected] = React.useState([]); const [position, setPosition] = React.useState(0);

const isItemSelected = (id) => !!selected.find((el) => el === id);

const handleClick = (id) => ({ getItemById, scrollToItem }) => { const itemSelected = isItemSelected(id)

setSelected((currentSelected) =>
    ? currentSelected.filter((el) => el !== id)
    : currentSelected.concat(id)


return ( {{ id }) => ( ) )}


); }

function LeftArrow() { const { isFirstItemVisible, scrollPrev } = React.useContext(VisibilityContext)

return ( scrollPrev()}> Left ); }

function RightArrow() { const { isLastItemVisible, scrollNext } = React.useContext(VisibilityContext)

return ( scrollNext()}> Right ); }

function Card({ onClick, selected, title, itemId }) { const visibility = React.useContext(VisibilityContext)

return (

onClick(visibility)} style={{ width: "160px", }} tabIndex={0} >
visible: {JSON.stringify(!!visibility.isItemVisible(itemId))}
selected: {JSON.stringify(!!selected)}
); }

export default App; ```

Check out Example in

folder for info how to implement more features like mouse drag or disable body scroll.


You can clone repository and run demo project.

git clone
yarn install
yarn run demo

Helpers and api

Children of main ScrollMenu component can use VisibilityContext to access state and callbacks. Function callbacks also pass context, eg


Properties and callbacks


LeftArrow React component for left arrow
RightArrow React component for right arrow
onWheel (VisibilityContext, event) => void
onScroll (VisibilityContext, event) => void
onInit (VisibilityContext) => void
apiRef React.RefObject
onUpdate (VisibilityContext) => void
onMouseDown (VisibilityContext) => (React.MouseEventHandler) => void
onMouseUp (VisibilityContext) => (React.MouseEventHandler) => void
onMouseMove (VisibilityContext) => (React.MouseEventHandler) => void
itemClassName ClassName of Item
separatorClassName ClassName of Item's separator
scrollContainerClassName ClassName of scrollContainer
wrapperClassName ClassName of the outer-most div



getItemById itemId => IOItem
getItemElementById itemId => DOM Element
getItemByIndex index => IOItem
getItemElementByIndex index => DOM Element
getNextItem () => IOItem
getPrevItem () => IOItem
initComplete boolean
isFirstItemVisible boolean
isItemVisible itemId => boolean
isLastItem boolean
isLastItemVisible boolean
scrollNext (behavior, inline, block) => void
scrollPrev (behavior, inline, block) => void
scrollToItem (item, behavior, inline, block) => void
visibleItemsWithoutSeparators ['item1', 'item2']
initComplete boolean
items ItemsMap class instance
scrollContainer Ref
visibleItems ['item1', 'item1-separator', 'item2']

Other helpers


Can get previous or next visible group of items with

slidingWindow(allItems: string[], visibleItems: string[])
helper, e.g
slidingWindow(allItems, visibleItems)


Can get first, center and last items, e.g. ``` const prevGroup = slidingWindow(allItems, visibleItems).prev() const { first, center: centerItem, last } = getItemsPos(prevGroup)

// and scroll to center item of previous group of items scrollToItem(getItemById(centerItem, 'smooth', 'center'))

Check out [examples](#examples)


Can pass Ref object to Menu, current value will assigned as VisibilityContext. But visibleItems and some other values can be staled, so better use it only for firing functions like scrollToItem.

For scrolling use apiRef.scrollToItem(apiRef.getItemElementById) instead of apiRef.scrollToItem(apiRef.getItemById).

Can get item outside of context via apiRef.getItemElementById(id) or directly via document.querySelector(`[data-key='${itemId}']`). See apiRef example and Add item and scroll to it

Browser support

  • Browser must support IntersectionObserver API, Element.scrollIntoView for Safari and requestAnimationFrame or use polyfills.
  • Only modern browsers, no IE or smart toasters


My first npm project. Sorry for my english.

Any contribution and correction appreciated. Just fork repo, commit and make PR, don't forget about tests.



We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.