Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
A simple vanilla JS scrollspy script. Gumshoe works great with Smooth Scroll.
Getting Started | Nested Navigation | Reflows | Fixed Headers | API | What's new? | Browser Compatibility | License
Compiled and production-ready code can be found in the dist
directory. The src
directory contains development code.
There are two versions of Gumshoe: the standalone version, and one that comes preloaded with polyfills for closest()
and CustomEvent()
, which are only supported in newer browsers.
If you're including your own polyfills or don't want to enable this feature for older browsers, use the standalone version. Otherwise, use the version with polyfills.
Direct Download
You can download the files directly from GitHub.
<script src="path/to/gumshoe.polyfills.min.js"></script>
CDN
You can also use the jsDelivr CDN. I recommend linking to a specific version number or version range to prevent major updates from breaking your site. Gumshoe uses semantic versioning.
<!-- Always get the latest version -->
<!-- Not recommended for production sites! -->
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/gumshoe/dist/gumshoe.polyfills.min.js"></script>
<!-- Get minor updates and patch fixes within a major version -->
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/gumshoe@4/dist/gumshoe.polyfills.min.js"></script>
<!-- Get patch fixes within a minor version -->
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/gumshoe@4.0/dist/gumshoe.polyfills.min.js"></script>
<!-- Get a specific version -->
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/gumshoe@4.0.0/dist/gumshoe.polyfills.min.js"></script>
NPM
You can also use NPM (or your favorite package manager).
npm install gumshoejs
The only thing Gumshoe needs to work is a list of anchor links. They can be ordered or unordered, inline or unstyled, or even nested.
<ul id="my-awesome-nav">
<li><a href="#eenie">Eenie</a></li>
<li><a href="#meenie">Meenie</a></li>
<li><a href="#miney">Miney</a></li>
<li><a href="#mo">Mo</a></li>
</ul>
In the footer of your page, after the content, initialize Gumshoe by passing in a selector for the navigation links that should be detected as the user scrolls.
<script>
var spy = new Gumshoe('#my-awesome-nav a');
</script>
Gumshoe adds the .active
class to the list item (<li></li>
) and content for the active link, but does not include any styling.
Add styles to your CSS as desired. And that's it, you're done. Nice work!
#my-awesome-nav li.active a {
font-weight: bold;
}
Note: you can customize the class names with user options.
If you have a nested navigation menu with multiple levels, Gumshoe can also apply an .active
class to the parent list items of the currently active link.
<ul id="my-awesome-nav">
<li><a href="#eenie">Eenie</a></li>
<li>
<a href="#meenie">Meenie</a>
<ul>
<li><a href="#hickory">Hickory</a></li>
<li><a href="#dickory">Dickory</a></li>
<li><a href="#doc">Doc</a></li>
</ul>
</li>
<li><a href="#miney">Miney</a></li>
<li><a href="#mo">Mo</a></li>
</ul>
Set nested
to true
when instantiating Gumshoe. You can also customize the class name.
var spy = new Gumshoe('#my-awesome-nav a', {
nested: true,
nestedClass: 'active-parent'
});
Try nested navigation on CodePen →
If the content that's linked to by your navigation has different layouts at different viewports, Gumshoe will need to detect these changes and update some calculations behind-the-scenes.
Set reflow
to true
to enable this (it's off by default).
var spy = new Gumshoe('#my-awesome-nav a', {
reflow: true
});
If you have a fixed header on your page, you may want to offset when a piece of content is considered "active."
The offset
user setting accepts either a number, or a function that returns a number. If you need to dynamically calculate dimensions, a function is the preferred method.
Here's an example that automatically calculates a header's height and offsets by that amount.
// Get the header
var header = document.querySelector('#my-header');
// Initialize Gumshoe
var spy = new Gumshoe('#my-awesome-nav a', {
offset: function () {
return header.getBoundingClientRect().height;
}
});
Try using an offset on CodePen →
Gumshoe includes smart defaults and works right out of the box. But if you want to customize things, it also has a robust API that provides multiple ways for you to adjust the default options and settings.
You can pass options into Gumshoe when instantiating.
var spy = new Gumshoe('#my-awesome-nav a', {
// Active classes
navClass: 'active', // applied to the nav list item
contentClass: 'active', // applied to the content
// Nested navigation
nested: false, // if true, add classes to parents of active link
nestedClass: 'active', // applied to the parent items
// Offset & reflow
offset: 0, // how far from the top of the page to activate a content area
reflow: false, // if true, listen for reflows
// Event support
events: true // if true, emit custom events
});
Gumshoe emits two custom events:
gumshoeActivate
is emitted when a link is activated.gumshoeDeactivate
is emitted when a link is deactivated.Both events are emitted on the list item and bubble up. You can listen for them with the addEventListener()
method. The event.detail
object includes the link
and content
elements, and the settings
for the current instantiation.
// Listen for activate events
document.addEventListener('gumshoeActivate', function (event) {
// The list item
var li = event.target;
// The link
var link = event.detail.link;
// The content
var content = event.detail.content;
}, false);
Gumshoe also exposes several public methods.
Setups all of the calculations Gumshoe needs behind-the-scenes. If you dynamically add navigation items to the DOM after Gumshoe is instantiated, you can run this method to update the calculations.
Example
var spy = new Gumshoe('#my-awesome-nav a');
spy.setup();
Activate the navigation link that's content is currently in the viewport.
Example
var spy = new Gumshoe('#my-awesome-nav a');
spy.detect();
Destroy the current instantiation of Gumshoe.
Example
var spy = new Gumshoe('#my-awesome-nav a');
spy.destroy();
Gumshoe 4 is a ground-up rewrite.
new Gumshoe()
) instead of being initialized gumshoe.init()
.init()
method has been deprecated.Gumshoe works in all modern browsers, and IE 9 and above.
Support back to IE9 requires polyfills for closest()
and CustomEvent()
. Without them, support starts with Edge.
Use the included polyfills version of Gumshoe, or include your own.
The code is available under the MIT License.
FAQs
A simple, framework-agnostic scrollspy script.
We found that gumshoejs demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.