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); 
}
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

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

Explore

css-custom-properties

By alexhris

css-custom-properties

  • 1,012