{"id":12585,"library":"vue-sticky-directive","title":"Vue Sticky Directive","description":"This package provides a Vue.js directive, `v-sticky`, designed to make elements \"sticky\" within their designated container, mimicking the CSS `position: sticky` behavior. It enables configurable sticky effects through various attributes such as `sticky-offset` (allowing top and bottom breakpoints), `sticky-side` (to specify sticking to the top, bottom, or both), and `sticky-z-index` for layer control. Additionally, it offers an `on-stick` callback function that notifies when an element's sticky state changes. The current version, 0.0.10, indicates it's an early-stage project. While its release cadence isn't explicitly defined, the versioning suggests a more cautious release cycle, with the last known commit in May 2021. A key differentiator is its straightforward, directive-based API for Vue 2 applications, providing a robust solution for contextual sticky elements that can be scoped to a specific `sticky-container` rather than just the viewport.","status":"maintenance","version":"0.0.10","language":"javascript","source_language":"en","source_url":"https://github.com/mehwww/vue-sticky-directive","tags":["javascript","vue","sticky","typescript"],"install":[{"cmd":"npm install vue-sticky-directive","lang":"bash","label":"npm"},{"cmd":"yarn add vue-sticky-directive","lang":"bash","label":"yarn"},{"cmd":"pnpm add vue-sticky-directive","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required peer dependency for the directive to function within a Vue 2 application.","package":"vue","optional":false}],"imports":[{"note":"This package exports `Sticky` as a default export for direct consumption. It is primarily designed for Vue 2 applications. Using named imports like `{ Sticky }` will fail.","wrong":"import { Sticky } from 'vue-sticky-directive'","symbol":"Sticky","correct":"import Sticky from 'vue-sticky-directive'"},{"note":"While CommonJS `require` might work with specific build configurations, modern Vue 2 projects primarily use ESM `import`. The import statement for local component registration is the same as for global registration.","wrong":"const Sticky = require('vue-sticky-directive')","symbol":"Sticky (for local registration)","correct":"import Sticky from 'vue-sticky-directive'"},{"note":"The directive is applied using `v-sticky`. Options like `sticky-offset` are passed as separate attributes, typically bound using `v-bind` (shorthand `:`) for dynamic values or expressions, not directly as the value of `v-sticky` unless disabling it conditionally.","wrong":"<div :sticky=\"{ top: 10 }\"></div>","symbol":"v-sticky","correct":"<div v-sticky sticky-offset=\"{ top: 10 }\"></div>"}],"quickstart":{"code":"<template>\n  <div id=\"app\">\n    <header>\n      <h1>My Awesome Page</h1>\n      <p>Scroll down to see the sticky navigation!</p>\n    </header>\n    <div class=\"content-wrapper\" sticky-container>\n      <nav v-sticky sticky-offset='{ top: 0 }' sticky-side=\"top\" sticky-z-index=\"10\" :on-stick=\"handleStickChange\">\n        <ul>\n          <li><a href=\"#section1\">Section 1</a></li>\n          <li><a href=\"#section2\">Section 2</a></li>\n          <li><a href=\"#section3\">Section 3</a></li>\n        </ul>\n      </nav>\n      <main>\n        <section id=\"section1\">\n          <h2>Section 1</h2>\n          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>\n          <p>...</p>\n        </section>\n        <section id=\"section2\">\n          <h2>Section 2</h2>\n          <p>Another long section to demonstrate scrolling.</p>\n          <p>...</p>\n        </section>\n        <section id=\"section3\">\n          <h2>Section 3</h2>\n          <p>The final section. Keep scrolling!</p>\n          <p>...</p>\n        </section>\n      </main>\n    </div>\n    <footer>\n      <p>Page footer</p>\n    </footer>\n  </div>\n</template>\n\n<script>\nimport Vue from 'vue';\nimport Sticky from 'vue-sticky-directive';\n\nVue.use(Sticky); // Register globally\n\nexport default {\n  name: 'App',\n  data() {\n    return {\n      isSticked: false\n    };\n  },\n  methods: {\n    handleStickChange(state) {\n      console.log('Sticky state changed:', state);\n      this.isSticked = state.sticked;\n    }\n  }\n};\n</script>\n\n<style>\n#app {\n  font-family: Avenir, Helvetica, Arial, sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  color: #2c3e50;\n  margin-top: 60px;\n}\nheader, footer {\n  background: #f0f0f0;\n  padding: 20px;\n  text-align: center;\n}\n.content-wrapper {\n  display: flex;\n  min-height: 1500px; /* Make content scrollable */\n}\nnav {\n  width: 200px;\n  background: #e9e9e9;\n  padding: 15px;\n}\nnav.is-sticky {\n  background-color: #d0d0d0;\n  box-shadow: 0 2px 5px rgba(0,0,0,0.2);\n}\nmain {\n  flex-grow: 1;\n  padding: 20px;\n}\nsection {\n  min-height: 500px;\n  margin-bottom: 30px;\n  border-bottom: 1px solid #eee;\n}\n</style>","lang":"javascript","description":"This example demonstrates how to globally register and use the `v-sticky` directive on a navigation bar. It shows how to define a `sticky-container`, set `sticky-offset` and `sticky-z-index`, and utilize the `on-stick` callback to react to the element's sticky state changes, applying a class when stuck. This code requires a Vue 2 environment."},"warnings":[{"fix":"For Vue 3, consider using a different sticky library specifically built for Vue 3 or directly utilizing CSS `position: sticky`. Migrating this directive to Vue 3 would require a significant rewrite of its core logic and registration process.","message":"This directive is designed for Vue 2 applications. It is not compatible with Vue 3 due to fundamental changes in the Vue 3 API, including directive registration and instance initialization methods. Direct usage in a Vue 3 project will result in errors.","severity":"breaking","affected_versions":">=0.0.1"},{"fix":"Always explicitly define the scrollable area or the element's intended relative parent with the `sticky-container` attribute. Ensure this container has sufficient height and, if meant to be scrollable, appropriate `overflow` CSS properties (e.g., `overflow: auto`).","message":"The sticky element must have a `sticky-container` parent (or nearest ancestor) to correctly define its relative boundaries. If no `sticky-container` is found, it will fallback to its direct parent, which might not be the desired scrollable area, leading to unexpected behavior where the element either doesn't stick or sticks to the wrong boundaries.","severity":"gotcha","affected_versions":">=0.0.1"},{"fix":"Always bind `sticky-offset` to a data property or an object literal containing `top` and/or `bottom` values, using `v-bind` (shorthand `:`), such as `:sticky-offset=\"myDynamicOffsets\"` or `:sticky-offset=\"{ top: 50, bottom: 0 }\"`.","message":"When setting `sticky-offset`, direct numeric values (e.g., `sticky-offset=\"10\"`) are not supported. It requires either a bound VM variable name (e.g., `:sticky-offset=\"myOffsetVar\"`) or a JavaScript expression in object form (e.g., `:sticky-offset=\"{ top: 10, bottom: 20 }\"`). Providing a simple number will be misinterpreted.","severity":"gotcha","affected_versions":">=0.0.1"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure `import Sticky from 'vue-sticky-directive'; Vue.use(Sticky);` is called early in your application's entry point (e.g., `main.js`), or that `directives: { Sticky }` is included in the component options where `v-sticky` is used.","cause":"The `v-sticky` directive has not been properly registered with the Vue instance, either globally via `Vue.use(Sticky)` or locally within a component's `directives` option.","error":"Failed to resolve directive: sticky"},{"fix":"Ensure `sticky-offset` is an object with `top` and/or `bottom` properties (e.g., `{ top: 0, bottom: 0 }`) and that it's bound using `v-bind` (shorthand `:`) if it's a dynamic value or expression, like `:sticky-offset=\"{ top: 50 }\"`.","cause":"`sticky-offset` or other options are being passed with incorrect types or formats, particularly when directly providing numbers instead of bound expressions or objects.","error":"TypeError: Cannot read properties of undefined (reading 'top') or similar errors related to sticky options."},{"fix":"Verify that an ancestor element has the `sticky-container` attribute and that this container has a defined height and is scrollable if intended. Check for conflicting `position` CSS properties on parent elements that might interfere with the directive's functionality.","cause":"This often occurs because the `sticky-container` ancestor is not properly defined, has insufficient height, or does not have `overflow: auto` or `scroll` if it's meant to be a scrollable container. Additionally, CSS conflicts (e.g., `position: relative` on a parent overriding the sticky behavior) can prevent proper sticking.","error":"The element with 'v-sticky' directive is not sticking as expected."}],"ecosystem":"npm"}