{"id":14653556,"url":"https://github.com/bramus/style-observer","last_synced_at":"2025-05-15T05:07:52.986Z","repository":{"id":256514089,"uuid":"849609478","full_name":"bramus/style-observer","owner":"bramus","description":"MutationObserver for CSS. Get notified when the computed value of a CSS property changes.","archived":false,"fork":false,"pushed_at":"2025-03-09T21:24:04.000Z","size":1024,"stargazers_count":409,"open_issues_count":2,"forks_count":6,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-11T09:11:21.747Z","etag":null,"topics":["css","javascript","mutationobserver"],"latest_commit_sha":null,"homepage":"https://brm.us/style-observer","language":"TypeScript","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/bramus.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},"funding":{"github":"bramus","-custom":["https://www.paypal.me/bramus","https://www.bram.us/"]}},"created_at":"2024-08-29T22:58:43.000Z","updated_at":"2025-04-03T13:27:01.000Z","dependencies_parsed_at":"2024-09-11T08:38:30.962Z","dependency_job_id":"7469156b-4938-47bf-b8ba-a77ed54391fb","html_url":"https://github.com/bramus/style-observer","commit_stats":null,"previous_names":["bramus/style-observer"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bramus%2Fstyle-observer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bramus%2Fstyle-observer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bramus%2Fstyle-observer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bramus%2Fstyle-observer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bramus","download_url":"https://codeload.github.com/bramus/style-observer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254276447,"owners_count":22043867,"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":["css","javascript","mutationobserver"],"created_at":"2024-09-11T08:00:53.666Z","updated_at":"2025-05-15T05:07:47.978Z","avatar_url":"https://github.com/bramus.png","language":"TypeScript","readme":"# `@bramus/style-observer` – MutationObserver for CSS\n\n[![@bramus/style-observer Logo](https://github.com/bramus/style-observer/raw/main/style-observer.jpg?raw=true)](https://brm.us/style-observer)\n\n[![npm](https://img.shields.io/npm/v/%40bramus%2Fstyle-observer)](https://www.npmjs.com/package/@bramus/style-observer)\n[![npm bundle size](https://img.shields.io/bundlejs/size/%40bramus/style-observer)](https://bundlejs.com/?q=%40bramus%2Fstyle-observer)\n[![NPM](https://img.shields.io/npm/l/%40bramus/style-observer)](./LICENSE)\n[![Demo](https://img.shields.io/badge/demo-_CodePen-hotpink)](https://codepen.io/bramus/pen/WNqKqxj?editors=1111)\n\n## CSS Style Observer?\n\nWhile [`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) can track DOM changes, it cannot be used to track style changes. This library plugs that gap and allows you to set up an observer that notifies you when the computed value of a tracked CSS property has changed.\n\nThe main use case for this library is to track changes to [CSS Custom Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) _(aka CSS Variables)_ but it can be used for other properties as well.\n\n![Demo](demo/demo-recording.gif)\n\n## Installation\n\n```\nnpm install @bramus/style-observer\n```\n\n## Usage\n\n```js\nimport StyleObserver, { NotificationMode, ReturnFormat } from '@bramus/style-observer';\n\nconst styleObserver = new StyleObserver(\n    /* The StyleObserver Callback. Gets called whenever one of the observed properties changes */\n    (values) =\u003e {\n      console.log(values['--variable1'], values['--variable2'], values['display'], values['border-width']);\n    },                                                 \n    /* StyleObserver Configuration */\n    {\n      properties: ['--variable1', '--variable2', 'display', 'border-width'],\n      returnFormat: ReturnFormat.OBJECT,\n      notificationMode: NotificationMode.ALL,\n    }\n);\n\nstyleObserver.observe(document.body); // Start observing changes to `document.body`\n\n// …\n\nstyleObserver.unobserve(document.body); // Stop observing\n```\n\n### Configuration options\n\n* `notificationMode` (`NotificationMode`, default: `CHANGED_ONLY`): Determines whether to pass all properties (`ALL`) or only the changed ones (`CHANGED_ONLY`) into the callback\n* `returnFormat` (`ReturnFormat`, default: `OBJECT`): Determines the format of the data passed to the callback. Below are the options:\n  * `VALUE_ONLY`: The callback receives an object with property names as keys and their current values:\n\n    ```js\n    {\n        \"--my-variable\": \"1.0\",\n        \"display\": \"block\"\n    }\n    ```\n\n  * `OBJECT`: The callback receives an object with property names as keys and detailed information as values:\n\n    ```js\n    {\n        \"--my-variable\":{\n            \"value\": \"1.0\",\n            \"previousValue\": \"0.0\",\n            \"changed\": true\n        }\n    }\n    ```\n\n    In the first callback invocation, which gets triggered after starting to observe an element, the value for `previousValue` will be `undefined`. You can use this to filter out the first trigger.\n\nTry out a demo on CodePen: [https://codepen.io/bramus/pen/WNqKqxj](https://codepen.io/bramus/pen/WNqKqxj?editors=1111)\n\n### Observing multiple elements\n\nOne single `StyleObserver` instance can be used to observer mutliple elements.\n\n```js\nconst observer = new StyleObserver(…);\n\nobserver.observe(document.getElementById('mainbutton'));\nobserver.observe(document.getElementById('otherbutton'));\n```\n\nTo unobserve a single element, pass a reference to it in `StyleObserver`’s `unobserve()`.\n\n```js\nobserver.unobserve(document.getElementById('mainbutton'));\n```\n\nWhen passing no argument in `unobserve()`, the observer will unobserve _all_ observed elements.\n\n## Local Development\n\nBelow is a list of commands you will probably find useful.\n\n### `npm run demo`\n\nRuns the project in development/watch mode, starts HTTP server and navigates to `http://localhost:8080/demo` \n\n### `npm start`\n\nRuns the project in development/watch mode. Your project will be rebuilt upon changes. \n\n### `npm run build`\n\nBundles the package to the `dist` folder.\n\n## FAQ\n\n### Browser support?\n\nThe requirement for this library to work is support for CSS Transitions.\n\nHowever, to also support properties that animate discretely – such as Custom Properties but also properties like `display` – the browser **must** support `transition-behavior: allow-discrete`.\n\nIn practice, this translates to the following list of browsers:\n\n- Safari 18\n- Firefox 129\n- Google Chrome 117\n\nNote: All browser versions listed above have bugs when transitioning Custom Properties. As it stands right now, the only cross-browser way to observe Custom Properties with `@bramus/style-observer` is to register the property with a syntax of `\"\u003ccustom-ident\u003e\"`, which might not be a good fit for your use-case. See [https://brm.us/style-observer#custom-props](https://brm.us/style-observer#custom-props) for a detailed write-up.\n\n### How is this library better when compared to other libraries?\n\nThis library doesn’t use `requestAnimationFrame` but responds to transition events. Therefore it doesn’t put a recurring and constant strain on the main thread.\n\nThe original [`css-variable-observer` library](https://github.com/fluorumlabs/css-variable-observer) that coined this approach only works with custom properties and numeric values. This library can work with any property having any value.\n\n### How is this library worse when compared to other libraries?\n\nThe properties that are being tracked are set to a very short transition time. If you relied on transitions for those properties, that is now no longer possible.\n\nYou can work around this by putting a value into a custom property that you track and then use that custom property in a regular property. The regular property can have any transition you want.\n\nAlso note that changing the value `transition` property yourself will make this library no longer work.\n\n## Acknowledgements\n\nThis library builds upon [the `css-variable-observer` project by Artem Godin](https://github.com/fluorumlabs/css-variable-observer). The suggestion to leverage `transition-behavior: allow-discrete` was done by [Jake Archibald](https://jakearchibald.com/) in [w3c/csswg-drafts#8982](https://github.com/w3c/csswg-drafts/issues/8982#issuecomment-2317164825).\n","funding_links":["https://github.com/sponsors/bramus","https://www.paypal.me/bramus","https://www.bram.us/"],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbramus%2Fstyle-observer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbramus%2Fstyle-observer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbramus%2Fstyle-observer/lists"}