If you’ve ever built an SPFx web part and noticed it looks like an uninvited guest — sporting a bright blue palette on a red-themed SharePoint site — you already know why reading the current theme matters. Your web part should blend in, not stick out like a sore thumb.
In this tutorial, I’ll walk you through exactly how to get the current theme in SPFx. I’ll cover three practical methods, give you real code you can drop into your project, and explain when to use each approach.
Why Theme Awareness Matters in SPFx
When SharePoint scaffolds a new web part for you, it ships with a fixed blue palette baked into the CSS. That’s fine for demos, but in the real world, every organization has its own branding. Site admins pick red themes, green themes, dark themes — and your hard-coded blue buttons will clash with all of them.
Getting the current theme lets your web part:
- Automatically adapt colors to whatever theme the site is using
- Respond when users switch section backgrounds (neutral, soft, strong, etc.)
- Work correctly in Teams too, including dark mode and high-contrast mode
- Look like it belongs — not like a third-party plugin that got dropped in
Check out SPFx Web Part Audience Targeting
Understanding SPFx Theming Basics
SharePoint themes are made up of tokens. Instead of hard-coding #0078d7, you reference a token like themePrimary, and SharePoint swaps in the right hex value at runtime.
There are two layers you’ll deal with:
- Palette colors — things like
themePrimary,themeDark,neutralSecondary. These come from the site’s color scheme. - Semantic colors — things like
bodyBackground,bodyText,buttonText. These are higher-level abstractions that map to palette colors based on context.
When possible, use semantic colors. They’re more stable and meaningful — bodyText always means “the color text should be on the page body,” regardless of the underlying palette.
Method 1: Using SPFx Theme Tokens in SCSS
This is the easiest approach, and it requires zero TypeScript. You just use a special syntax directly in your SCSS file, and SPFx does the rest.
How it works:
Instead of writing a fixed color:
.button {
background-color: #0078d7;
}
You write a theme token reference:
.button {
background-color: "[theme: themePrimary, default: #0078d7]";
}
The @microsoft/load-themed-styles package — which is bundled with SPFx — scans your CSS at load time, finds these token strings, and replaces them with the actual color from the current site theme. The default value is your safety net for environments where the token isn’t available.
A real example — updating a scaffolded web part:
Open your .module.scss file and update your selectors:
.row {
padding: 20px;
background-color: "[theme: themeDark, default: #005a9e]";
}
.button {
background-color: "[theme: themePrimary, default: #0078d7]";
border-color: "[theme: themePrimary, default: #0078d7]";
color: "[theme: white, default: #ffffff]";
border-style: solid;
border-width: 1px;
padding: 8px 16px;
cursor: pointer;
font-size: 14px;
border-radius: 2px;
}
.title {
color: "[theme: neutralPrimary, default: #333333]";
font-size: 24px;
font-weight: 600;
margin: 0 0 8px 0;
}

When to use this:
Use it when you only need colors in CSS and don’t want to mess around with TypeScript at all. It’s perfect for quick wins and straightforward styling.
In the .tsx file below, I just took sample text and a button control and applied the styles we defined at the top.
import * as React from 'react';
import styles from './BrandTheme.module.scss';
import type { IBrandThemeProps } from './IBrandThemeProps';
export default class BrandTheme extends React.Component<IBrandThemeProps> {
public render(): React.ReactElement<IBrandThemeProps> {
return (
<section>
<div className={styles.row}>
<h2 className={styles.title}>Get the Current Theme in SPFx</h2>
<p>
SPFx automatically resolves theme tokens in <code>.module.scss</code> files using the
SharePoint theme system. The background, text, and button colors on this web part all
adapt to the current site theme.
</p>
<button className={styles.button}>Themed Button</button>
</div>
</section>
);
}
}
Now, look at the output image: the button on the div element dynamically adopts the SharePoint site theme.

