{"id":8253291,"url":"https://github.com/strawdynamics/drift","last_synced_at":"2026-03-11T05:31:14.600Z","repository":{"id":37979297,"uuid":"48402726","full_name":"strawdynamics/drift","owner":"strawdynamics","description":"Easily add \"zoom on hover\" functionality to your site's images. Lightweight, no-dependency JavaScript.","archived":false,"fork":false,"pushed_at":"2024-06-28T02:42:30.000Z","size":11608,"stargazers_count":1570,"open_issues_count":16,"forks_count":118,"subscribers_count":35,"default_branch":"main","last_synced_at":"2026-02-16T14:57:19.247Z","etag":null,"topics":["drift","hacktoberfest","hover-effects","javascript","zoom-images"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/strawdynamics.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE-OF-CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-12-22T01:13:08.000Z","updated_at":"2026-01-31T02:28:21.000Z","dependencies_parsed_at":"2023-02-16T02:31:16.194Z","dependency_job_id":"3231e877-483c-4c09-aa61-f6b1fe47ef48","html_url":"https://github.com/strawdynamics/drift","commit_stats":{"total_commits":748,"total_committers":33,"mean_commits":"22.666666666666668","dds":0.732620320855615,"last_synced_commit":"beb88d9d1d33718ec724f356bf59877bd400633b"},"previous_names":["strawdynamics/drift","imgix/drift"],"tags_count":37,"template":false,"template_full_name":null,"purl":"pkg:github/strawdynamics/drift","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strawdynamics%2Fdrift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strawdynamics%2Fdrift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strawdynamics%2Fdrift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strawdynamics%2Fdrift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/strawdynamics","download_url":"https://codeload.github.com/strawdynamics/drift/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strawdynamics%2Fdrift/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30372166,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"online","status_checked_at":"2026-03-11T02:00:07.027Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["drift","hacktoberfest","hover-effects","javascript","zoom-images"],"created_at":"2024-04-19T12:03:44.762Z","updated_at":"2026-03-11T05:31:14.563Z","avatar_url":"https://github.com/strawdynamics.png","language":"JavaScript","readme":"# Drift\n\nDrift adds easy \"zoom on hover\" functionality to your site's images, all with lightweight, no-dependency JavaScript.\n\n[![npm version](https://img.shields.io/npm/v/drift-zoom.svg)](https://www.npmjs.com/package/drift-zoom)\n[![Build Status](https://travis-ci.org/imgix/drift.svg?branch=main)](https://travis-ci.org/imgix/drift)\n[![npm](https://img.shields.io/npm/dm/drift-zoom.svg)](https://www.npmjs.com/package/drift-zoom)\n[![License](https://img.shields.io/github/license/imgix/drift)](https://github.com/imgix/drift/blob/main/LICENSE.md)\n[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)\n[![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-)\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fimgix%2Fdrift.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fimgix%2Fdrift?ref=badge_shield)\n\n---\n\n\u003c!-- NB: Run `npx markdown-toc README.md --maxdepth 4 | sed -e 's/[[:space:]]\\{2\\}/    /g' | pbcopy` to generate TOC and copy to clipboard :) --\u003e\n\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [Demo](#demo-)\n- [Options / Defaults](#options--defaults)\n- [API](#api)\n    * [`Drift#disable`](#drift%23disable)\n    * [`Drift#enable`](#drift%23enable)\n    * [`Drift#setZoomImageURL(imageURL)`](#drift%23setzoomimageurlimageurl)\n- [Theming](#theming)\n- [FAQs/Examples](#faqsexamples)\n    * [Disabling on Mobile](#disabling-on-mobile)\n        + [CSS Solution (Recommended)](#css-solution-recommended)\n        + [JS Solution](#js-solution)\n    * [Use Drift with Multiple Images on the Same Page](#use-drift-with-multiple-images-on-the-same-page)\n- [Browser Support](#browser-support)\n- [Contributors ✨](#contributors-)\n- [Meta](#meta)\n- [License](#license)\n\n## Installation\n\n- **NPM**: `npm install drift-zoom`\n- **Bower**: `bower install drift`\n- **Manual**: [Download](https://github.com/imgix/drift/archive/main.zip) and use `dist/Drift.min.js` or `dist/Drift.js`\n\nIf you're using the pre-built version of Drift, it will automatically make `window.Drift` available for your use when included on your page.\n\nIf you prefer to use `require` statements and a build tool like Browserify, here are a couple examples to help:\n\n```javascript\nvar Drift = require('drift-zoom');\n\nnew Drift(…);\n```\n\nIf your project uses ES6, you can do the following instead:\n\n```javascript\nimport Drift from 'drift-zoom';\n\nnew Drift(…);\n```\n\n## Basic Usage\n\nOnce you've installed Drift via one of the above methods, you're ready to get started. There are no dependencies, so you can just start making cool stuff. Check out the [announcement blog post](https://blog.imgix.com/2016/01/06/better-lightbox-zoom-viewer-with-imgix?utm_medium=referral\u0026utm_source=github\u0026utm_campaign=drift).\nHere's an example of a basic implementation:\n\n```html\n\u003cimg src=\"https://assets.imgix.net/dog.png?w=400\" data-zoom=\"https://assets.imgix.net/dog.png?w=1200\"\u003e\n\n\u003cp\u003eThis is a simple description of the dog picture.\u003c/p\u003e\n```\n\n```javascript\nnew Drift(document.querySelector(\"img\"), {\n  paneContainer: document.querySelector(\"p\")\n});\n```\n\n## Demo 💻💻💻\nTake a peek at our [Demo Site](https://codepen.io/imgix/pen/WrRmLb).\n\n## Options / Defaults\n\nHere's an example of using Drift with a custom configuration. All of the listed options are displayed with their default value.\n\n```javascript\nvar options = {\n\t// Prefix for generated element class names (e.g. `my-ns` will\n\t// result in classes such as `my-ns-pane`. Default `drift-`\n\t// prefixed classes will always be added as well.\n\tnamespace: null,\n\t// Whether the ZoomPane should show whitespace when near the edges.\n\tshowWhitespaceAtEdges: false,\n\t// Whether the inline ZoomPane should stay inside\n\t// the bounds of its image.\n\tcontainInline: false,\n\t// How much to offset the ZoomPane from the\n\t// interaction point when inline.\n\tinlineOffsetX: 0,\n\tinlineOffsetY: 0,\n\t// A DOM element to append the inline ZoomPane to.\n\tinlineContainer: document.body,\n\t// Which trigger attribute to pull the ZoomPane image source from.\n\tsourceAttribute: 'data-zoom',\n\t// How much to magnify the trigger by in the ZoomPane.\n\t// (e.g., `zoomFactor: 3` will result in a 900 px wide ZoomPane image\n\t// if the trigger is displayed at 300 px wide)\n\tzoomFactor: 3,\n\t// A DOM element to append the non-inline ZoomPane to.\n\t// Required if `inlinePane !== true`.\n\tpaneContainer: document.body,\n\t// When to switch to an inline ZoomPane. This can be a boolean or\n\t// an integer. If `true`, the ZoomPane will always be inline,\n\t// if `false`, it will switch to inline when `windowWidth \u003c= inlinePane`\n\tinlinePane: 375,\n\t// If `true`, touch events will trigger the zoom, like mouse events.\n\thandleTouch: true,\n\t// If present (and a function), this will be called\n\t// whenever the ZoomPane is shown.\n\tonShow: null,\n\t// If present (and a function), this will be called\n\t// whenever the ZoomPane is hidden.\n\tonHide: null,\n\t// Add base styles to the page. See the \"Theming\"\n\t// section of README.md for more information.\n\tinjectBaseStyles: true,\n\t// An optional number that determines how long to wait before\n\t// showing the ZoomPane because of a `mouseenter` event.\n\thoverDelay: 0,\n\t// An optional number that determines how long to wait before\n\t// showing the ZoomPane because of a `touchstart` event.\n\t// Setting this to a reasonable amount will allow users to execute\n\t// scroll-gestures events on touch-enabled devices with the image as\n\t// a starting point\n\ttouchDelay: 0,\n\t// If true, a bounding box will show the area currently being previewed\n\t// during mouse hover\n\thoverBoundingBox: false,\n\t// If true, a bounding box will show the area currently being previewed\n\t// during touch events\n\ttouchBoundingBox: false,\n\t// A DOM element to append the bounding box to.\n\tboundingBoxContainer: document.body,\n\t// If true, the events related to handleTouch use passive listeners in\n\t// order to improve performance for touch devices.\n\tpassive: false,\n};\n\nnew Drift(document.querySelector('img'), options);\n```\n\n## API\n\n### `Drift#disable`\n\nDisable your Drift instance. This will prevent your Drift instance from showing, but will not hide it if it's currently visible.\n\n```javascript\nvar drift = new Drift(document.querySelector(\"img\"), {\n  paneContainer: document.querySelector(\"p\")\n});\n\ndocument.querySelector(\".disable-button\").addEventListener(\"click\", function() {\n  drift.disable();\n});\n```\n\n### `Drift#enable`\n\nEnable your Drift instance.\n\n```javascript\nvar drift = new Drift(document.querySelector(\"img\"), {\n  paneContainer: document.querySelector(\"p\")\n});\n\ndocument.querySelector(\".enable-button\").addEventListener(\"click\", function() {\n  drift.enable();\n});\n```\n\n### `Drift#setZoomImageURL(imageURL)`\n\nChange the URL of the zoom image to the passed string. This only has a visible effect while your Drift is currently open. When opening, Drift always pulls the zoom image URL from the specified `sourceAttribute`. If you want to make a \"permanent\" change that will persist after the user leaves and re-enters your Drift trigger, you update its `sourceAttribute` as well (default `data-zoom`). For more information about this method, please see [issue #42](https://github.com/imgix/drift/issues/42).\n\n```javascript\nvar triggerEl = document.querySelector(\"img\");\nvar drift = new Drift(triggerEl, {\n  paneContainer: document.querySelector(\"p\")\n});\n\nvar frames = [\"https://mysite.com/frame1.jpg\", \"https://mysite.com/frame2.jpg\", \"https://mysite.com/frame3.jpg\"];\n\nvar currentFrame = 0;\n\nsetInterval(function() {\n  currentFrame++;\n\n  if (currentFrame \u003e frames.length - 1) {\n    currentFrame = 0;\n  }\n\n  drift.setZoomImageURL(frames[currentFrame]);\n  triggerEl.setAttribute(\"data-zoom\", frames[currentFrame]);\n}, 1200);\n```\n\n## Theming\n\nBy default, Drift injects an extremely basic set of styles into the page. You will almost certainly want to extend these basic styles for a prettier, more usable experience that matches your site. There is an included basic theme that may meet your needs, or at least give a good example of how to build out your own custom styles. The `namespace` option can be used as a way to easily apply different themes to specific instances of Drift.\n\nIf you need to do something very out of the ordinary, or just prefer to include the default styles in CSS yourself, you can pass `injectBaseStyles: false` when instantiating a new instance of Drift. Please note that if you disable the included base styles, you will still need to provide an animation for `.drift-window.drift-opening` and `.drift-window.drift-closing` (this can be a \"noop\" style animation, as seen in the base styles source).\n\n## FAQs/Examples\n\nIn this section we answer common questions about Drift.\n\n### Disabling on Mobile\n\nIf you would like the touch events not to fire on mobile for one reason or another, these two solutions should work for you.\n\n#### CSS Solution (Recommended)\n\nThis solution places a transparent element over the image on mobiles to block touch events. Replace `1024px` in the media query with your mobile breakpoint.\n\n```css\n.zoom-image {\n\tposition: relative;\n}\n\n.zoom-image::before {\n\tcontent: \"\";\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tbackground: transparent;\n}\n\n@media only screen and (min-width: 1024px) {\n\t.zoom-image::before {\n\t\tdisplay: none;\n\t}\n}\n```\n\n#### JS Solution\n\nThis solution creates and destroys the Drift instance when the browser size changes. It depends on the library [responsive.js](https://www.responsivejs.com/) but can easily be altered to use vanilla JS.\n\n```js\nconst driftOptions = {\n\tpaneContainer: paneContainer,\n\tinlinePane: false,\n\thandleTouch: false\n};\n\nconst handleChange = () =\u003e {\n\trequestAnimationFrame(() =\u003e {\n\t\tif (Responsive.is('mobile') \u0026\u0026 !!window.productZoom) {\n\t\t\twindow.productZoom.destroy();\n\t\t} else {\n\t\t\twindow.productZoom = new Drift(img, driftOptions);\n\t\t}\n\t})\n}\n\nwindow.addEventListener('resize', handleChange);\nwindow.addEventListener('load', handleChange);\n\n```\n\n### Use Drift with Multiple Images on the Same Page\n\nThis code will iterate over all elements on your page with the class `drift-img`, and will instantiate Drift for each element. You can update the query selector and pane as you see fit.\n\n```js\nconst driftImgs = document.querySelectorAll('.drift-img');\nconst pane = document.querySelector('.drift-pane');\ndriftImgs.map(img =\u003e {\n\tnew Drift(img, {\n\t\tpaneContainer: pane,\n\t\tinlinePane: false\n\t});\n});\n```\n\n## Browser Support\n\nWe support the latest version of Google Chrome (which [automatically updates](https://support.google.com/chrome/answer/95414) whenever it detects that a new version of the browser is available). We also support the current and previous major releases of desktop Firefox, Internet Explorer, and Safari on a rolling basis. Mobile support is tested on the most recent minor version of the current and previous major release for the default browser on iOS and Android (e.g., iOS 9.2 and 8.4). Each time a new version is released, we begin supporting that version and stop supporting the third most recent version.\n\n## Contributors ✨\n\u003c!-- ix-docs-ignore --\u003e\n\nThanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://paulstraw.com\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/117288?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ePaul Straw\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/imgix/drift/commits?author=paulstraw\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"https://github.com/imgix/drift/commits?author=paulstraw\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#maintenance-paulstraw\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/sherwinski\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/15919091?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003esherwinski\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/imgix/drift/commits?author=sherwinski\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/imgix/drift/commits?author=sherwinski\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#maintenance-sherwinski\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/frederickfogerty\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/615334?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eFrederick Fogerty\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/imgix/drift/commits?author=frederickfogerty\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/imgix/drift/commits?author=frederickfogerty\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#maintenance-frederickfogerty\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"http://jayeb.com\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/609840?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJason Eberle\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/imgix/drift/commits?author=jayeb\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/imgix/drift/commits?author=jayeb\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#maintenance-jayeb\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"http://www.luisball.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/16711614?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eLuis H. Ball Jr.\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#maintenance-luqven\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\u003c!-- /ix-docs-ignore --\u003e\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!\n\n## Meta\n\nDrift was made by [imgix](https://imgix.com?utm_medium=referral\u0026utm_source=github\u0026utm_campaign=drift). It's licensed under the BSD 2-Clause license (see the [license file](https://github.com/imgix/drift/blob/main/LICENSE.md) for more info). Any contribution is absolutely welcome, but please review the [contribution guidelines](https://github.com/imgix/drift/blob/main/CONTRIBUTING.md) before getting started.\n\n## License\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fimgix%2Fdrift.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fimgix%2Fdrift?ref=badge_large)\n","funding_links":[],"categories":["JavaScript","javascript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrawdynamics%2Fdrift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstrawdynamics%2Fdrift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrawdynamics%2Fdrift/lists"}