{"id":18922,"library":"vue-use-active-scroll","title":"vue-use-active-scroll","description":"Vue 3 composable for accurate TOC/sidebar active link tracking without Intersection Observer compromises. Current stable version 1.1.3 (released 2024). Zero runtime dependencies, ships TypeScript types. Unlike typical Intersection Observer solutions, it implements a custom scroll observer that reliably highlights clicked links that never intersect, handles first/last link at page boundaries, and works consistently across scroll speeds, smooth scrolling, and hash navigation. Supports template refs or DOM elements in place of IDs, customizable offsets per scroll direction, and custom scroll containers. Does not scroll to targets or manipulate DOM. Released on npm with monthly cadence.","status":"active","version":"1.1.3","language":"javascript","source_language":"en","source_url":"https://github.com/smastrom/vue-use-active-scroll","tags":["javascript","vue","vue3","vue-scroll","vue-scroll-active","vue-active-scroll","vue-active-link","vue-toc","typescript"],"install":[{"cmd":"npm install vue-use-active-scroll","lang":"bash","label":"npm"},{"cmd":"yarn add vue-use-active-scroll","lang":"bash","label":"yarn"},{"cmd":"pnpm add vue-use-active-scroll","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"ESM-only. The package does not provide a CommonJS entry.","wrong":"const useActiveScroll = require('vue-use-active-scroll')","symbol":"useActiveScroll","correct":"import { useActiveScroll } from 'vue-use-active-scroll'"},{"note":"This is a named export, not a default export. Both 'use-active-scroll' (kebab-case) and 'UseActiveScroll' (PascalCase) will not work.","wrong":"import useActiveScroll from 'vue-use-active-scroll'","symbol":"useActiveScroll","correct":"import { useActiveScroll } from 'vue-use-active-scroll'"},{"note":"Exported as a PascalCase ref for use in templates, but import name is camelCase. Also available via return from useActiveScroll.","wrong":"import { IsActive } from 'vue-use-active-scroll'","symbol":"isActive","correct":"import { isActive } from 'vue-use-active-scroll'"}],"quickstart":{"code":"<template>\n  <nav>\n    <a\n      v-for=\"item in items\"\n      :key=\"item.id\"\n      :href=\"'#' + item.id\"\n      :class=\"{ active: activeId === item.id }\"\n    >\n      {{ item.title }}\n    </a>\n  </nav>\n  <main>\n    <section v-for=\"item in items\" :key=\"item.id\" :id=\"item.id\">\n      <h2>{{ item.title }}</h2>\n      <p>{{ item.content }}</p>\n    </section>\n  </main>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { useActiveScroll } from 'vue-use-active-scroll'\n\nconst items = [\n  { id: 'introduction', title: 'Introduction', content: '...' },\n  { id: 'installation', title: 'Installation', content: '...' },\n  { id: 'usage', title: 'Usage', content: '...' },\n]\n\n// Array of target IDs (strings, no hash prefix)\nconst targetIds = items.map((item) => item.id)\n\nconst { activeId } = useActiveScroll(targetIds, {\n  offset: { top: 80, bottom: 80 },\n  firstTopMargin: 100,\n  lastBottomMargin: 100,\n})\n</script>","lang":"typescript","description":"Basic example: track active section based on scroll position and highlight a sidebar link accordingly."},"warnings":[{"fix":"Add scrollBehavior(to) { if (to.hash) return { el: to.hash } } to your Vue Router instance.","message":"Vue Router is required for hash-based scrolling unless using Nuxt. Without configuring scrollBehavior in createRouter({...}), clicking hash links may not scroll to the target element.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Add 'html { scroll-behavior: smooth; }' in your global CSS.","message":"CSS scroll-behavior must be set on html element (e.g., scroll-behavior: smooth) for smooth scrolling. If omitted, scrolling jumps instantly and active highlight may feel abrupt.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"No action needed if using string IDs. If using refs, ensure they are valid TemplateRef or HTMLElement.","message":"Version 1.1.0 changed target API: targets can now be set using template refs or DOM elements in place of IDs. If you previously relied on string IDs only, this is backward-compatible, but passing refs now works differently.","severity":"breaking","affected_versions":">=1.1.0"},{"fix":"Access activeId.value in script setup or composition functions.","message":"The activeId returned is a Ref<string | null>, not a plain string. In templates it auto-unwraps, but in script you must use .value.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Import useActiveScroll and destructure isActive from its return, or upgrade to >=1.1.1.","message":"The export 'isActive' is deprecated since v1.1.1? Actually 'isActive' is still exported but also available via useActiveScroll return. There is no deprecation notice, but note that using isActive alone might not work in SSR (fixed in 1.1.1).","severity":"deprecated","affected_versions":">=1.0.0 <1.1.1"}],"env_vars":null,"last_verified":"2026-04-25T00:00:00.000Z","next_check":"2026-07-24T00:00:00.000Z","problems":[{"fix":"Add scrollBehavior(to) { if (to.hash) return { el: to.hash } } to createRouter({...}).","cause":"Vue Router scrollBehavior not configured or to.hash undefined when clicking a hash link.","error":"Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'hash')"},{"fix":"Use import { useActiveScroll } from 'vue-use-active-scroll' instead of import useActiveScroll from 'vue-use-active-scroll'.","cause":"Using a default import instead of named import.","error":"useActiveScroll is not a function"},{"fix":"Run npm install vue-use-active-scroll (or pnpm/yarn/bun add) and ensure tsconfig includes node_modules/@types.","cause":"Package not installed or TypeScript cannot resolve types.","error":"Cannot find module 'vue-use-active-scroll' or its corresponding type declarations."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}