{"id":40506201,"url":"https://github.com/tomhodgins/computed-variables","last_synced_at":"2026-01-20T19:36:17.334Z","repository":{"id":57205054,"uuid":"153730070","full_name":"tomhodgins/computed-variables","owner":"tomhodgins","description":"Easy to use event-driven CSS variables","archived":false,"fork":false,"pushed_at":"2019-03-18T16:41:59.000Z","size":24,"stargazers_count":82,"open_issues_count":2,"forks_count":1,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-10-04T10:33:17.577Z","etag":null,"topics":["css","css-reprocessor","css-variables","cssom","custom-properties","custom-property","reprocessor","variables"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/tomhodgins.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}},"created_at":"2018-10-19T05:17:42.000Z","updated_at":"2025-04-06T14:51:21.000Z","dependencies_parsed_at":"2022-09-18T01:01:28.742Z","dependency_job_id":null,"html_url":"https://github.com/tomhodgins/computed-variables","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tomhodgins/computed-variables","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomhodgins%2Fcomputed-variables","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomhodgins%2Fcomputed-variables/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomhodgins%2Fcomputed-variables/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomhodgins%2Fcomputed-variables/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomhodgins","download_url":"https://codeload.github.com/tomhodgins/computed-variables/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomhodgins%2Fcomputed-variables/sbom","scorecard":{"id":892596,"data":{"date":"2025-08-18","repo":{"name":"github.com/tomhodgins/computed-variables","commit":"dcdbb2615df0b06677848fb4b70d371b51efbbe7"},"scorecard":{"version":"v5.2.1-41-g40576783","commit":"40576783fda6698350fcbbeaea760ff827433034"},"score":3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/13 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-24T12:26:18.420Z","repository_id":57205054,"created_at":"2025-08-24T12:26:18.420Z","updated_at":"2025-08-24T12:26:18.420Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28610770,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T18:56:40.769Z","status":"ssl_error","status_checked_at":"2026-01-20T18:54:26.653Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["css","css-reprocessor","css-variables","cssom","custom-properties","custom-property","reprocessor","variables"],"created_at":"2026-01-20T19:36:16.725Z","updated_at":"2026-01-20T19:36:17.327Z","avatar_url":"https://github.com/tomhodgins.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# computed-variables\n\nEasy to use event-driven CSS variables\n\n## About\n\nComputed Variables is a JavaScript plugin that allows CSS variables to subscribe to events happening in the browser, and have their values updated by simple JavaScript functions on an as-needed basis.\n\nHave you ever wished you could access values from your CSS stylesheets that JavaScript is aware of, but CSS can't quite reach? By using computed variables you can expose things like the window dimensions or scroll positions, properties of elements, any math JavaScript can compute, cursor and pointer events, custom easing functions, and more.\n\n\u003e Similar in concept to [jsincss](https://github.com/tomhodgins/jsincss), except jsincss is for rules and stylesheets, and computed variables is for CSS variables.\n\n## Downloading\n\nYou can download computed-variables and add it to your codebase manually, or download it with npm:\n\n```bash\nnpm install computed-variables\n```\n\nAnother option is linking to the module directly from a CDN like unpkg:\n\n```html\n\u003cscript type=module\u003e\n  import computedVariables from 'https://unpkg.com/computed-variables/index.es.js'\n\u003c/script\u003e\n```\n\n## Importing\n\nYou can import the plugin into your own JavaScript modules in a couple of ways.\n\nThe first way is using the native [`import` statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) in JavaScript. Here you can assign any name you want to the function you are importing, and you only need to provide a path to the plugin's `index.es.js` file:\n\n```js\nimport computedVariables from './index.es.js'\n```\n\nYou can also use `require()` to load this plugin instead with a bundler like Webpack or Parcel:\n\n```js\nconst computedVariables = require('computed-variables')\n```\n\nOnce you have imported this plugin into your module, you can use the plugin as `computedVariables()`\n\n## Usage\n\nThe main goal of the plugin is to create recipes for CSS variables that can be computed and re-computed when certain events happen in the window, or on individual tags. You want to define a name for the variables you will be watching and computing, as well as supply a JavaScript function for calculating the current value CSS should use.\n\nThe plugin has the following format:\n\n```js\ncomputedVariables(name, func, selector, events)\n```\n\n- `name` is a string starting with `--` that the custom selector(s) should match\n\n- `func` is a JavaScript function that accepts three arguments:\n- - `value`: the value originally set to the property in CSS or HTML\n- - `event`: the event object from JavaScript when the style recomputed\n- - `tag`: the CSS rule or DOM tag containing the custom property\n\n- `selector` is string containing either `'window'` or a CSS selector\n\n- `events` is an array of events to add event listeners for, quoted as strings: (eg. `['load', resize']`)\n\nThe default `selector` is `window`, and the default list of `events` is `['load', 'resize', 'input', 'click', 'recompute']`.\n\nYou can also create and listen for custom events with JavaScript using `new Event()` and `dispatchEvent()` for total control over when computed-variables recomputes styles.\n\n## Examples\n\n### Exposing browser viewport dimensions to CSS\n\nThis example shows and example of exposing properties from the `window` object, on the `load` and `resize` event:\n\n```html\n\u003cscript type=module\u003e\n  import computedVariables from 'https://unpkg.com/computed-variables/index.es.js';\n\n  computedVariables(\n    '--inner',\n    value =\u003e window[value],\n    window,\n    ['load', 'resize']\n  )\n\u003c/script\u003e\n```\n\nThis means it will go through the DOM and CSSOM looking for CSS rules or DOM nodes with styles that contain a custom CSS variable starting with `--inner`, which would match both `--innerWidth` and `--innerHeight` for example, and it would set their value to the property on the `window` object that matches the string we write in our CSS. This means a rule like this:\n\n```css\n:root {\n  --innerWidth: \"innerWidth\";\n  --innerHeight: \"innerHeight\";\n}\n```\n\nWould result in the `\u003chtml\u003e` tag having a `--innerWidth` property getting the value of `window.innerWidth` every time the variable recomputes. And likewise the `--innerHeight` variable gets the value of `window.innerHeight` every time the variable recomputes.\n\nAlternatively, we can also write custom variables in HTML in addition to CSS - suppose we had this in our DOM instead:\n\n```html\n\u003chtml style='\n  --innerWidth: \"innerWidth\";\n  --innerHeight: \"innerHeight\";\n'\u003e\n```\n\nThis would result in functionally the same thing - the `\u003chtml\u003e` element would have custom `--innerWidth` and `--innerHeight` variables that equalled their `window.innerWidth` and `window.innerHeight`.\n\n### Exposing mouse and touch pointer coordinates\n\n```css\n:root {\n  --cursorX: \"clientX\";\n  --cursorY: \"clientY\";\n}\n```\n\n```js\ncomputedVariables(\n  '--cursor',\n  (value, event) =\u003e event[value] || event.touches[0][value],\n  window,\n  ['mousemove', 'touchstart']\n)\n```\n\nWith this recipe we can watch the mouse or first touch point cursor coordinates, and use them in CSS with `var(--cursorX)` and `var(--cursorY)`. This will update every `mousemove` and `touchmove` event, allowing you to use the mouse cursor position in your CSS styles.\n\n### Exposing element dimensions and offset\n\n```html\n\u003cdiv style='\n  --offsetWidth: \"offsetWidth\";\n  --offsetHeight: \"offsetHeight\";\n  --offsetLeft: \"offsetLeft\";\n  --offsetTop: \"offsetTop\";\n'\u003e\u003c/div\u003e\n```\n\n```js\ncomputedVariables(\n  '--offset',\n  (value, event, tag) =\u003e tag[value],\n  window,\n  ['load', 'resize']\n)\n```\n\nThis recipe uses custom properties on DOM nodes (rather than in CSS stylesheets). By looking for all custom properties on tags that begin with `--offset` and reading the property expressed as the initial value, we can read and use the tag's `offsetWidth`, `offsetHeight`, `offsetLeft`, and `offsetTop` properties, and keep those updated every `load` and `resize` event.\n\nFor a demo that uses the last two recipes, check out:\n\n- [Box Shadow (exposing cursor events and element properties)](https://codepen.io/tomhodgins/pen/XxYjqV)\n\n### Exposing window scroll position via `document.scrollingElement`\n\n```css\n:root {\n  --window-scroll-top: \"scrollTop\";\n  --window-scroll-left: \"scrollLeft\";\n}\n```\n\n```js\ncomputedVariables(\n  '--window-scroll-',\n  value =\u003e document.scrollingElement[value],\n  window,\n  ['load', 'scroll']\n)\n```\n\nThis recipe let's CSS authors create variables like `--scroll-top` or `--scroll-left` which can be used to expose `document.scrollingElement.scrollTop` or `document.scrollingElement.scrollLeft` (or other things) to CSS, updated whenever the window loads or scrolls.\n\n### Exposing element scroll position\n\n```html\n\u003ctextarea style='\n  --element-scroll-top: \"scrollTop\";\n'\u003e\n```\n\n```js\ncomputedVariables(\n  '--element-scroll-',\n  (value, event, tag) =\u003e tag[value],\n  '[style*=\"--element-scroll-\"]',\n  ['scroll']\n)\n```\n\nThis recipe looks for any custom properties that start with `--element-scroll-` and will expose the properties of each matching DOM node that has such a property that matches the initial value given. Here we can use it to create a CSS variable on a `\u003ctextarea\u003e` element that exposes that tag's `scrollTop` property to CSS, and with computed-variables we're able to only listen to the `scroll` events only on tags whose `style=\"\"` attribute contains `--element-scroll-` inline.\n\nTo see the last two example in action, check out this demo:\n\n- [Scrolling demo (exposing `document.scrollingElement` and element scroll positions)](https://codepen.io/tomhodgins/pen/BqPjpe)\n\n### Generating random numbers in CSS\n\n```css\n:root {\n  --random-1: 1;\n  --random-2: 10;\n  --random-3: 50;\n}\n```\n\n```js\ncomputedVariables(\n  '--random-',\n  value =\u003e Math.random() * value,\n  window,\n  ['load']\n)\n```\n\nThis recipe would look for any CSS variable that started with `--random-` and would return a random number between `0` and the supplied value when the page first loads. For `--random-1` the value supplied is `1`, so the number returned will be between 0-10. For `--random-2` the value supplied is `10`, so the number returned will be between 0-10. And for `--random-3` the value supplied is `50`, so the number returned will be between 0-50.\n\n### Picking from an array of choices\n\n```css\n:root {\n  --choice-1: [\"black\", \"white\"];\n  --choice-2: [\"red\", \"green\", \"blue\"];\n}\n```\n\n```js\ncomputedVariables(\n  '--choice-',\n  value =\u003e value[Math.floor(Math.random() * value.length)],\n  window,\n  ['load']\n)\n```\n\nThis recipe would take an array expressed in CSS and return a random choice from one of the supplied options, once when the page loads.\n\nYou can see an example of the last two recipes in the following demo:\n\n- [Computed Variables Plugin](https://codepen.io/tomhodgins/pen/JmvNoQ)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomhodgins%2Fcomputed-variables","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomhodgins%2Fcomputed-variables","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomhodgins%2Fcomputed-variables/lists"}