Introduction

Since SPFx 1.8, we have been able to make web parts aware of what section they reside in on a modern page.

Each SharePoint site theme has four variants: the main variant, a neutral variant, a soft variant, and a strong variant.

You can configure each page section’s background color with one of the four theme’s variants.

Theme variants

When you place a web part on a section with a different background color, the web part has the ability to adapt to that section’s background color.

Microsoft has a great article explaining how to add section support to your web parts, but it does not go into great detail explaining the theme variants.

Theme variants define a lot of different colors, like the background color, body color, button colors, etc.

Every time I write a web part that is "theme-variant-aware," I find myself looking up which theme colors I should use for each element in my web part.

If you dig enough in the SharePoint code (under sp-component-base) you’ll find helpful comments describing how to use each color of a theme variant.

Hoping this will help someone, I extracted the description of each color in theme variants from the comments and created this post.

Keep in mind that this information may change between versions of SPFx. I’ll do my best to keep it up-to-date between versions.

Adding support for theme variants

Before we explore the various colors that are available at your disposal, let’s discuss how to make your web part aware when a section theme variant changes.

When you create a new web part using the Yeoman generator, your web part does not adapt to theme variants. If you change the background color of the section where you web part resides, it mostly stays the same color, like the sample below:

This web part is not theme aware

