I built a library to track DOM visibility, because the math was driving me crazy

Perceptible is a zero-dependency JavaScript library designed specifically for high-performance DOM element viewability and visibility tracking.

I keep coming back to a surprisingly annoying problem in front-end development: figuring out if a user is actually looking at a specific element on the page.

It sounds simple, right? Just use IntersectionObserver. But then the requirements start piling up. What if they scroll halfway past it? What if they switch tabs? What if you need to know exactly how long they looked at 50% of an ad to meet some strict analytics standard? Suddenly, you're writing a ton of messy state management code to calculate surface area and track visibility durations.

So, I built Perceptible.

What I built

Perceptible is a zero-dependency JavaScript library designed specifically for high-performance DOM element viewability and visibility tracking.

I wanted something that monitors elements in real time as users interact and scroll, but does all the tedious math for me. It measures the exact surface area coverage relative to the browser viewport. More importantly, it handles the edge cases that always trip me up - like tracking tab visibility, managing window focus events (which I call attentionMode), and keeping a precise timer on visibility duration.

What exactly is it?

At its core, Perceptible is a lightweight tracking engine. You point it at a DOM element, give it a threshold, and let it do the heavy lifting.

If you're using modern bundlers, you just import it and set up a watcher:

import Perceptor from 'perceptible'

const target = document.querySelector('#target')
const perceptor = new Perceptor(target, {
  threshold: 0.5, // Tell me when 50% is visible
})

perceptor.subscribe((event) => {
  console.log('Visibility changed:', event)
})

perceptor.watch()

I also made sure to give it full, native TypeScript support. You get types like SpectatorResult and Config right out of the box, which honestly just makes the developer experience so much better.

Why you might actually use this

I didn't just build this to reinvent the wheel. Calculating viewability is a real headache in a few specific scenarios, and that's where I think Perceptible actually shines:

  • Ad Viewability Standards: You can use this to track your ads. Perceptible tracks this out of the box.
  • Analytics & Impression Telemetry: It's great for figuring out how long a user actually engaged with a banner or a specific content card, rather than just knowing it loaded.
  • Media Player Automation: There's something really satisfying about a video player that auto-pauses when you scroll past it or switch tabs, and then resumes when you look at it again.
  • Lazy Loading & A/B Testing: Triggering assets or measuring content exposure metrics without writing custom intersection logic every single time.

It's completely open source and available under the MIT license. If you've ever wrestled with DOM visibility tracking and just want a clean API to handle it for you, give it a try. I'd love to hear what you think (or if you find any bugs I missed).

You can check out the code on GitHub or read the docs.