{"id":13515641,"url":"https://github.com/kovart/sticksy","last_synced_at":"2025-04-05T20:05:12.923Z","repository":{"id":34245811,"uuid":"172678112","full_name":"kovart/sticksy","owner":"kovart","description":"🧲 Blazing fast sticky widgets in one line! (Sidebar friendly)","archived":false,"fork":false,"pushed_at":"2024-02-24T14:17:09.000Z","size":11238,"stargazers_count":185,"open_issues_count":9,"forks_count":24,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-05-10T16:32:53.363Z","etag":null,"topics":["element","fixed","javascript","scrolling","sidebar","sticky","widget","wordpress"],"latest_commit_sha":null,"homepage":"https://sticksy.js.org","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kovart.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2019-02-26T09:17:43.000Z","updated_at":"2024-08-01T06:07:23.383Z","dependencies_parsed_at":"2024-02-24T15:38:04.130Z","dependency_job_id":null,"html_url":"https://github.com/kovart/sticksy","commit_stats":{"total_commits":45,"total_committers":2,"mean_commits":22.5,"dds":"0.022222222222222254","last_synced_commit":"f5323ee7cea52bdb57db66467ce992fa893c2330"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovart%2Fsticksy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovart%2Fsticksy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovart%2Fsticksy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovart%2Fsticksy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kovart","download_url":"https://codeload.github.com/kovart/sticksy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247393566,"owners_count":20931812,"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":["element","fixed","javascript","scrolling","sidebar","sticky","widget","wordpress"],"created_at":"2024-08-01T05:01:14.016Z","updated_at":"2025-04-05T20:05:12.888Z","avatar_url":"https://github.com/kovart.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"\u003ch1 align=\"left\"\u003eSticksy.js 📌\u003c/h1\u003e\n\n[![npm](https://badge.fury.io/js/sticksy.svg)](https://www.npmjs.com/package/sticksy)\n[![gzip size](https://badgen.net/badgesize/gzip/https://unpkg.com/sticksy@latest/dist/sticksy.min.js)](https://cdn.jsdelivr.net/npm/sticksy/dist/sticksy.min.js)\n[![hits](https://data.jsdelivr.com/v1/package/npm/sticksy/badge)](https://cdn.jsdelivr.net/npm/sticksy/dist/sticksy.min.js)\n[![snyk](https://snyk.io/test/npm/sticksy/badge.svg)](https://snyk.io/test/npm/sticksy)\n[![license](https://badgen.net/npm/license/lodash)](https://opensource.org/licenses/MIT)\n\nSticksy.js is a **zero-dependency** JavaScript library that sticks your elements to the top until they reaching the bottom.\nUnlike [**Q2W3 WordPress Plugin**](https://wordpress.org/plugins/q2w3-fixed-widget/), you don't need WordPress, jQuery, or other stuff. **You can use it in any web project.** \\\n_It's simple and ultra fast. ⚡_\n\nJust import and initialize:\n\n```javascript\nvar stickyElems = Sticksy.initializeAll('.container \u003e .sticky') // and that's all!\n```\n\n\u003e ⚠️ The library **is not** a `position: sticky` polyfill, it makes the sibling elements move down.\n\n\u003cbr/\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Fixed widgets in sidebar\" src=\"https://github.com/kovart/sticksy/raw/assets/demo.gif?raw=true\"\u003e\u003c/img\u003e\n\u003c/p\u003e\n\n## When do you need Sticksy?\n\n\u003e The basic use-case of the library is to make **fixed widgets** in a sidebar.\n\nThe library is especially useful for ads or other items that visitors want to interact with.\nSticky blocks are perceived much better by your visitors than unfixed widgets and therefore they have a significantly higher click-through rate.\n\n_But also you can use it for some design features._\n\n## Features\n\n-   Setup in one line\n-   Super performance\n-   Zero dependencies\n-   Fully written in ES5\n-   Can react to DOM changes\n-   Small size ~1.8Kb (minified gzip)\n\n## Demo\n\n-   [Basic usage](https://codepen.io/kovart/pen/VReGjN)\n-   [Usage with JQuery or Zepto](https://codepen.io/kovart/pen/OqMrvR)\n-   [Same selector for multiple items](https://codepen.io/kovart/pen/eXJxQY)\n\nMore examples in [`this folder`](./examples).\n\n## Installation\n\nYou can simply install the library from CDN, NPM, Yarn or just download it from this repo.\n\n### CDN\n\nJust insert the proper version of the library into your page:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/sticksy@0.2.0/dist/sticksy.min.js\"\u003e\u003c/script\u003e\n```\n\n### NPM\n\n```sh\n$ npm install sticksy --save\n```\n\n### Yarn\n\n```sh\n$ yarn add sticksy\n```\n\n---\n\n🧱 Import an entire module if you use Webpack, Rollup or other module bundlers:\n\n```js\nimport 'sticksy'\n```\n\n## Usage\n\nWatch an example.\n\n```html\n\u003c!-- Container --\u003e\n\u003caside class=\"sidebar\"\u003e\n    \u003c!-- Non sticky element --\u003e\n    \u003cdiv class=\"widget\"\u003e\u003c/div\u003e\n    \u003c!-- Sticky element --\u003e\n    \u003cdiv class=\"widget js-sticky-widget\"\u003e\u003c/div\u003e\n    \u003cdiv class=\"widget\"\u003e\u003c/div\u003e\n    \u003cdiv class=\"widget\"\u003e\u003c/div\u003e\n\u003c/aside\u003e\n```\n\n_⚠️ The container shouldn't be absolutely positioned as we use absolute position to stuck the elements to the bottom._\n\nThen you should initialize an instance with a **new** keyword (it's important):\n\n```js\nvar stickyEl = new Sticksy('.js-sticky-widget')\n// just for demonstration of state handling\nstickyEl.onStateChanged = function (state) {\n    if (state === 'fixed') stickyEl.nodeRef.classList.add('widget--fixed')\n    else stickyEl.nodeRef.classList.remove('widget--fixed')\n}\n```\n\nThat's all 😎\n\nAlso, you can directly pass the target node:\n\n```js\nvar stickyEl = new Sticksy(document.getElementById('sticky-widget'))\n```\n\n#### Via JQuery/Zepto:\n\n```js\nvar stickyEl = $('.widget.js-sticky-widget').sticksy({ topSpacing: 60, listen: true })\n```\n\n---\n\n#### Initialize all sticky elements\n\nYou can add the one class to all the target elements and initialize them all in one line:\n\n```html\n\u003caside class=\"sidebar\"\u003e\n    \u003cdiv class=\"widget\"\u003e\u003c/div\u003e\n    \u003c!-- Sticky element --\u003e\n    \u003cdiv class=\"widget js-sticky-widget\"\u003e\u003c/div\u003e\n\u003c/aside\u003e\n\u003cmain\u003e\n    \u003c!-- Some content here --\u003e\n\u003c/main\u003e\n\u003caside class=\"sidebar\"\u003e\n    \u003c!-- Sticky element --\u003e\n    \u003cdiv class=\"widget js-sticky-widget\"\u003e\u003c/div\u003e\n    \u003cdiv class=\"widget\"\u003e\u003c/div\u003e\n\u003c/aside\u003e\n```\n\n```js\nvar stickyElements = Sticksy.initializeAll('.js-sticky-widget')\n```\n\n#### Enable reaction to DOM changes\n\nThe library can detect changes of the container and its children by using \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver\" target=\"_blank\"\u003eMutationObserver\u003c/a\u003e. To enable this behavior, you have to specify `listen` option.\n\n```js\nvar stickyEl = new Sticksy('.js-sticky-widget', {\n    listen: true, // Listen for the DOM changes in the container\n})\n```\n\n\u003e Beware! Since the library uses style attribute to change elements position,\n\u003e it ignores changes of width and height properties of style attribute.\n\u003e Use CSS classes instead.\n\n---\n\nMore examples in [`example folder`](https://github.com/kovart/sticksy/tree/master/examples) and [`this section`](#demo).\n\n## API\n\nThe API is as simple as possible.\n\n### Constructor options\n\n```js\nvar instance = new Sticksy(target[, options]);\n```\n\n-   `target` _(String | Element)_ target element or query string\n-   `options` _(ContructorOptions)_ all options below are optional\n    -   `topSpacing`: _(Number)_ additional top spacing for the top sticky element when it becomes fixed (sticky). Use this option when you have a fixed top panel. `Optional` | `Default: 0`\n    -   `listen`: _(Boolean)_ should we recalculate all cached dimensions of the viewport, container and sticky elements on any DOM changes in the container element. `Optional` | `Default: false`\n-   **_Returns:_** [`Instance`](#instance-object)\n\nExample:\n\n```js\nvar stickyEl = new Sticksy('.block.js-sticky-widget', {\n    topSpacing: 60, // Specify this when you have a fixed top panel\n    listen: true, // Listen for the DOM changes in the container\n})\n```\n\n### Instance object\n\n### Properties\n\n-   `nodeRef` _(Element)_ a direct reference to the DOM element\n\n```js\nstickyEl.onStateChanged = function (state) {\n    if (state === 'fixed') stickyEl.nodeRef.classList.add('widget--fixed')\n    else stickyEl.nodeRef.classList.remove('widget--fixed')\n}\n```\n\n### Methods\n\n#### refresh(): void\n\nRecalculate and update the element according to the new state.\n\n```js\nstickyEl.refresh()\n```\n\n#### hardRefresh(): void\n\nRecalculate all cached dimensions of the viewport, container and sticky elements and update the element according to the new state. Use it for manual refreshing, for example, if you haven't specified `listen` option, but you have to deal with some DOM manipulations.\n\n```js\nstickyEl.hardRefresh()\n```\n\n#### enable(): void\n\nEnable `'sticky'` effect.\n\n```js\nstickyEl.enable()\n```\n\n#### disable(): void\n\nMake the element static.\n\n```js\nstickyEl.disable()\n```\n\n### Events\n\n#### onStateChanged\n\nTriggered when the state of the element has changed.\nThe state can be: `static`, `fixed` and `stuck`.\n\n```js\nstickyEl.onStateChanged = function (state) {\n    // your handler here\n    if (state === 'fixed') alert('it is fixed!')\n}\n```\n\n---\n\n### Static methods\n\n#### refreshAll(): void\n\nCall `refresh()` method for the initialized instances.\n\n```js\nSticksy.refreshAll()\n```\n\n#### hardRefreshAll(): void\n\nCall `hardRefresh()` method for the initialized instances.\n\n```js\nSticksy.hardRefreshAll()\n```\n\n#### enableAll(): void\n\nCall `enable()` method for all the initialized instances.\n\n```js\nSticksy.enableAll()\n```\n\n#### disableAll(): void\n\nCall `disable()` method for all the initialized instances.\n\n```js\nSticksy.disableAll()\n```\n\n### Helper methods\n\n#### initializeAll(target[, options][, ignorenothingfound])\n\nFind and initialize all the elements with the same options. By default, it doesn't throw an error if nothing found.\n\n-   `target` _(String | Element | Element[] | jQuery)_ target element(s) or query string. `Required`\n-   `options` _[(ContructorOptions)](#constructor-options)_ options for the target elements. `Optional`\n-   `ignoreNothingFound` _(Boolean)_ should we throw an error if no match is found. `Default: true`\n\n-   **_Returns_:** [`Instance`](#instance-object)\n\nExample:\n\n```js\nvar stickyElems = Sticksy.initializeAll('.js-sticky-widget', { listen: true }, true)\n```\n\n## Performance\n\nPerformance is ultra high. ⚡\n\nThe library uses the simplest function to calculate the elements state:\n\n```js\nSticksy.prototype._calcState = function (windowOffset) {\n    if (windowOffset \u003c this._limits.top) {\n        return States.STATIC\n    } else if (windowOffset \u003e= this._limits.bottom) {\n        return States.STUCK\n    }\n    return States.FIXED\n}\n```\n\nThe function doesn't have any complicated calculations. It just compares two variables. Not more. \\\nIf the calculated state is **the same** as previous the library **does nothing**.\n\nCool, right? 😃\n\n## Browser Compatibility\n\nSticksy.js works in all modern browsers including Internet Explorer 11.\\\nIf you want the library to react to DOM changes and need to support IE10 or below,\nyou should install [`Mutation Observer Polyfill`](https://github.com/megawac/MutationObserver.js).\n\nPlease, open an issue if you have any browser compatibility problems.\n\n## License (MIT)\n\n```\nWWWWWW||WWWWWW\n W W W||W W W\n      ||\n    ( OO )__________\n     /  |           \\\n    /o o|    MIT     \\\n    \\___/||_||__||_|| *\n         || ||  || ||\n        _||_|| _||_||\n       (__|__|(__|__|\n```\n\nSticksy.js is released under the MIT license.\\\nCopyright (c) 2019-present Artem Kovalchuk\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkovart%2Fsticksy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkovart%2Fsticksy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkovart%2Fsticksy/lists"}