CSS Custom Properties
Aleksandra Hristov
10 July 2018, Skopje @ Front-end meetup
CSS Custom Properties
Variables
//SCSS
$text-color: #565656;
.component {
color: $text-color;
}
/* LESS */
@text-color: #565656;
.component {
color: @text-color;
}
/* CSS */
:root {
/* :root is on the level of the html tag, with more specificity */
--text-color: #565656;
}
.component {
color: var(--text-color);
}
Declaration & Usage
/* CSS */
:root {
--text-color: #565656;
}
.component {
color: var(--text-color, red);
/* red is fallback if --text-color is not defined */
}
Fallback values
/* CSS */
:root {
--text-color: #565656;
}
.component {
color: red;
color: var(--text-color, var(--text-color-2, red));
/* red is fallback if --text-color and --text-color-2 are not defined */
}
:root{
--main-color: #4d4e53;
--main-bg: rgb(255, 255, 255);
--logo-border-color: rebeccapurple;
--header-height: 68px;
--content-padding: 10px 20px;
--base-line-height: 1.428571429;
--transition-duration: .35s;
--external-link: "external link";
--margin-top: calc(2vh + 20px);
/* Valid CSS custom properties can be reused later in, say, JavaScript. */
--foo: if(x > 5) this.width = 10;
}
Declaration examples
:root{
--indent-size: 10px;
--indent-xl: calc(2*var(--indent-size));
--indent-l: calc(var(--indent-size) + 2px);
--indent-s: calc(var(--indent-size) - 2px);
--indent-xs: calc(var(--indent-size)/2);
}
Operations
:root{
--spacer: 10;
}
.box{
padding: var(--spacer)px 0; /* DOESN'T work */
padding: calc(var(--spacer)*1px) 0; /* WORKS */
}
Watch out for unitless operations
Difference with pre-processor variables is that they are static
//Compiled
.component {
color: red;
}
//SCSS
$text-color: red;
.component {
color: $text-color;
}
$text-color: blue;
Difference with pre-processor variables is that they are static
Difference with pre-processor variables is that they are static
//Compiled
.component {
color: blue;
}
.component {
color: red;
}
//SCSS
$text-color: red;
.component {
color: $text-color;
}
$text-color: blue;
.component {
color: $text-color;
}
Difference with pre-processor variables is that they are static
Pre-processor variables have limitations:
- You cannot change them dynamically.
- They are not aware of the DOM’s structure.
- They cannot be read or changed from JavaScript.
Custom properties are dynamic
.component {
color: var(--text-color); //blue
}
:root {
--text-color: blue;
}
:root {
--text-color: red;
}
/* CSS */
:root {
--text-color: red;
}
.component {
color: var(--text-color);
}
:root {
--text-color: blue;
}
Custom properties are dynamic
with specific scope
.component {
color: var(--text-color); //blue
--text-color: blue;
}
:root {
--text-color: red;
}
/* CSS */
:root {
--text-color: red;
}
.component {
color: var(--text-color);
--text-color: blue;
}
with specific scope
different scope requires explicit rules
.component span {
--text-color: blue;
}
.component {
color: var(--text-color);
}
:root {
--text-color: red;
}
/* SCSS */
:root {
--text-color: red;
}
.component {
color: var(--text-color);
span {
--text-color: blue;
color: var(--text-color);
}
}
.component span {
--text-color: blue;
color: var(--text-color);
}
.component {
color: var(--text-color);
}
:root {
--text-color: red;
}
different scope requires explicit rules
rules
remove inheritance
/* CSS */
* {
--text-color: initial;
/* remove inheritance */
}
.component {
color: var(--text-color);
span {
--text-color: inherit;
/* explicitly inherit from parent */
}
}
and with specific overrides in different contexts
//Compiled for screens > 900px
.component {
color: var(--text-color); //red
}
/* CSS */
:root {
--text-color: red;
}
.component {
color: var(--text-color);
}
@media (max-width: 900px) {
:root {
--text-color: blue;
}
}
and with specific overrides in different contexts
//Compiled for screens > 900px
.component {
color: var(--text-color); //red
}
//Compiled for screens <= 900px
.component {
color: var(--text-color); //blue
}
and with specific overrides in different contexts
when you want to override a css custom property,
just change its value
Combining with
pre-processor variables
//SCSS mixin to include
//https://github.com/malyw/css-vars/blob/master/css-vars.scss
$color-basic: #ff0000; //red
@include css-vars((
--text-color: $color-basic;
));
.component {
color: var(--text-color);
}
or check out https://codepen.io/vank0/pen/kkGvAb
var element = document.documentElement;
// get variable from inline style
element.style.getPropertyValue("--text-color");
// get variable from wherever
getComputedStyle(element).getPropertyValue("--text-color");
// set variable on inline style
element.style.setProperty("--var-value", jsVar + 10);
Usage in JavaScript
Example usage:
Browser support

63
70
18
12
Custom
properties
31 (2014)
49 (2016)
15 (04.2017)
9.1
(2016)
@supports
22
(2013)
28
(2013)
12 (2015)
9
(2015)
Grid
52
(03.2017)
57
(03.2017)
16 (10.2017)
10.1
(03.2017)
IE 10+ (2012)
Old spec w/ -ms-
current versions 12.2018
.selector {
/* Styles that are supported in old browsers */
}
@supports (property:value) {
.selector {
/* Styles for browsers that support the specified property */
}
}
Feature queries
.selector { }
@supports ( (--a: 0)) {
/* Styles that are supported in old browsers */
.selector { }
}
@supports ( not (--a: 0)) {
/* Styles for browsers that support the specified property */
.selector { }
}
You can use AWESOME CSS
today!
Real-life examples



One layout -
multiple solutions
Demo
THANK YOU!
any questions?
aleksandra.hristov@netcetera.com
@alexhris
medium.com/@alexhris
- Differences between types of CSS variables
https://css-tricks.com/difference-between-types-of-css-variables/
Explore
css-custom-properties
By alexhris
css-custom-properties
- 1,012