The catch:
This doesn’t automatically react to section background changes. If someone switches a section from neutral to dark-colored, your web part won’t know about it. For that, you need one of the next two methods.
Check out SPFx Drag and Drop File Upload: Single & Multiple Files
Method 2: Detecting Theme Changes with onThemeChanged
BaseClientSideWebPart has a built-in lifecycle method called onThemeChanged. Every time the theme changes — including when section backgrounds are toggled — SharePoint calls this method and hands you the current theme object.
This is cleaner than polling or reading global variables, and it’s the Microsoft-recommended way for most web parts.
- Import the interface: At the top of your web part
.tsfile, add:
import { IReadonlyTheme } from "@microsoft/sp-component-base";
- Override the method in your web part class:
protected onThemeChanged(currentTheme: IReadonlyTheme | undefined): void {
if (!currentTheme) {
return;
}
const { semanticColors } = currentTheme;
if (semanticColors) {
this.domElement.style.setProperty(
"--bodyText",
semanticColors.bodyText || null
);
this.domElement.style.setProperty(
"--bodyBackground",
semanticColors.bodyBackground || null
);
this.domElement.style.setProperty(
"--buttonBackground",
semanticColors.buttonBackground || null
);
}
}

What’s happening here: you’re reading the semantic color values from the theme and pushing them as CSS custom properties onto your web part’s root DOM element.
- Use those CSS variables in your SCSS:
.myWebPart {
color: var(--bodyText);
background-color: var(--bodyBackground);
}
.myButton {
background-color: var(--buttonBackground);
}
This is a really clean pattern because your TypeScript handles the data side and your SCSS handles the display side; they’re cleanly separated.

Commonly used semanticColors properties you can pull:
bodyText— main text colorbodyBackground— page backgroundbuttonText— text on default buttonsbuttonBackground— button backgroundprimaryButtonText— text on primary/CTA buttonslink— hyperlink colorerrorText— error message textinputText— text inside form inputsdisabledText— grayed-out element textfocusBorder— focus ring color
Check out Fluent UI in SharePoint Framework (SPFx)
Method 3: Accessing Theme Data with ThemeProvider
This is the most powerful approach. Instead of waiting for onThemeChanged to fire, you proactively consume the ThemeProvider service in onInit, get the current theme right away, and also register for future changes.
Use this when you need to pass theme data into React components as props, or when you need to do something more complex than just setting CSS variables.
- Import what you need:
import {
ThemeProvider,
ThemeChangedEventArgs,
IReadonlyTheme,
} from "@microsoft/sp-component-base";
- Declare private variables in your web part class:
private _themeProvider: ThemeProvider;
private _themeVariant: IReadonlyTheme | undefined;
- Initialize in
onInit:
protected onInit(): Promise<void> {
// Consume the ThemeProvider service
this._themeProvider = this.context.serviceScope.consume(
ThemeProvider.serviceKey
);
// Get the current theme right now
this._themeVariant = this._themeProvider.tryGetTheme();
// Listen for future changes
this._themeProvider.themeChangedEvent.add(
this,
this._handleThemeChangedEvent
);
return super.onInit();
}
- Handle theme change events:
private _handleThemeChangedEvent(args: ThemeChangedEventArgs): void {
this._themeVariant = args.theme;
this.render();
}
- Pass the theme to your React component:
public render(): void {
const element: React.ReactElement<IMyComponentProps> = React.createElement(
MyComponent,
{
themeVariant: this._themeVariant,
}
);
ReactDom.render(element, this.domElement);
}
- Use the theme inside your React component:
import { IReadonlyTheme } from "@microsoft/sp-component-base";
export interface IMyComponentProps {
themeVariant: IReadonlyTheme | undefined;
}
export const MyComponent: React.FC<IMyComponentProps> = ({ themeVariant }) => {
const semanticColors = themeVariant?.semanticColors;
return (
<div
style={{
backgroundColor: semanticColors?.bodyBackground,
color: semanticColors?.bodyText,
padding: "20px",
}}
>
<h2 style={{ color: semanticColors?.link }}>Hello, theme-aware world!</h2>
<button
style={{
backgroundColor: semanticColors?.buttonBackground,
color: semanticColors?.buttonText,
border: `1px solid ${semanticColors?.buttonBorder}`,
}}
>
Click Me
</button>
</div>
);
};

