Styling Fabric UI React Controls in SPFx projects

Robin Agten
delaware
Published in
5 min readMar 30, 2020

--

The goal of this post is to explore some options to style the out of the box Fabric UI React controls. Very often we use these controls in our SPFx solutions, but we want them to be styled according to a specific company guideline and use them in different components of the solution. There are a couple of ways to achieve the styling of the OOTB controls:

  • Globally target the OOTB Fabric UI classes
  • Custom css classes attached to the component
  • Function based styling

The 3 approaches are explained in this post, but the function based styling seems the way to go (spoiler 🙂 )

Globally targeted css classes

The first thing I did when I wanted to start styling an OOTB Fabric UI control (e.g. checkbox), is inspect the component HTML structure. It turns out that all components have these general ‘ms-’ prefixed classes. You can use the ‘:global’ selector in your SPFx style sheets to target these classes.

The image above shows the usage of the ‘:global’ selector. It ensures that the sass module loader will not modify the class names in the output bundle so the css will directly target the ‘ms-’ prefixed classes. There are some significant drawbacks to this approach:

  • You have to inspect the HTML elements to find out the correct classes to target.
  • What happens if these ‘ms-’ class names change in future releases?
  • For component states (e.g. checked or unchecked) you have to target the elements based on attribute values.
  • It quickly can become very complex and unstructured.

Custom classes attached to the control

Another way to style the controls is to create a custom css class for it that you attach to the control:

<Checkbox className={styles.myCustomCheckbox} label="Checkbox" />

In your css you can then target the different elements of the control:

.myCustomCheckbox { 
> label {
> span {
color: purple;
}
}
}

Using this approach, you are not longer bound to the OOTB ‘ms-’ classes and you can achieve the same goal as the first approach as shown in the image below:

This is already an improvement in comparison to the first approach. You can for example put these styles in a separate file and re-use them across your solution. But still there are some disadvantages:

  • You still have to inspect the HTML elements to find the correct elements to target.
  • The HTML element structure might change in future releases so the css might stop working
  • You still need attribute selectors to style components based on their state (e.g. checked or unchecked)

Function based styling

I still wasn’t 100% satisfied with the second approach, so I searched for a better alternative and I came across function based styling: https://github.com/microsoft/fluentui/wiki/Component-Styling#function-based-styling.

This approach lets you style components based on their theming or state. With this technique you have an IComponentStyleProps and IComponentStyles object that you can use to define the styles. The snippet below shows an example for the Fabric UI React Checkbox:

const checkboxStyles = (props: ICheckboxStyleProps): ICheckboxStyles => { 
const chkStyles: ICheckboxStyles = {
text: [
{color: "purple"},
props.checked && { color: "blue" }
]
};
return chkStyles;
};

As you can see the style function takes a parameter of type ICheckboxStyleProps. This object contains information about the component’s state (checked, disabled, theme, …). The function should return an ICheckboxStyles object which holds the actual styles. Once you have this style function defined you can add it to your control:

<Checkbox styles={checkboxStyles} label="Checkbox" />

The big advantage of this is that you have type-safe objects that you can use for styling. The image below shows this approach to achieve the exact same styling as the previous methods:

Note: These style functions aren’t available for all components. For example, the Button doesn’t have a IButtonStyleProps interface. Instead the state classes are defined on the IButtonStyles interface (e.g. root and rootHovered). So you don’t input a function in the control but just the IButtonStyles object. This is what’s called object based styling: https://github.com/microsoft/fluentui/wiki/Component-Styling#object-based-styling

Okay, this seems a pretty neat approach to style your components. Granted you have to write a bit more code, but you make sure you are always targeting the correct elements. You could move these style functions to a separate file and re-use them across your solution. You will still need to add this function to all your Fabric UI React controls styles attribute.

In the next chapter I take this a bit further and create separate components that include the styling and can be re-used in your solution.

Extending OOTB Fabric UI React controls

The goal is to create a custom component (e.g. CompanyCheckbox) that has the exact same properties as the OOTB Fabric UI React Checkbox but includes your custom styling. You can create a central location in your solution and reference these extended components from anywhere in your code.

The code below shows an example of an extended Checkbox:

import * as React from 'react'; 
import { Checkbox, ICheckboxProps, ICheckboxStyleProps, ICheckboxStyles } from "office-ui-fabric-react";
export const CompanyCheckbox: React.SFC<ICheckboxProps> = (props: ICheckboxProps) => {
const checkboxStyles = (styleProps: ICheckboxStyleProps): ICheckboxStyles => {
const chkStyles: ICheckboxStyles = {
text: [
{color: "purple"},
styleProps.checked && {
color: "blue"
}
]
};
return chkStyles;
};
return (
<Checkbox {...props} styles={checkboxStyles}/>
);
};

As you can see we create a stateless function component which takes the OOTB ICheckboxProps interface as an input. In the function component we also define the custom styling we need for the control. Lastly we return the OOTB Checkbox control with the ICheckboxProps and the custom styling. You can now use the CompanyCheckbox component and use it in the exact same way as the OOTB control but with custom styling:

<CompanyCheckbox label="Checkbox"/>

Conclusion

There are multiple ways to style the Fabric UI React controls, but the Function based approach seems the most integrated. It provides type safe interfaces for your stylable elements and can easily be abstracted to create re-usable styled controls. If you have other approaches to achieve this please let us know in the comments.

You can find the full code of the examples on GitHub

Originally published at http://digitalworkplace365.wordpress.com on March 30, 2020.

--

--