Article
17 comments

How to use Theme Colors in SPFX Web Parts

DEPPRECATED This blog post is outdated please implement the new version of this feature see: How to make CSS Variables work in SPFx web parts.

While Waldek Mastykarz and I were working on a new project, we ask ourselves what it needs to create the web part corresponding to the current site theme colors.
After a small research, we found the solution for that.

Tokenize your CSS

It seems like you can use some variable when you are writing your style sheet. The color property, therefore, needs to be formatted in a certain way.
Let’s say you like to use the themes primary color as the background of your web part you need to define the color value in a specific way.

.row {
  padding: 20px;
  background-color: "[theme:themePrimary, default:#0078d7]";
  color: "[theme:white, default:white]"
}

The token “[theme:themePrimary]” gets automatically replaced with the proper theme color. If the framework is unable to find the and replace “theme:themePrimary” the default value gets assigned.
The web part now in the local workbench looks like this:

Workbench Web Part with themed color fallbacks

In Office 365 I applied a dark theme to my site, and the web part looks completely different but according to the color defined in the theme.

Office 365 Workbench web part with theme applied from site

Also, I opened an issue on SPFx-dev-docs because currently the default values are required for local development.

Practical hints on tokens

These tokens to allows the reuse of the colors of the theme and makes your web part perfectly matching to the current theme. During development, it might cause some troubles because the chance is high to mistype theses text-based definitions. There is also no chance that your code editor is capable of auto-complete and recommend these text strings.
The good news is that SPFx uses SASS which allows defining those strings including default values as variables.

// define variables first
$themePrimary: '[theme:themeDarker, default:#0078d7]';
$themeWhite: '[theme:white, default:white]';

.row {
  padding: 20px;
  // use variables
  background-color: $themePrimary;
  color: $themeWhite;
}

Now your code editor can recommend you one the defined color slots while typing the CSS statements.

Import theme slots into your project

Well, the previous example only used two theme slots. In this case, it is easy but is there a complete list of theme options with fallback available. Sadly not at the moment I created that list of SASS variables based on the names of Office UI Fabric and the defined color there.

$ms-greenLight:                 "[theme:greenLight, default:#bad80a]";
$ms-neutralSecondaryAlt:        "[theme:info, default:#767676]";
$ms-neutralLight:               "[theme:infoBackground, default:#eaeaea]";
$ms-magenta:                    "[theme:magenta, default:#b4009e]";
$ms-magentaDark:                "[theme:magentaDark, default:#5c005c]";
$ms-magentaLight:               "[theme:magentaLight, default:#e3008c]";
$ms-neutralDark:                "[theme:neutralDark, default:#212121]";
$ms-neutralLight:               "[theme:neutralLight, default:#eaeaea]";
$ms-neutralLighter:             "[theme:neutralLighter, default:#f4f4f4]";
$ms-neutralLighterAlt:          "[theme:neutralLighterAlt, default:#f8f8f8]";
$ms-neutralPrimary:             "[theme:neutralPrimary, default:#333333]";
$ms-neutralPrimaryAlt:          "[theme:neutralPrimaryAlt, default:#3C3C3C]";
$ms-neutralQuaternary:          "[theme:neutralPrimaryTranslucent50, default:#d0d0d0]";
$ms-neutralQuaternaryAlt:       "[theme:neutralQuaternary, default:#dadada]";
$ms-neutralSecondary:           "[theme:neutralQuaternaryAlt, default:#666666]";
$ms-neutralSecondaryAlt:        "[theme:neutralSecondary, default:#767676]";
$ms-neutralTertiary:            "[theme:neutralSecondaryAlt, default:#a6a6a6]";
$ms-neutralTertiaryAlt:         "[theme:neutralTertiary, default:#c8c8c8]";
$ms-white:                      "[theme:neutralTertiaryAlt, default:#ffffff]";
$ms-orange:                     "[theme:orange, default:#d83b01]";
$ms-orangeLight:                "[theme:orangeLight, default:#ea4300]";
$ms-orangeLighter:              "[theme:orangeLighter, default:#ff8c00]";
$ms-primaryBackground:          "[theme:primaryBackground, default:#0078d7]";
$ms-primaryText:                "[theme:primaryText, default:#0078d7]";
$ms-purple:                     "[theme:purple, default:#5c2d91]";
$ms-purpleDark:                 "[theme:purpleDark, default:#32145a]";
$ms-purpleLight:                "[theme:purpleLight, default:#b4a0ff]";
$ms-red:                        "[theme:red, default:#e81123]";
$ms-redDark:                    "[theme:redDark, default:#a80000]";
$ms-success:                    "[theme:success, default:#107c10]";
$ms-successBackground:          "[theme:successBackground, default:#dff6dd]";
$ms-teal:                       "[theme:teal, default:#008272]";
$ms-tealDark:                   "[theme:tealDark, default:#004b50]";
$ms-tealLight:                  "[theme:tealLight, default:#00b294]";
$ms-themeAccent:                "[theme:themeAccent, default:inherit]";
$ms-themeAccentTranslucent10:   "[theme:themeAccentTranslucent10, default:inherit]";
$ms-themeDark:                  "[theme:themeDark, default:#005a9e]";
$ms-themeDarkAlt:               "[theme:themeDarkAlt, default:#106ebe]";
$ms-themeDarker:                "[theme:themeDarker, default:#004578]";
$ms-themeLight:                 "[theme:themeLight, default:#b3d6f2]";
$ms-themeLightAlt:              "[theme:themeLightAlt, default:inherit]";
$ms-themeLighter:               "[theme:themeLighter, default:#deecf9]";
$ms-themeLighterAlt:            "[theme:themeLighterAlt, default:#eff6fc]";
$ms-themePrimary:               "[theme:themePrimary, default:#0078d7]";
$ms-themeSecondary:             "[theme:themeSecondary, default:#2488d8]";
$ms-themeTertiary:              "[theme:themeTertiary, default:#69afe5]";
$ms-themeTertiaryAlt:           "[theme:themeTertiaryAlt, default:#c8c8c8]";
$ms-white:                      "[theme:white, default:#ffffff]";
$ms-whiteTranslucent40:         "[theme:whiteTranslucent40, default:rgba(255,255,255,.4)]";
$ms-yellow:                     "[theme:yellow, default:#ffb900]";
$ms-yellowLight:                "[theme:yellowLight, default:#fff100]";

