Skip to content

dead-claudia/postcss-css-variables

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

53 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

npm version Build Status

PostCSS CSS Variables

PostCSS plugin to transform CSS Custom Properties(CSS variables) syntax into a static representation. This plugin provides a future-proof way of using most of CSS variables features.

CSS variables or CSS Custom Properties limited subset polyfill/shim.

We strive for the most complete transformation but we/no plugin can achieve true complete parity according to the specification because of the DOM cascade unknowns.

Install

npm install postcss-css-variables --save-dev

Try it before you install it!

Add some PostCSS and it will show you the transformed/compiled CSS.

Usage

You can try any of these examples on the code playground.

var postcss = require('postcss');
var cssvariables = require('postcss-css-variables');

var fs = require('fs');

var mycss = fs.readFileSync('input.css', 'utf8');

// Process your CSS with postcss-css-variables
var output = postcss([
		cssvariables(/*options*/)
	])
	.process(mycss)
	.css;

console.log(output);

For more general PostCSS usage, see this section

At-rule support @media, @support, etc

You can add rules that declare CSS variables nested inside at-rules. You can even nest the at-rules however deep you want.

The following CSS:

:root {
	--width: 100px;
}

@media (max-width: 1000px) {
	:root {
		--width: 200px;
	}
}

.box {
	width: var(--width);
}

will be processed to:

.box {
	width: 100px;
}

@media (max-width: 1000px) {
	.box {
		width: 200px;
	}
}

Pseudo class and elements

.foo {
	--foo-color: #ff0000;
	color: var(--foo-color);
}

.foo:hover {
	--foo-color: #00ff00;
}

will be processed to:

.foo {
	color: #ff0000;
}

.foo:hover {
	color: #00ff00;
}

Nested rules

When using this feature, postcss-css-variables will output invalid CSS by itself(but you did input invalid CSS anyway). This feature is best paired with postcss-nested in order to properly expand the rules.

Run postcss-nested before postcss-css-variables so that postcss-nested can properly expand the & references before we start resolving variable values.

var postcss = require('postcss');
var cssvariables = require('postcss-css-variables');
var nestedcss = require('postcss-nested');

var fs = require('fs');

var mycss = fs.readFileSync('input.css', 'utf8');

// Process your CSS with postcss-css-variables
var output = postcss([
		// Flatten/unnest rules
		nestedcss,
		// Then process any CSS variables
		cssvariables(/*options*/)
	])
	.process(mycss)
	.css;

console.log(output);

Simple example

The following CSS:

.box-foo {
	--some-width: 150px;
	width: var(--some-width);

	.box-bar {
		width: var(--some-width);
	}
}

will be processed to:

.box-foo {
	width: 150px;

	.box-bar {
		width: 150px;
	}
}

Complex example

The following CSS:

:root {
	--some-width: 150px;
}

.box-foo {
	width: var(--some-width);

	.box-bar {
		width: var(--some-width);
	}
}

@media (max-width: 800px) {
	.box-foo {
		--some-width: 300px;
	}
}

will be processed to:

.box-foo {
	width: 150px;

	.box-bar {
		width: 150px;
	}

	@media (max-width: 800px) {
		.box-bar {
			width: 300px;
		}
	}
}

@media (max-width: 800px) {
	.box-foo {
		width: 300px;
	}
}

Interoperability

postcss-css-variables plays really nice with postcss-nested in order to get a larger subset of CSS variables features. See Nested rules, Usage section

If you are using postcss-custom-properties previously, we have a compatible feature set and more so you can switch over without having to refactor any of your code. You can just start writing the new awesome stuff.

Why?

This plugin was spawned out of a discussion on the cssnext repo and a personal need.

There is another similar plugin available, postcss-custom-properties, which at the moment, covers less of the CSS-variable/custom-property draft/spec compared to this plugin. It also happened to not cover the feature I was after and after dealing with it, making an incomplete prototype piggybacking off of it; I decided to write my own starting from scratch. I do use some of the same/similar unit tests because that just makes sense to get proper code coverage.

Differences from postcss-custom-properties

The main features that wepostcss-css-variables add/provide are:

  • No limitation on what scope CSS variables can be declared or used (:root or wherever)
    • Proper value substitution based on explicit DOM/structure traversal
  • At-rule support @media, @support, etc
  • Nested rules which can be fully deduced with postcss-nested.
  • Pseudo class/element support :hover, etc

Syntax

A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS). A property must be in a rule.

Note: :root is nothing more than the selector for the root DOM node. You could use any other selector (class, id, etc)

:root {
	--foo-width: 100px;
	--foo-bg-color: rgba(255, 0, 0, 0.85);
}

A custom property can be declared multiple times.

See: W3C Draft: CSS Custom Properties for Cascading Variables, section 2 for more information.

.foo {
	width: var(--foo-width);
	/* You can even provide a fallback */
	background: var(--foo-bg-color, #ff0000);
}

See: W3C Draft: CSS Custom Properties for Cascading Variables, section 3 for more information.

Options:

preserve (default: false)

Allows you to preserve custom properties & var() usage in output. Allowed values:

  • false: Removes --var declarations and replaces var() with their resolved/computed values.
  • true: Keeps var() declarations in the output and has the computed value as a fallback declaration. Also keeps computed --var declarations
  • 'computed': Keeps computed --var declarations in the output. Handy to make them available to your JavaScript.

variables (default: {})

Define an object map of variables in JavaScript that will be declared at the :root scope.

Can be a simple key-value pair or an object with a value property and an optional isImportant bool property

The object keys are automatically prefixed with -- (according to CSS custom property syntax) if you do not provide it.

var postcss = require('postcss');
var cssvariables = require('postcss-css-variables');

postcss([
	cssvariables({
		variables: {
			'--some-var': '100px',
			'--other-var': {
				value: '#00ff00'
			},
			'--important-var': {
				value: '#ff0000',
				isImportant: true
			}
		}
	})
])
.process(css, opts);

Quick Reference/Notes

Testing

We have a suite of Mocha tests. If you see something that doesn't have coverage, make an issue or pull request.

Run once:

npm install

Run whenever you want to test:

npm run test

About

PostCSS plugin to transform CSS Custom Properties(CSS variables) syntax into a static representation

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 99.8%
  • Other 0.2%