├── LICENSE ├── README.md ├── demo ├── browser.html ├── bundle.js ├── cjs.html ├── cjs.js └── module.html ├── index.browser.js ├── index.es.js ├── index.js └── package.json /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Tommy Hodgins 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # computed-variables 2 | 3 | Easy to use event-driven CSS variables 4 | 5 | ## About 6 | 7 | Computed 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. 8 | 9 | Have 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. 10 | 11 | > Similar in concept to [jsincss](https://github.com/tomhodgins/jsincss), except jsincss is for rules and stylesheets, and computed variables is for CSS variables. 12 | 13 | ## Downloading 14 | 15 | You can download computed-variables and add it to your codebase manually, or download it with npm: 16 | 17 | ```bash 18 | npm install computed-variables 19 | ``` 20 | 21 | Another option is linking to the module directly from a CDN like unpkg: 22 | 23 | ```html 24 | 27 | ``` 28 | 29 | ## Importing 30 | 31 | You can import the plugin into your own JavaScript modules in a couple of ways. 32 | 33 | The 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: 34 | 35 | ```js 36 | import computedVariables from './index.es.js' 37 | ``` 38 | 39 | You can also use `require()` to load this plugin instead with a bundler like Webpack or Parcel: 40 | 41 | ```js 42 | const computedVariables = require('computed-variables') 43 | ``` 44 | 45 | Once you have imported this plugin into your module, you can use the plugin as `computedVariables()` 46 | 47 | ## Usage 48 | 49 | The 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. 50 | 51 | The plugin has the following format: 52 | 53 | ```js 54 | computedVariables(name, func, selector, events) 55 | ``` 56 | 57 | - `name` is a string starting with `--` that the custom selector(s) should match 58 | 59 | - `func` is a JavaScript function that accepts three arguments: 60 | - - `value`: the value originally set to the property in CSS or HTML 61 | - - `event`: the event object from JavaScript when the style recomputed 62 | - - `tag`: the CSS rule or DOM tag containing the custom property 63 | 64 | - `selector` is string containing either `'window'` or a CSS selector 65 | 66 | - `events` is an array of events to add event listeners for, quoted as strings: (eg. `['load', resize']`) 67 | 68 | The default `selector` is `window`, and the default list of `events` is `['load', 'resize', 'input', 'click', 'recompute']`. 69 | 70 | You can also create and listen for custom events with JavaScript using `new Event()` and `dispatchEvent()` for total control over when computed-variables recomputes styles. 71 | 72 | ## Examples 73 | 74 | ### Exposing browser viewport dimensions to CSS 75 | 76 | This example shows and example of exposing properties from the `window` object, on the `load` and `resize` event: 77 | 78 | ```html 79 | 89 | ``` 90 | 91 | This 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: 92 | 93 | ```css 94 | :root { 95 | --innerWidth: "innerWidth"; 96 | --innerHeight: "innerHeight"; 97 | } 98 | ``` 99 | 100 | Would result in the `` 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. 101 | 102 | Alternatively, we can also write custom variables in HTML in addition to CSS - suppose we had this in our DOM instead: 103 | 104 | ```html 105 | 109 | ``` 110 | 111 | This would result in functionally the same thing - the `` element would have custom `--innerWidth` and `--innerHeight` variables that equalled their `window.innerWidth` and `window.innerHeight`. 112 | 113 | ### Exposing mouse and touch pointer coordinates 114 | 115 | ```css 116 | :root { 117 | --cursorX: "clientX"; 118 | --cursorY: "clientY"; 119 | } 120 | ``` 121 | 122 | ```js 123 | computedVariables( 124 | '--cursor', 125 | (value, event) => event[value] || event.touches[0][value], 126 | window, 127 | ['mousemove', 'touchstart'] 128 | ) 129 | ``` 130 | 131 | With 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. 132 | 133 | ### Exposing element dimensions and offset 134 | 135 | ```html 136 |
142 | ``` 143 | 144 | ```js 145 | computedVariables( 146 | '--offset', 147 | (value, event, tag) => tag[value], 148 | window, 149 | ['load', 'resize'] 150 | ) 151 | ``` 152 | 153 | This 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. 154 | 155 | For a demo that uses the last two recipes, check out: 156 | 157 | - [Box Shadow (exposing cursor events and element properties)](https://codepen.io/tomhodgins/pen/XxYjqV) 158 | 159 | ### Exposing window scroll position via `document.scrollingElement` 160 | 161 | ```css 162 | :root { 163 | --window-scroll-top: "scrollTop"; 164 | --window-scroll-left: "scrollLeft"; 165 | } 166 | ``` 167 | 168 | ```js 169 | computedVariables( 170 | '--window-scroll-', 171 | value => document.scrollingElement[value], 172 | window, 173 | ['load', 'scroll'] 174 | ) 175 | ``` 176 | 177 | This 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. 178 | 179 | ### Exposing element scroll position 180 | 181 | ```html 182 |