Implementing Css Variables

by Will Moody

Implementing Css Variables

Approximate Reading Time: 5 minutes

As of today Can I Use gives 91.65% of browsers now being a capable of using CSS variables so I thought it was time to implement their use on my website. 

Having already used Scss in a modular format and compiled it using my gulp workflow the transition was relatively simple.

First off it was a case of setting up all the base variables that would be used throughout the various scss include files as they are compiled. 

The main files I use to contain all variables used throughout the various components and sections for all my website builds are a normalise, mixins, colours and a config scss. Samples below are the colours and config files.

colors.scss


:root {
  // main
  @include defineColorHSL(--color-primary-darkest, 350, 73%, 14%);
  @include defineColorHSL(--color-primary-darker, 350, 73%, 24%);
  @include defineColorHSL(--color-primary-dark, 350, 73%, 34%);
  @include defineColorHSL(--color-primary, 350, 73%, 44%);
  @include defineColorHSL(--color-primary-light, 350, 73%, 54%);
  @include defineColorHSL(--color-primary-lighter, 350, 73%, 64%);
  @include defineColorHSL(--color-primary-lightest, 350, 73%, 74%);

  // black + white
  @include defineColorHSL(--color-black, 240, 8%, 12%);
  @include defineColorHSL(--color-white, 0, 0%, 100%);
  @include defineColorHSL(--color-lime-green, 120, 61%, 50%);

  // greys
  @include defineColorHSL(--color-white-grey, 0, 0%, 95%);
  @include defineColorHSL(--color-silver, 0, 0%, 90%);
  @include defineColorHSL(--color-silver-grey, 0, 0%, 80%);
  @include defineColorHSL(--color-grey, 0, 0%, 70%);
  @include defineColorHSL(--color-light-grey, 0, 0%, 60%);
  @include defineColorHSL(--color-medium-grey, 0, 0%, 45%);
  @include defineColorHSL(--color-dark-grey, 0, 0%, 30%);

  // feedback
  @include defineColorHSL(--color-danger-darker, 355, 90%, 41%);
  @include defineColorHSL(--color-danger-dark, 355, 90%, 51%);
  @include defineColorHSL(--color-danger, 355, 90%, 61%);
  @include defineColorHSL(--color-danger-light, 355, 90%, 71%);
  @include defineColorHSL(--color-danger-lighter, 355, 90%, 81%);

  @include defineColorHSL(--color-success-darker, 94, 48%, 36%);
  @include defineColorHSL(--color-success-dark, 94, 48%, 46%);
  @include defineColorHSL(--color-success, 94, 48%, 56%);
  @include defineColorHSL(--color-success-light, 94, 48%, 66%);
  @include defineColorHSL(--color-success-lighter, 94, 48%, 76%);

  @include defineColorHSL(--color-info-darker, 220, 90%, 41%);
  @include defineColorHSL(--color-info-dark, 220, 90%, 51%);
  @include defineColorHSL(--color-info, 220, 90%, 61%);
  @include defineColorHSL(--color-info-light, 220, 90%, 71%);
  @include defineColorHSL(--color-info-lighter, 220, 90%, 81%);

  @include defineColorHSL(--color-warning-darker, 46, 100%, 41%);
  @include defineColorHSL(--color-warning-dark, 46, 100%, 51%);
  @include defineColorHSL(--color-warning, 46, 100%, 61%);
  @include defineColorHSL(--color-warning-light, 46, 100%, 71%);
  @include defineColorHSL(--color-warning-lighter, 46, 100%, 81%);
}

config.scss

:root {
  --background-color: var(--color-white);
  --font-color: var(--color-dark-grey);
  // Navigation Variables
  --nav-height: 70px;
  // Consistent settings
  // Transitions
  --transition: all 0.35s cubic-bezier(0.42, 0.0, 0.58, 1.0);
  --transition-l: all 0.35s cubic-bezier(0, 0, 1, 1);
  --transition-e: all 0.35s cubic-bezier(0.25, 0.1, 0.25, 1);
  --transition-ei: all 0.35s cubic-bezier(0.42, 0.0, 1.0, 1.0);
  --transition-eo: all 0.35s cubic-bezier(0.0, 0.0, 0.58, 1.0);
  // General
  --content-width: 1000px;
  // Borders
  --border-radius: 4px;
  --border-width: 1px;
  --border: var(--border-width) solid var(--color-primary);
  --border-white: var(--border-width) solid var(--color-white);
  --border-lightgrey: var(--border-width) solid var(--color-light-grey);
  --border-mediumgrey: var(--border-width) solid var(--color-medium-grey);
  --border-darkgrey: var(--border-width) solid var(--color-dark-grey);
  --border-dotted: var(--border-width) dotted var(--color-light-grey);
  --button-border-radius: var(--border-radius);
  // Shadows
  --box-shadow: 0px 1px 1px var(--color-light-grey);
  --inner-shadow: 0px 1px 1px var(--color-light-grey);
  // Fonts
  --font-size: 14px;
  --footer-font-size: 12px;
  --copyright-font-size: 11px;
  --letter-spacing: 0.05em;
  --word-spacing: 0.1em;
  --header-position: left;
  --line-height: 1.5;
  // Paddings
  --padding-xs: 0.2rem;
  --padding-sm: 0.4rem;
  --padding: 0.6rem;
  --padding-md: 1rem;
  --padding-lg: 1.5rem;
  --padding-xl: 2rem;
  // Margins
  --margin-xs: 0.2rem;
  --margin-sm: 0.4rem;
  --margin: 0.6rem;
  --margin-md: 1rem;
  --margin-lg: 1.5rem;
  --margin-xl: 2rem;
  // Grid
  --grid-gap: 0;
  --grid-columns: 12;
}

