Package Exports
- css-vars-ponyfill
- css-vars-ponyfill/dist/css-vars-ponyfill.esm.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (css-vars-ponyfill) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
css-vars-ponyfill 
A ponyfill that provides client-side support for CSS custom properties ("CSS variables") in legacy browsers.
Why
Legacy "support" for CSS custom properties often means using a CSS preprocessor such as PostCSS or Sass to perform a one-time transformation of custom properties to static values prior to deployment. This approach allows developers to define variables and values using the CSS custom property syntax, but it fails to deliver one of the primary benefits of CSS custom properties: the ability to set values dynamically at runtime and have the DOM update accordingly.
This ponyfill was created specifically to address this issue. There are limitations to consider (see below), but if these limitations are acceptable then this ponyfill should simplify working with custom properties when legacy support is required.
Features
- Client-side transformation of CSS custom properties to static values in legacy browsers
- Unified interface for modifying runtime values in modern and legacy browsers
- Persistant changes on subsequent calls in legacy browsers
- Support for custom property fallback values
- UMD and ES6 modules available
- Lightweight (less than 5k min+gzip) and dependency-free
Limitations
- Custom property support is limited to
:root
declarations - The use of
var()
is limited to property values (per W3C specification)
Installation
NPM:
npm install css-vars-ponyfill
Git:
git clone https://github.com/jhildenbiddle/css-vars-ponyfill.git
CDN (unpkg.com shown, also on jsdelivr.net):
<!-- ES5 in file.html (latest v1.x.x) -->
<script src="https://unpkg.com/css-vars-ponyfill@1"></script>
<script>
cssVars({
// options...
});
</script>
<!-- ES6 module in file.html (latest v1.x.x) -->
<script type="module">
import cssVars from 'https://unpkg.com/css-vars-ponyfill@1/dist/css-vars-ponyfill.esm.min.js';
cssVars({
// options...
});
</script>
// ES6 module in file.js (latest v1.x.x)
import cssVars from 'https://unpkg.com/css-vars-ponyfill@1/dist/css-vars-ponyfill.esm.min.js';
cssVars({
// options...
});
Example
HTML:
<link rel="stylesheet" href="style.css">
<style>
:root {
--color2: green;
}
.two {
color: var(--color2);
}
</style>
External CSS:
/* style.css */
:root {
--color1: red;
}
.two {
color: var(--color1);
}
JavaScript (see Options for details):
// Call using default options
cssVars();
CSS is generated and appended to the DOM:
<style id="css-vars-ponyfill">
:root {
--color1: red;
--color2: green;
}
.one {
color: red;
color: var(--color1);
}
.two {
color: green;
color: var(--color2);
}
</style>
To add or modify values, call cssVars()
using options.variables...
// Call using default options
cssVars({
variables: {
color1: 'blue',
color2: 'purple'
}
});
… and the previously generated CSS will be updated.
<style id="css-vars-ponyfill">
:root {
--color1: blue;
--color2: purple;
}
.one {
color: blue;
color: var(--color1);
}
.two {
color: purple;
color: var(--color2);
}
</style>
Options
Example
// Default values shown
cssVars({
include : 'link[rel=stylesheet],style',
exclude : '',
onlyLegacy: true,
onlyVars : true,
preserve : false,
silent : false,
updateDOM : true,
variables : {
// ...
},
onSuccess(cssText) {
// ...
},
onError(message, node) {
// ...
},
onWarning(message) {
// ...
},
onComplete(cssText, styleNode) {
// ...
}
});
options.include
- Type:
string
- Default:
"link[rel=stylesheet],style"
CSS selector matching <link rel="stylesheet">
and <style>
nodes to process. The default value includes all style and link nodes.
Example
cssVars({
// Include only <link rel="stylesheet"> nodes
// with an href that does not contains "bootstrap"
include: 'link[rel=stylesheet]:not([href*=bootstrap])'
});
options.exclude
- Type:
string
- Default: none
CSS selector matching <link rel="stylesheet">
and <style>
nodes to exclude from those matched by options.include.
Example
cssVars({
// Of matched 'include' nodes, exclude any node
// with an href that contains "bootstrap"
exclude: '[href*=bootstrap]'
});
options.onlyLegacy
- Type:
boolean
- Default:
true
Determines if the ponyfill will only generate legacy-compatible CSS in browsers that lack native support (i.e., legacy browsers).
When true
, the ponyfill will only generate legacy-compatible CSS, trigger callbacks, and (optionally) update the DOM in browsers that lack native support. When false
, the ponyfill will treat all browsers as legacy, regardless of their support for CSS custom properties.
Example
cssVars({
onlyLegacy: true
});
options.onlyVars
- Type:
boolean
- Default:
true
Determines if CSS rulesets and declarations without a custom property value should be removed from the ponyfill-generated CSS.
When true
, rulesets and declarations without a custom property value will be removed from the generated CSS, reducing CSS output size. When false
, all rulesets and declarations will be retained in the generated CSS.
Note: @font-face
and @keyframes
require all declarations to be retained if a CSS custom property is used anywhere within the ruleset.
Example
CSS:
:root {
--color: red;
}
h1 {
font-weight: bold;
}
p {
margin: 20px;
padding: 10px;
color: var(--color);
}
JavaScript:
cssVars({
onlyVars: true
});
Output when onlyVars: true
:root {
--color: red;
}
p {
color: red;
color: var(--color);
}
Output when onlyVars: false
:root {
--color: red;
}
h1 {
font-weight: bold;
}
p {
margin: 20px;
padding: 10px;
color: red;
color: var(--color);
}
options.preserve
- Type:
boolean
- Default:
false
Determines if the original CSS custom property declaration will be retained in the ponyfill-generated CSS.
When true
, the original custom property declarations are available in the ponyfill-generated CSS along with their static values. When false
, only static values are available in the ponyfill-generated CSS.
Example
CSS:
:root {
--color: red;
}
p {
color: var(--color);
}
JavaScript:
cssVars({
preserve: true
});
Output when preserve: true
:root {
--color: red;
}
p {
color: red;
color: var(--color);
}
Output when preserve: false
p {
color: red;
}
options.silent
- Type:
boolean
- Default:
false
Determines if warning and error messages will be displayed on the console.
When true
, messages will be displayed on the console for each warning and error encountered while processing CSS. When false
, messages will not be displayed on the console but will still be available using the options.onWarning and options.onSuccess callbacks.
Example
CSS:
@import "fail.css"
p {
color: var(--fail);
}
p {
color: red;
JavaScript:
cssVars({
silent: false
});
Console:
> CSS XHR error: "fail.css" 404 (Not Found)
> CSS transform warning: variable "--fail" is undefined
> CSS parse error: missing "}"
options.updateDOM
- Type:
boolean
- Default:
true
Determines if the ponyfill will update the DOM after processing CSS custom properties.
When true
, legacy browsers will have a <style>
node appended with ponyfill-generated CSS and modern browsers with native support will apply options.variables as custom properties using the native style.setProperty() method. When false
, the DOM will not be updated by the polyfill in either modern or legacy browsers, but ponyfill-generated CSS can be accessed with either the options.onSuccess or options.onComplete callback.
Example
cssVars({
updateDOM: true
});
options.variables
- Type:
object
- Default:
{}
A map of custom property name/value pairs. Property names can omit or include the leading double-hyphen (—
), and values specified will override previous values.
Legacy browsers will process these values while generating legacy-compatible CSS. Modern browsers with native custom property support will apply these values using the native setProperty() method when options.updateDOM is true
.
Example
cssVars({
variables: {
// without leading '--'
color1 : 'red',
// with leading '--'
'--color2': 'green'
}
});
options.onSuccess
- Type:
function
- Arguments:
- cssText: A
string
of CSS text fromnode
andurl
- cssText: A
Callback after all CSS has been processed and legacy-compatible CSS has been generated, but before the legacy CSS has been appended to the DOM. Allows modifying the CSS data by returning any string
value (or false
to skip) before options.onComplete is triggered.
Example
// Beautify CSS output (requires separate beautify lib)
cssVars({
onSuccess(cssText, node, url) {
const newCssText = beautify(cssText);
return newCssText;
}
});
options.onError
- Type:
function
- Arguments:
- message: The error message
- node: The source node
object
reference - xhr: The XHR
object
containing details of the failed request - url: The source URL
string
(<link>
href or@import
url)
Callback after a CSS parsing error has occurred or an XHR request has failed.
Example
HTML:
<link rel="stylesheet" href="path/to/fail.css">
JavaScript:
cssVars({
onError(message, node, xhr) {
console.log(message); // 1
console.log(node); // 2
console.log(xhr.status); // 3
console.log(xhr.statusText); // 4
console.log(url); // 5
}
});
// 1 => 'CSS XHR error: "fail.css" 404 (Not Found)'
// 2 => <link rel="stylesheet" href="path/to/fail.css">
// 3 => '404'
// 4 => 'Not Found'
// 5 => 'path/to/fail.css'
options.onWarning
- Type:
function
- Arguments:
- message: The warning message
Callback after each CSS parsing warning has occurred.
Example
CSS:
p {
color: var(--fail);
}
JavaScript:
cssVars({
onWarning(message) {
console.log(message); // 1
}
});
// 1 => 'CSS transform warning: variable "--fail" is undefined'
options.onComplete
- Type:
function
- Arguments:
- cssText: A
string
of concatenated CSS text from all nodes in DOM order - styleNode: An
object
reference to the appended<style>
node
- cssText: A
Callback after all CSS has been processed, legacy-compatible CSS has been generated, and (optionally) the DOM has been updated.
Example
cssVars({
onComplete(cssText, styleNode) {
// ...
}
});
Attribution
This ponyfill includes code based on the following projects. Many thanks to the authors and contributors for helping to make this project possible.
Contact
- Create a Github issue for bug reports, feature requests, or questions
- Follow @jhildenbiddle for announcements
License
This project is licensed under the MIT License. See the LICENSE for details.