{"id":15334318,"url":"https://github.com/gerhardsletten/use-snap-slider","last_synced_at":"2026-01-07T02:30:31.294Z","repository":{"id":150650523,"uuid":"623191318","full_name":"gerhardsletten/use-snap-slider","owner":"gerhardsletten","description":"React hook / Vanilla JS to manage scroll-state for CSS Scroll Snap","archived":false,"fork":false,"pushed_at":"2024-02-14T11:48:18.000Z","size":609,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-03-15T12:12:22.321Z","etag":null,"topics":["carusel","react","react-hooks","scroll-snap","slider"],"latest_commit_sha":null,"homepage":"https://use-snap-slider.vercel.app/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gerhardsletten.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-03T22:04:05.000Z","updated_at":"2024-05-02T14:12:44.392Z","dependencies_parsed_at":"2024-05-02T14:12:13.829Z","dependency_job_id":"53daf5b9-0be1-48a9-830b-d177b919ff29","html_url":"https://github.com/gerhardsletten/use-snap-slider","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerhardsletten%2Fuse-snap-slider","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerhardsletten%2Fuse-snap-slider/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerhardsletten%2Fuse-snap-slider/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerhardsletten%2Fuse-snap-slider/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gerhardsletten","download_url":"https://codeload.github.com/gerhardsletten/use-snap-slider/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245898314,"owners_count":20690466,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["carusel","react","react-hooks","scroll-snap","slider"],"created_at":"2024-10-01T10:06:46.485Z","updated_at":"2026-01-07T02:30:31.216Z","avatar_url":"https://github.com/gerhardsletten.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# use-snap-slider\n\nReact hook / Vanilla JS to manage scroll-state for [CSS Scroll Snap](https://caniuse.com/?search=scroll-snap)\n\n![](https://img.shields.io/bundlephobia/min/use-snap-slider)\n\nGives you states and actions for CSS Scroll Snap sliders:\n\n* `count:number` - total pages\n* `countDelta:number` - total slides, for 1/1 width slides the same as count\n* `index:number` - current page index\n* `indexDelto:number` - current slide index, for 1/1 width slides the same as index\n* `prevEnabled:boolean` - can go to previous slide\n* `nextEnabled:boolean` - can go to next slide\n* `goPrev()` - scroll to previous slide\n* `goNext()` - scroll to next slide\n* `jumpTo(index:number)` - go to a spesified slide\n\n## Usage\n\n`npm i use-snap-slider`\n\n### Basic usage (react)\n\nIn your react component:\n\nSee a [more complete react-example here](https://github.com/gerhardsletten/use-snap-slider/blob/main/src/react-example/SnapSliderReact.tsx)\n\n```tsx\nimport React, { useRef } from 'react'\nimport { useSnapSlider } from 'use-snap-slider'\n\nexport function MySlider () {\n  const ref = useRef\u003cHTMLDivElement | null\u003e(null)\n  const slides = [1,2]\n  // Passing inital count avoid extra render, for best lighthouse score, pass the same count as you show on mobile\n  const {index, count, jumpTo, goPrev, goNext, prevEnabled, nextEnabled} = useSnapSlider(ref, slides.length)\n  const pages = Array.from(Array(count).keys())\n  return (\n    \u003cdiv\u003e\n      \u003cdiv className=\"flex scroll-smooth snap-x snap-mandatory overflow-x-auto\" ref={ref}\u003e\n        {slides.map((slide) =\u003e (\n          \u003cdiv key={slide} className=\"flex snap-start shrink-0 w-full md:w-1/2\"\u003e\n            Slide {slide}\n          \u003c/div\u003e\n        ))}\n      \u003c/div\u003e\n      \u003cnav aria-label=\"Pages navigation\"\u003e\n        {pages.map((page) =\u003e (\n          \u003cbutton onClick={() =\u003e jumpTo(page)} disabled={page === index}\u003e{page + 1}\u003c/button\u003e\n        ))}\n      \u003c/nav\u003e\n      \u003cnav aria-label=\"Prev / Next navigation\"\u003e\n        \u003cbutton onClick={goPrev} disabled={!prevEnabled}\u003ePrev\u003c/button\u003e\n        \u003cbutton onClick={goNext} disabled={!nextEnabled}\u003eNext\u003c/button\u003e\n      \u003c/nav\u003e\n    \u003c/div\u003e\n  )\n}\n```\n\n### Basic usage (vanilla javascript)\n\nSee a [more complete vanilla javascript example here](https://github.com/gerhardsletten/use-snap-slider/blob/main/src/vanilla-example/create-snap-slider.ts)\n\n```ts\nimport { createSnapSlider } from 'use-snap-slider/dist/snap-slider'\n\nfunction createSnapSliderVanilla(element: HTMLElement) {\n  const { jumpTo, goNext, goPrev, subscribe } = createSnapSlider({\n    element,\n    count: count,\n    index: 0,\n  })\n  subscribe((state) =\u003e {\n    // Update UI with sate\n  })\n  document.querySelector('.prev-btn')?.addEventListener('click', goPrev)\n  document.querySelector('.next-btn')?.addEventListener('click', goNext)\n}\n// Expose globally\nwindow.createSnapSliderVanilla = createSnapSliderVanilla\n```\n\n## API\n\n### useSnapSlider react hook\n\n```ts\nimport { useSnapSlider } from 'use-snap-slider'\n\nconst {\n  index: number,\n  // If displaying multiple slides on the same page, this will be slide at left position\n  indexDelta: number,\n  // Count of pages\n  count: number,\n  countDelta: number,\n  prevEnabled: boolean,\n  nextEnabled: boolean,\n  jumpTo: (index: number) =\u003e void,\n  goNext: () =\u003e void,\n  goPrev: () =\u003e void,\n} = useSnapSlider(\n  ref: MutableRefObject\u003cHTMLDivElement | null\u003e,\n  // Pass inital count\n  count?: number = 1,\n  // Pass inital index\n  index?: number = 0,\n  // onPrev / next buttons go to end / start \n  circular = false,\n  // Will reset index on change of count, but pass something here to force a reset even if count dont change\n  countHash?: string | number\n)\n```\n\n### createSnapSlider vanilla js function\n\n```ts\nimport { createSnapSlider } from 'use-snap-slider/dist/snap-slider'\n\nconst {\n  // Removes event listner for window.resize and element.scroll\n  destroy: () =\u003e void,\n  // Get current state\n  getState: () =\u003e TSnapSliderStateFull,\n  // Go to slide index\n  jumpTo: (index?: number, indexDelta?: number) =\u003e void,\n  goNext: () =\u003e void,\n  goPrev: () =\u003e void,\n  // Subscribe to updates\n  subscribe: (fn: TSnapListner) =\u003e () =\u003e void,\n  // Set element at later stage\n  setElement: (el: HTMLElement) =\u003e void,\n  // Updates count and countDelta, call if you change inner slides\n  calculate: () =\u003e void,\n  // Should subscribe return a inital publish after subscribing\n  initalSubscriptionPublish: boolean = true\n} = createSnapSlider({\n  element: HTMLDivElement | null,\n  count?:number = 1,\n  countDelta?:number,\n  index?:number = 0,\n  circular?:boolean,\n  indexDelta?:number,\n  itemSelector?:string = ':scope \u003e *',\n})\n```\n\n## Adding nessesary styles\n\nThis library only delivers javascript for handle the state, you will need to make your own component for complete solution. See examples in this repo: \n\n* [React component](https://github.com/gerhardsletten/use-snap-slider/blob/main/src/react-example/SnapSliderReact.tsx)\n* [Vanilla JS function](https://github.com/gerhardsletten/use-snap-slider/blob/main/src/vanilla-example/create-snap-slider.ts)\n\n### TailwindCSS\n\nSee also tailwinds own documentation for [scroll snap](https://tailwindcss.com/docs/scroll-snap-type)\n\n```html\n\u003cdiv class=\"flex scroll-smooth snap-x snap-mandatory overflow-x-auto\"\u003e\n  \u003cdiv class=\"flex snap-start shrink-0\"\u003e\n    Slide 1\n  \u003c/div\u003e\n  \u003cdiv class=\"flex snap-start shrink-0\"\u003e\n    Slide 2\n  \u003c/div\u003e\n\u003c/div\u003e\n```\n\n### Basic css\n\n```html\n\u003cstyle\u003e\n.css-slider {\n  display: flex;\n  overflow-x: auto;\n  scroll-snap-type: x mandatory;\n  scroll-behavior: smooth;\n  -webkit-overflow-scrolling: touch;\n}\n.css-slider::-webkit-scrollbar {\n  display: none;\n}\n.css-slider-item {\n  display: flex;\n  scroll-snap-align: start;\n  flex-shrink: 0;\n}\n.css-slider-item-half {\n  width: 50%;\n}\n\u003c/style\u003e\n\u003c!-- Markup --\u003e\n\u003cdiv class=\"css-slider\"\u003e\n  \u003cdiv class=\"css-slider-item css-slider-item-half\"\u003e\n    Slide 1\n  \u003c/div\u003e\n  \u003cdiv class=\"css-slider-item css-slider-item-half\"\u003e\n    Slide 2\n  \u003c/div\u003e\n\u003c/div\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgerhardsletten%2Fuse-snap-slider","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgerhardsletten%2Fuse-snap-slider","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgerhardsletten%2Fuse-snap-slider/lists"}