When to use this method:
Go with ThemeProvider when your web part is React-based and you want to wire the theme into component props cleanly. It gives you full access to both semanticColors and palette in one place, and you can drill it down the component tree however you like.
Check out Call an Azure Function from an SPFx Web Part
Reading Theme Information from the Window Object
You’ll sometimes see this pattern in older tutorials and StackOverflow answers:
const themeColorsFromWindow: any = (window as any).__themeState__.theme;
This reads the raw theme palette directly from the global window state that SharePoint injects on every page. It works, and you can get any token value from it. But I’d treat this as a last resort — it’s not a documented API, so Microsoft can change the structure without warning. Stick to onThemeChanged or ThemeProvider for anything production-facing.
Comparing Theme Retrieval Methods in SPFx
| Method | Best For | Reacts to Section Changes | TypeScript Needed |
|---|---|---|---|
| SCSS Theme Tokens | CSS-only color styling | No | No |
onThemeChanged | Simple color injection via CSS vars | Yes | Minimal |
ThemeProvider | React components with prop-based theming | Yes | Yes |
Commonly Used SPFx Theme Tokens
Here are some commonly used theme tokens you can use in SCSS:
themePrimary— main brand colorthemeDark— darker variant of primarythemeDarkAlt— slightly lighter dark variantthemeDarker— deepest dark variantthemeLight— light variantthemeLighter— lighter variantneutralPrimary— main body textneutralSecondary— secondary text and iconsneutralLight— borders and dividerswhite— pure white backgroundsblack— pure black text
Always include a default fallback value when using SCSS tokens. That fallback kicks in when the theme value isn’t available — for example, on a classic SharePoint page or in a local workbench.
Common Mistakes When Working with SPFx Themes
A lot of developers use getTheme() from @fluentui/react (or the older office-ui-fabric-react) thinking it’ll return the SharePoint site theme. It doesn’t — it returns Fluent UI’s own internal theme, which defaults to Microsoft’s blue palette regardless of what’s applied to the SharePoint site. Don’t rely on it for SharePoint-specific theming.
Complete Example: Bringing Everything Together
If I’m starting a fresh web part today and want theme support:
- For CSS-only styling — I use SCSS theme tokens. Fast, zero overhead.
- For a simpler web part with some dynamic styling — I override
onThemeChangedand set CSS custom properties. - For a React-based web part where I want theme values in components, I go with
ThemeProviderinonInitand passthemeVariantas a prop.
The important thing is to always handle the case where the theme is undefined — It can happen in classic pages, the local workbench, and certain Teams contexts. A simple if (!currentTheme) return; guard goes a long way.
Conclusion
I hope you found this article helpful. In this article, I explained 3 different methods to get the current theme in SharePoint Framework (SPFx). I also explained when to use each method and what makes them different.
When you build a SharePoint Framework web part, it is always a good idea to use the current theme instead of hardcoded colors. This helps your web part match the site theme and gives users a more consistent experience.
If you only need colors in your styles, theme tokens are usually the easiest option. If you need to react when the theme changes, use the onThemeChanged method. And if you need full control over theme information, ThemeProvider is the best choice.
Choose the method that fits your requirement, and your SPFx solutions will look more professional and work better with modern SharePoint themes.
Also, you may like:
- Build a Custom Slides Manager in SPFx Web Part Property Pane (Drag & Drop, Reorder, Hide Slides)
- Build a SharePoint Folder Tree View Using SharePoint Framework (SPFx)
- Display SharePoint List Items in SPFx Web Part
- Fluent UI React Dropdown in SharePoint Framework (SPFx)

Hey! I’m Bijay Kumar, founder of SPGuides.com and a Microsoft Business Applications MVP (Power Automate, Power Apps). I launched this site in 2020 because I truly enjoy working with SharePoint, Power Platform, and SharePoint Framework (SPFx), and wanted to share that passion through step-by-step tutorials, guides, and training videos. My mission is to help you learn these technologies so you can utilize SharePoint, enhance productivity, and potentially build business solutions along the way.