// System fonts
$system-font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;

@font-face {
  font-family: 'Avenir';
  src: url('/assets/fonts/AvenirNext_Variable.ttf');
  font-weight: 1 999;
}

@font-face {
  font-family: 'Decovar';
  src: url('/assets/fonts/DecovarAlpha-VF.ttf');
  font-weight: 1 999;
}

$header-font: 'Decovar', sans-serif;
$base-font: 'Avenir', sans-serif;

$small-break: 480px;
$medium-break: 768px;
$big-break: 1024px;

I kept to the same format of separate files for each block of code this gives me more control in locating problems if any arise, it also means that if a given website were to have say no alerts, I could easily remove them from the compiled CSS by blocking out the whole alerts.scss file on build.
This is the apps.scss which pulls all the other scss files together:-


@charset 'utf-8';

@import 'base/normalise';
//@import 'base/debugger';
@import "base/mixins";
@import "base/colors";
@import "base/config";
@import "base/type";
@import "components/media";
@import "components/buttons";
@import "components/tables";
@import "components/forms";
@import "components/icons";
@import "components/links";
@import "components/list";
@import "components/alerts";
@import "components/classes";
@import "grid/grid-settings";
@import "sections/layout";
@import "sections/accessibility";
@import "sections/nav";
@import "sections/header";
@import "sections/content";
@import "sections/testimonials";
@import "sections/contact";
@import "sections/footer";
@import "sections/copyright";
@import "sections/pagination";
@import "sections/sitemap";
@import "sections/blog";
@import "sections/project";
@import "sections/services";
@import "sections/404";
@import "sections/scrollup";

You will notice that the debugger.scss is commented out, this is only used when I have a problem to solve, it's a great way of simply being able to switch on boxing around each element.

The code for debugger.scss is:-


//debugger
*:not(path):not(g) {
  color: hsla(210, 100%, 100%, 0.9) !important;
  background: hsla(210, 100%, 50%, 0.5) !important;
  outline: solid 0.25rem hsla(210, 100%, 100%, 0.5) !important;
  box-shadow: none !important;
}

It's then a simple process of using the CSS variables in the various build files such as the footer.scss file:- 


/* -- footer -- */

footer {
  display: flex;
  display: -ms-flexbox;
  -ms-flex-wrap: wrap;
  flex-wrap: wrap;
  justify-content: center;
  margin: 0;
  padding: var(--padding-xl) var(--padding-md);
  font-size: calc(var(--footer-font-size) + 0.5vmin);
  -ms-flex-item-align: center;
  grid-area: footer;
  background-color: var(--color-white-grey);

  ul {
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
  }

  ul li {
    list-style: none;
    margin: 15px;
  }

  ul li a {
    position: relative;
    display: block;
    width: 2em;
    height: 2em;
    text-align: center;
    line-height: 1;
    background: transparent;
    border-radius: 50%;
    border: 2px solid var(--color-primary);
    font-size: 30px;
    color: var(--color-primary);
    transition: .5s;
  }

  ul li a:before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background: var(--color-primary);
    transition: .5s;
    transform: scale(.9);
    z-index: -1;
  }

  ul li a:hover:before {
    transform: scale(1.2);
    box-shadow: 0 0 15px var(--color-primary);
    filter: blur(3px);
  }

  ul li a:hover {
    color: var(--color-white);
    box-shadow: 0 0 15px var(--color-primary-lighter);
    text-shadow: 0 0 15px var(--color-primary-lighter);
  }

  .icon {
    position: relative;
    top: 0.1em;
    left: 0;
    width: var(--padding-lg);
    height: var(--padding-lg);
    margin: var(--margin) var(--margin-md);
    transition: var(--transition);
    fill: var(--color-primary);

    &:hover {
      transform: scale(1.5);
      fill: var(--color-primary-lighter);
    }
  }
}

@media screen and (min-width: $medium-break) {
  footer {

    ul li a {
      width: 3em;
      height: 3em;
      line-height: 3em;
      margin: var(--margin-md);
    }

    .icon {
      width: 2.25rem;
      height: 2.25rem;
      left: 0;
      top: 0.3em;
    }
  }
}

@media screen and (min-width: $big-break) {
  footer {
    ul li a {
      width: 3.25em;
      height: 3.25em;
    }

    .icon {
      width: 2.5rem;
      height: 2.5rem;
      left: 0;
      top: 0.3em;
    }

  }
}

The only variables that I have found I cannot pass through are the font and media query values.

Which is only to be expected as the W3C spec, states:-

The var() function can be used in place of any part of a value in any property on an element. The var() function can not be used as property names, selectors, or anything else besides property values. (Doing so usually produces invalid syntax, or else a value whose meaning has no connection to the variable.) 

As the font and media queries are not HTML elements, it's only to be expected.

I found the transition relatively painless as I use Visual Studio Code for my code editing, this has a really nice find and replace function which allows for text replacement though-out a selection of files. It was then a case of replacing the original scss variable $white with the new CSS variable var(--color-white), simple.