To make it support theme variants, you need to follow these steps (this code is extracted from Microsoft’s article:

  1. In your web part’s .manifest.json, add the following (I usually add it above the preconfiguredEntries):
"supportsThemeVariants": true,
  1. At the top of your web part’s code (YourWebPartNameWebPart.ts, add the following imports:
import {
  ThemeProvider,
  ThemeChangedEventArgs,
  IReadonlyTheme,
  ISemanticColors
} from '@microsoft/sp-component-base';
  1. In your web part class (just below export default class YourWebPartNameWebPart, add these two variables:
private _themeProvider: ThemeProvider;
private _themeVariant: IReadonlyTheme | undefined;

The _themeProvider variable will store the web part’s instance of the theme provider, which notifies the web part of the currently selected theme. The _themeVariant variable will store the currently selected theme variant.

  1. Add an event handler in your web part to react to changing theme variants:
private _handleThemeChangedEvent(args: ThemeChangedEventArgs): void {
  this._themeVariant = args.theme;
  this.render();
}
  1. In your web part code, add an onInit method to initialize the theme provider, get the initial theme variant, and associate the event handler:
protected onInit(): Promise<void> {
  // Consume the new ThemeProvider service
  this._themeProvider = this.context.serviceScope.consume(ThemeProvider.serviceKey);

  // If it exists, get the theme variant
  this._themeVariant = this._themeProvider.tryGetTheme();

  // Register a handler to be notified if the theme variant changes
  this._themeProvider.themeChangedEvent.add(this, this._handleThemeChangedEvent);

  return super.onInit();
}
  1. In your web part’s render method, you’ll need to add code to pass the theme variant to your component:
public render(): void {
  const element: React.ReactElement<IYourWebPartNameProps > = React.createElement(
    YourWebPartName,
    {
      themeVariant: this._themeVariant,
      // whatever other props you want to pass 
    }
  );

  ReactDom.render(element, this.domElement);
}
  1. In your web part’s component’s props (IYourWebPartNameProps), add a prop for the theme variant:
import { IReadonlyTheme } from '@microsoft/sp-component-base';

export interface IYourWebPartNameProps {
  themeVariant: IReadonlyTheme | undefined;
}
  1. Finally, in your web part’s component’s tsx file, you can use the themeVariant prop to retrieve variant colors:
public render(): React.ReactElement<IYouWebPartNameProps> {

  const { semanticColors }: IReadonlyTheme = this.props.themeVariant;

  return (
    <div style={{backgroundColor: semanticColors.bodyBackground, color: semanticColors.bodyText}}>
      <span className={ styles.title }>Welcome to SharePoint!</span>
      <p className={ styles.subTitle }>This web part is theme variant aware.</p>
    </div>
  );
}
  1. Once your rebuild your web part (gulp build) and add your web part to a page (remember: if you changed the manifest since you added the web part to a page, you need to re-add the web part), your web part will now be aware of section background colors:

You’ll notice that we use the bodyBackground and bodyText colors from the themeVariant. But theme variants define a lot more colors.

Theme variant colors

In a theme variant, you can find the palette colors (e.g.: themeDark, themePrimary, themeSecondary, etc.) and the semantic colors.

Your first instinct might be to try to use the palette colors, but that would require you to know exactly which color is applied to what element. For example, do you know which palette color is used for a button’s background color when a user mouses over it?

Me neither.

The semantic colors, however, describe how you would use each palette color semantically. For example, it tells you that the background color of a hover button should be buttonBackgroundHovered.

Here is the full list of semantic colors available within a theme variant. The list is extracted from Microsoft’s code.

Base colors

ColorDescription
bodyBackgroundThe default color for backgrounds.
bodyStandoutBackgroundThe standout color for highlighted content backgrounds. For highlighted content when there is no emphasis, use the neutral variant instead. This should be a shade darker than bodyBackground in light themes, and a shade lighter in inverted themes.
bodyFrameBackgroundThe color for chrome adjacent to an area with bodyBackground. This can be used to provide visual separation of zones when using stronger colors, when using a divider line is not desired. In most themes, this should match the color of bodyBackground.
bodyFrameDividerUsed as the border between a zone with bodyFrameBackground and a zone with bodyBackground. If bodyBackground and bodyFrameBackground are different, this should be the same color as bodyFrameBackground in order to visually disappear.
bodyDividerDivider lines; e.g. lines that separate sections in a menu, an <HR> element.
disabledBackgroundThe color of the outline around focused controls that don’t already have a border; e.g. menu items
variantBorderThe color of the border that provides contrast between an element, such as a card, and an emphasized background.
variantBorderHoveredHover color of border that provides contrast between an element, such as a card, and an emphasized background.
defaultStateBackgroundBackground color for default/empty state graphical elements; e.g. default icons, empty section that needs user to fill in content, placeholder graphics, empty seats, etc.
errorBackgroundThe background for errors, if necessary, or highlighting the section of the page where the error is present.
blockingBackgroundBackground for blocking issues, which is more severe than a warning, but not as bad as an error.
warningBackgroundBackground for warning messages.
warningHighlightForeground color for warning highlights
successBackgroundBackground for success
inputBorderThe border of a large input control in its resting, state; e.g. the box of a dropdown.
smallInputBorderThe border of a small input control in its resting unchecked state; e.g. the box of an unchecked checkbox.
inputBorderHoveredThe border color of a large hovered input control, such as textbox.
inputBackgroundThe background color of an input, e.g. textbox background.
inputBackgroundCheckedThe background of a checked control; e.g. checked radio button’s dot, checked toggle’s background.
inputBackgroundCheckedHoveredThe background of a checked and hovered control; e.g. checked checkbox’s background color on hover.
inputForegroundCheckedThe foreground of a checked control; e.g. checked checkbox’s checkmark color, checked toggle’s thumb color, radio button’s background color around the dot.
inputFocusBorderAltThe alternate focus border color for elements that already have a border; e.g. text field borders on focus.
buttonBackgroundBackground of a standard button
buttonBackgroundCheckedBackground of a checked standard button; e.g. bold/italicize/underline text button in toolbar
buttonBackgroundHoveredBackground of a hovered standard button
buttonBackgroundCheckedHoveredBackground of a checked and hovered standard button; e.g. bold/italicize/underline text button in toolbar
buttonBackgroundDisabledBackground of a disabled standard button
buttonBackgroundPressedBackground of a pressed standard button; i.e. currently being clicked by mouse
buttonBorderBorder of a standard button
buttonBorderDisabledBorder of a disabled standard button
primaryButtonBackgroundBackground of a primary button
primaryButtonBackgroundHoveredBackground of a hovered primary button
primaryButtonBackgroundPressedBackground of a pressed primary button; i.e. currently being clicked by mouse
primaryButtonBackgroundDisabledBackground of a disabled primary button
primaryButtonBorderBorder of a primary button
accentButtonBackgroundBackground of an accent button (kicker)
menuBackgroundThe background of a menu.
menuDividerThe divider between menu items.
menuIconThe default colors of icons in menus.
menuHeaderThe headers in menus that denote title of a section.
menuItemBackgroundHoveredThe background of a hovered menu item.
menuItemBackgroundPressedThe background of a pressed menu item.
menuItemTextThe text color of a menu item.
menuItemTextHoveredThe text color of a hovered menu item.
listBackgroundThe background color for the entire list.
listTextThe default text color for list item titles and text in column fields.
listItemBackgroundHoveredThe background color of a hovered list item.
listItemBackgroundCheckedThe background color of a checked list item.
listItemBackgroundCheckedHoveredThe background color of a checked and hovered list item.
listHeaderBackgroundHoveredThe background color for a hovered list header.
listHeaderBackgroundPressedThe background color for a pressed list header.

Text colors

ColorDescription
bodyTextThe default color for text.
bodyTextCheckedChecked text color, e.g. selected menu item text.
bodySubtextDe-emphasized text; e.g. metadata, captions, placeholder text.
actionLinkNeutral colored links and links for action buttons.
actionLinkHoveredHover state for neutral colored links and links for action buttons.
linkThe color of a link.
linkHoveredThe color of a hovered link. Also used when the link is active.
disabledTextThe default color for disabled text on top of disabledBackground; e.g. text in a disabled text field, disabled button text.
disabledBodyTextThe default color for disabled text on the default background (bodyBackground).
disabledSubtextDisabled de-emphasized text, for use on disabledBackground
disabledBodySubtextDisabled de-emphasized text, for use on the default background (bodyBackground).
errorTextThe default color of error text, used on bodyBackground.
warningTextThe color of text on errorBackground, warningBackground, blockingBackground, or successBackground.
inputTextThe color of input text.
inputTextHoveredThe color of input text on hover.
inputPlaceholderTextThe color of placeholder text.
buttonTextColor of text in a standard button
buttonTextHoveredColor of text in a hovered standard button
buttonTextCheckedColor of text in a checked standard button
buttonTextCheckedHoveredColor of text in a checked and hovered standard button
buttonTextPressedColor of text in a pressed standard button; i.e. currently being clicked by mouse
buttonTextDisabledColor of text in a disabled standard button
primaryButtonTextColor of text in a primary button
primaryButtonTextHoveredColor of text in a hovered primary button
primaryButtonTextPressedColor of text in a pressed primary button; i.e. currently being clicked by mouse
primaryButtonTextDisabledColor of text in a disabled primary button
accentButtonTextColor of text for accent button (kicker)
listTextThe default text color for list item titles and text in column fields.

Conclusion

Like chameleons, SPFx web parts can change colors to adapt to changing environments and blend in.

With a few lines of code and some knowledge of which semantic colors you can use, you can built awesome web parts that will look good no matter what theme (or theme variant) your site uses.

I hope this helps?

Photo Credits

Photo by Pierre Bamin on Unsplash

Author

Microsoft MVP and PnP Team Member. Independent consultant. Certified SCRUM Master. SharePoint, Office 365 and Dynamics 365 are his favourite toys.

How can I help?

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