npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

style-observer

v0.1.2

Published

Observe CSS property changes on any elements

Readme

npm gzip size

  • Observe changes to custom properties
  • Observe changes to standard properties (except transition and animation)
  • Observe changes on any element (including those in Shadow DOM)
  • Lightweight, ESM-only code, with no dependencies
  • 200+ unit tests you can run in your browser of choice
  • Throttling per element
  • Does not overwrite existing transitions

Compatibility

Install

The quickest way is to just include straight from the Netlify CDN:

import StyleObserver from "https://observe.style/index.js";

This will always point to the latest version, so it may be a good idea to eventually switch to a local version that you can control. E.g. you can use npm:

npm install style-observer

and then, if you use a bundler like Rollup or Webpack:

import StyleObserver from "style-observer";

and if you don’t:

import StyleObserver from "node_modules/style-observer/dist/index.js";

Usage

You can first create the observer instance and then observe, like a MutationObserver. The simplest use is observing a single property on a single element:

const observer = new StyleObserver(records => console.log(records));
observer.observe(document.querySelector("#my-element"), "--my-custom-property");

You can also observe multiple properties on multiple elements:

const observer = new StyleObserver(records => console.log(records));
const properties = ["color", "--my-custom-property"];
const targets = document.querySelectorAll(".my-element");
observer.observe(targets, properties);

You can also provide both targets and properties when creating the observer, which will also call observe() for you:

import StyleObserver from "style-observer";

const observer = new StyleObserver(callback, {
	targets: document.querySelectorAll(".my-element"),
	properties: ["color", "--my-custom-property"],
});

Both targets and properties can be either a single value or an iterable.

Note that the observer will not fire immediately for the initial state of the elements (i.e. it behaves like MutationObserver, not like ResizeObserver).

Records

Just like other observers, changes that happen too close together (set the throttle option to configure) will only invoke the callback once, with an array of records, one for each change.

Each record is an object with the following properties:

  • target: The element that changed
  • property: The property that changed
  • value: The new value of the property
  • oldValue: The previous value of the property

Future Work

  • Observe pseudo-elements
  • immediate convenience option that fires the callback immediately for every observed element

Limitations & Caveats

  • You cannot observe changes on elements not connected to a document. However, once the elements become connected again, the observer will pick up any changes that happened while they were disconnected.
  • You cannot observe changes to transition and animation properties (and their constituent properties).
  • You cannot observe changes caused by CSS animations (follow #87 for updates).
  • Changes caused due to a slotted element being moved to a different slot will not be picked up.

Changing transition properties after observing

If you change the transition/transition-* properties dynamically on elements you are observing after you start observing them, the easiest way to ensure the observer continues working as expected is to call observer.updateTransition(targets) to regenerate the transition property the observer uses to detect changes.

If running JS is not an option, you can also do it manually:

  1. Add , var(--style-observer-transition, --style-observer-noop) at the end of your transition property. E.g. if instead of transition: 1s background you'd set transition: 1s background, var(--style-observer-transition, --style-observer-noop).
  2. Make sure to also set transition-behavior: allow-discrete;.

Prior Art

The quest for a JS style observer has been long and torturous.

While StyleObserver builds on this body of work, it is not a fork of any of them. It was written from scratch with the explicit goal of extending browser support and robustness. Read the blog post for more details.

By Lea Verou and Dmitry Sharabin.