View on GitHub

To embed these variables there are basically two ways to use this in your code.

The easy way – Single Web Part

To use these variables, you only need to copy them to your web part CSS, and then you are ready to rock. The correct values then will be replaced during the SASS compilation process. The variables will not end up in your web part code.

The other easy way – Multiple Web Parts

In case you have more than one web part in your project you redefine the variables all over again. Instead, you can save the theme in a file in your web parts root folder.
You can choose any file name you like. On thing, you should take care of that the name starts with an underscore. SASS will interpret this underscore prefixed file as a partial file, and the compiler will not compile a separate CSS file.
So you do not need to have an additional style import in your web part, but you need to import this SASS file into the SASS file of your web part.

// import
@import '@import '../../theming';

You might need to adapt the path depending on where you stored your ‘theming.scss’ file. After this small import statement, all SASS variables are available in your web part style sheet.

.row {
  padding: 20px;
  background-color: $ms-themePrimary; // default theme color
  color: $ms-white; // white
}

Let’s see how this looks in local workbench now,

Local Workbench themed web part

alternatively, in Office 365 on a black themed site.

Office 365 Workbench on black themed site

Alternatively, in a beautiful orange themed site

Office 365 Workbench with a beautiful orange themed Web Part

Now you can make year web parts consistent with the theme of the site the web part is embedded too.

Bonus Content

If you have trouble find out the color available in the theme, there is an easy solution for that. The global variable __themeState__ contains all defined color and slots used by the theme.

Available Theme Slots shown in Web Inspector

This is the complete list:

