Using CSS Variables in AEM with Sass

The Challenge:

Our client had multiple standalone co-branded microsites with two particular pain points:

  1. Microsites were difficult to maintain and were frequently out of sync with corporate branding standards.
  2. Creating a new microsite was difficult for an author and frequently required a developer to guide the process.
We needed a solution that would:
  1. Allow AEM components from the company site to be used on microsites
  2. Provide a tool to define brand colors and fonts for authors
  3. Enable authors to create a new microsite without a developer

The Solution:

CSS Variables! I had previously used CSS variables on a Polymer project with another client, but they were not part of my everyday development. I had (mistakenly) assumed they required some Polymer-specific magic in order to work reliably. Oh, but how wrong I was!

Why should you consider CSS variables?

  • Widespread support – 90%+ of all browsers in the US and 87.5% of browsers worldwide support CSS variables according to cainuse.com.
  • CSS Variables + Sass = ♥ – CSS variables can be used in conjunction with Sass variables.
  • No variables? No problem – CSS variables do not have to be defined at compilation time*.

Defining variables

Defining a CSS variable is surprisingly straightforward. You only need to set the scope and a variable name/value preceded by two hyphens. (In our case, we want the variables to be applied everywhere, so our scope is :root. )
:root {
     --my-color-variable: blue;
     --my-font-stack-variable: 'Helvetica', 'Arial', sans-serif;
}

Depending on your requirements, this can be included in the <head> or in a separate CSS file that can be loaded via <link> tag.

To reference your new variables, replace the CSS property value with the variable name:

.myClass {
     background-color: var(--my-color-variable);
     height: 5rem;
     width: 2.5rem;
}
.anotherClass {
     color: var(--my-color-variable);
     font-family: var(--my-font-stack-variable);
}

Note: CSS variables aren’t limited to colors or font stacks- they can be used for any property, including transforms!

Defining fallbacks

What if your authored overrides are optional? No problem! CSS variables allows you to define as many or as few fallbacks as you like:
.myClass {
     background-color: var(--my-color-variable, #F00);
     height: 5rem;
     width: 2.5rem;
}
.anotherClass {
     color: var(--my-color-variable, #00F);
     font-family: var(--my-font-stack-variable, 'Georgia', 'Times New Roman', serif);
}

Using CSS Variables in Sass Mixins

This client has a global footprint and their content has been translated into multiple languages. Many languages have characters that are not available in the default font. We have font-family mixins that can serve up different font stacks based on the <html lang="..."> attribute to handle this challenge. (Even if localization is not a concern, it can be handy to use a mixin with an optional parameter to pass in a CSS Variable.)

$default-font-family: ...

@mixin font-family-main ($customFonts: null) {
  @if $customFonts {
    font-family: var($customFonts, $default-font-family);

    /* Chinese simplified */
    :lang(zh-cn) &,
    :lang(zh-sg) & {
      font-family: var($customFonts, 'Helvetica', 'Arial', 'HeisASC', sans-serif);
    } 

    /* Chinese traditional */ 
    :lang(zh-tw) &,
    :lang(zh-hk) & {
      font-family: var($customFonts, 'Helvetica', 'Arial', 'HeitASC', sans-serif);
    }

  } @else {
    font-family: $default-font-family;

    /* Chinese simplified */
    :lang(zh-cn) &,
    :lang(zh-sg) & {
      font-family: 'Helvetica', 'Arial', 'HeisASC', sans-serif;
    }
    
    /* Chinese traditional */ 
    :lang(zh-tw) &,
    :lang(zh-hk) & {
      font-family: 'Helvetica', 'Arial', 'HeitASC', sans-serif;
    }
  }
}
(Apologies for the random bolding; the syntax highlighter doesn’t know what to do with Sass mixin syntax.)
 

What about the 10-12% of browsers that don’t support CSS variables?

Enter the CSS Vars Ponyfill polyfill. According to ponyfoo.com, “A ponyfill is almost the same as a polyfill, but not quite. Instead of patching functionality for older browsers, a ponyfill provides that functionality as a standalone module you can use.”

After including the CSS Vars Ponyfill javascript via your preferred method,  invoke it after the CSS variables have been included on the page with cssVars().  The ponyfill finds the CSS variables and emulates their effect by adding CSS to the <head>, converting the variable values to plain CSS.

*Modern browsers ignore undefined CSS variables, but the ponyfill will throw a console warning if a variable is undefined. This can be alleviated by defining variables in the Sass using the default values and then re-defining the variables with the authored values by including them later in the <head> or with the options.silent parameter.


Summary

  • CSS Variables are really cool and really ready for primetime.
  • They can work in place of or alongside CSS preprocessor variables.
  • Even obsolete browsers can join in the fun using the CSS Vars Ponyfill.
Sources:
Photo by Zbysiu Rodak on Unsplash

Leave a Reply

avatar
  Subscribe  
Notify of