// Default theme slots of Office theme
{
  "backgroundOverlay": null,
  "primaryBackground": null,
  "primaryText": null,
  "themeDarker": "#013a76",
  "themeDark": "#0156b0",
  "themeDarkAlt": "#0156b0",
  "themePrimary": "#0273eb",
  "themeSecondary": "#5dabfe",
  "themeTertiary": "#93c7fe",
  "themeLight": "#93c7fe",
  "themeLighter": "#c9e3ff",
  "themeLighterAlt": "#c9e3ff",
  "black": null,
  "cmdbarSelected": null,
  "cmdbarSelectedHover": null,
  "neutralDark": null,
  "neutralPrimary": null,
  "neutralPrimaryAlt": null,
  "neutralPrimaryTranslucent50": null,
  "neutralSecondary": null,
  "neutralSecondaryAlt": null,
  "neutralTertiary": null,
  "neutralTertiaryAlt": null,
  "neutralQuaternary": null,
  "neutralQuaternaryAlt": null,
  "neutralLight": null,
  "neutralLighter": null,
  "neutralLighterAlt": null,
  "white": null,
  "blackTranslucent40": null,
  "whiteTranslucent40": null,
  "yellow": null,
  "yellowLight": null,
  "orange": null,
  "orangeLight": null,
  "redDark": null,
  "red": null,
  "magentaDark": null,
  "magenta": null,
  "magentaLight": null,
  "purpleDark": null,
  "purple": null,
  "purpleLight": null,
  "blueDark": null,
  "blueMid": null,
  "blue": null,
  "blueLight": null,
  "tealDark": null,
  "teal": null,
  "tealLight": null,
  "greenDark": null,
  "green": null,
  "greenLight": null,
  "error": null,
  "errorBackground": null,
  "success": null,
  "successBackground": null,
  "alert": null,
  "alertBackground": null,
  "infoBackground": null,
  "info": null,
  "orangeLighter": null,
  "themeLightAlt": "#93c7fe",
  "themeAccent": "#0273eb",
  "themeTertiaryAlt": "#93c7fe",
  "themeAccentTranslucent10": "rgba(2, 115, 235, 0.10)",
  "backgroundImageUri": "none"
}

View on Github

If you have any suggestions how to improve the SASS variable handling or noticed a bug please let me know.

Have fun creating themed SPFX web parts.


Also published on Medium.

17 Comments

  1. The yeoman generator should ask you if you want this and add the file when creating the project…
    Please do every developer a favour and submit this as a improvement suggestion on Github 🙂

    Reply

  2. Hi Stefan, I’ve just tried this and I believe your import is wrong: should it not be
    @import ‘_theming’; ?

    Reply

    • It depends where you store that file. In my case I stored it directly under ‘./src/webparts’ there for I have to navigate two levels up in the folder structure.
      Also as mentioned in the blog post the underscore is not required because of the SASS partial file name convention. These are files that won’t be compiled into a SASS but can be consumed by other SASS files if needed. Check out http://sass-lang.com/guide under partials and imports.

      Reply

  3. Hi Stefan, very helpful article.
    In your post the ‘@import’ statement in one code listing where you import the ‘_theming.scss’ seems accidentally been doubled.
    Also you’ll find a nice listing of the themes colors in the fabric-ui project documentation site itself on github. See https://github.com/OfficeDev/office-ui-fabric-react/blob/14f335d0ca77f09cc9422c1809121e527153c430/packages/office-ui-fabric-react/src/common/_themeOverrides.scss
    Cheers Chris

    Reply

  4. Hi – and thanks for the good intro to theming.
    What I need is to do some further SASS’ing on the colors from the theme – specifically use the lighten() function to calculate a lighter version of one of the theme colors. However, I get a SASS error when I do something like this:
    $level-0-background: “[theme: themePrimary, default: #0078d7]”;
    $level-1-background: lighten($level-0-background, 30% ) ;

    It complains that it needs a color object for the first parameter, and apparently my $level-0-background is not seen as a color when SASS is running. I also tried to use the [theme: … ] expression directly in the function call but that did not help.

    How can I get access to using SASS functions to manipulate the theme colors?

    Regards
    Leif

    Reply

    • Hi Leif,

      yes sadly the string values cannot be use be used with the color functions. You might be able to get the color value applying a string manipulation to the SASS variable and return the color value. This actually could work.

      A problem you then facing is that you get a static color value instead a dynamic. This means you will get actually a default blue just lightened by 30%. This you will get even when the theme uses another color schema. You can only look up another matching color defined in Office UI Fabric.
      /Stefan

      Reply

  5. Hi Stefan,
    I am wondering – will this approach support semantic colors, so that placing a webpart on a section with a background color will reflect this color on the webpart?

    Regards
    Leif

    Reply

  6. I was trying to use themePrimary in a external css file to match my site Theme for the React Content Query Web Part but it does not recognize it any suggestion as why so

    Reply

  7. This happens only on page refresh. is there any option like when the theme is selected, the colors should apply on the go?

    Reply

Leave a Reply

Required fields are marked *.


This site uses Akismet to reduce spam. Learn how your comment data is processed.