Skip to content
Manish Garg edited this page Mar 6, 2017 · 23 revisions

Using Office UI Fabric Core and Fabric React in SharePoint Framework

Office UI Fabric is the official front-end framework for building experiences in Office 365 and SharePoint. SharePoint Framework provides a seamless integration with Fabric that enables Microsoft to deliver robust and consistent design language across various SharePoint experiences such as modern team sites, modern pages, etc... Additionally, we have a goal for Fabric to be available for developers in SharePoint Framework to build SharePoint solutions.

Goals

There are two parts of Office UI Fabric that are expected to be used by developers:

  1. Office UI Fabric Core a.k.a. Fabric Core - this is a set of core styles, typography, responsive grid, animation related class, icons and other fundamental building blocks of the overall design language.

  2. Office UI Fabric React a.k.a. Fabric React - this package contains a set of React components built on top of the Fabric design language.

One of the goals of SharePoint Framework is to allow both Microsoft and customers to build rich, beautiful and consistent solutions on top of SharePoint. In that spirit, we wanted to ensure that SharePoint Framework allows:

  • All customers to smoothly consume Fabric Core and Fabric React in their solutions.
  • Microsoft to roll out updated experiences that consume updated versions of Fabric Core and Fabric React in SharePoint without conflicting with customer's solutions.
  • Customers to choose and bundle their desired version of Fabric Core and Fabric React for their solutions.
  • Customers to customize the styles, designs and components tailored to their solution's needs.

Current State

Microsoft uses a version of Fabric Core and Fabric React in SharePoint. In SharePoint online Microsoft keeps pushing updates to the service on a regular basis i.e. SharePoint experiences are likely to keep updating the version of Fabric Core and Fabric React they use. These updates can potentially conflict with your deployed solution as it could break existing styles for components that are using Fabric Core and Fabric React in your solution. For example, the "submit" button in your web part is now using a dark red background color scheme instead of the intended blue background color scheme due to a Fabric Core update pushed in SharePoint by Microsoft that uses an updated color scheme for buttons.

Problem

The main reason conflicts occur between the customer solution and Microsoft experiences is due to the use of global styles in both Fabric Core and Fabric React. Since the client side components (e.g. web parts) live in the same window namespace as the overall page, changes to global styles, apply to all components in the page, including customer solutions deployed on that page. The conflicts could be as small as a change in the color scheme to as big as the component failing to render resulting in a critical loss of functionality. Further, if you override the styles then the 0overrides would apply to the Microsoft code also. This could make the Microsoft expreriences not look or behave correctly.

For the above mentioned reasons, at the current time customer solutions cannot safely use Fabric Core and Fabric React and guarantee they will never be broken. That said, we do understand that developers need Fabric Core and Fabric React to build their solutions. Hence, we are wroking hard to resolve as quickly as possible.

This discussion explains the problem well.

CSS Concepts to understand

  • Global CSS styles and how avoid it at all cost: this is by far the biggest problem. Today, both Fabric Core and Fabric React have global styles. Lack of any native solutions availabe to manage the style scoping makes this a very difficult problem. Scope CSS is only in early stages of discussion, iframes are not a good option to isolate styles. Please read through the end to understand the options we are trying to use to solve thi problem.
  • CSS Specifity and how it applies to web UI. Higher specificity styles override the lower specificity styles. Please note the following precedence order:
    • The style (e.g. style="background:red;") attribute has the highest specifity.

    • Id selectors (e.g. #myDiv { }) is next in the list.

    • Class selectors (e.g. .myCssClass{}), attributre selectors (e.g. [type="radio"]) and pseudo-classes (e.g. :hover) come next.

    • Type selectors (e.g. h1) come last

    • If two classes are applied on a element and they have the same specificity, the class that is loaded later take precedence. This is an important concept as if not used correctly, the user experience can become load order dependent.

Scenarios that are not supported by Microsoft

Because of the problems describe above, the following scenarios are not officially supported by Microsoft because they are bound to break.

  • Loading a copy of the unscoped Fabric core css (i.e. fabric.css) in your web part.
  • Loading a copy of the fabric.component.css file in your web part. The class names used in this class are same as those in React Fabric. Loading this file will cause UI to not look correct. If you really need to depend on fabric.component.css, the only option is to make a copy of this file and rename the class names to custom class names.
  • Importing only styles from React Fabric components is supported only partially. Lets say a developer is using knockout for his/her web part. And they decide to import the React Fabric component styles. Once Microsoft completes the CSS modules work, this can be considered a supported scenario.

Plan going forward

Here are some high level details about what we are doing to alleviate these concerns and support the scenarios.

Short term

In the short term we are planning to release the following updates:

  1. Office UI Fabric Core:
  • We plan to solve this problem through CSS specificity. The Fabric Core team will ship multiple copies of Fabric Core css. e.g. fabric-6.css, fabric-6-scoped.css, fabric-6.0.0.css, fabric-6.0.0-scoped.css.
  • All the styles in the scoped css files are inside a descendant selector namespace e.g. "fabric-6 ms-Icon--list"
  • The tooling will collect what version of the Office UI Fabric Core the web part was built with. This version can be the one that comes with SPFx. Alternatively, web part developers would take an explicit dependency on a chosen
    version if Office UI Fabir core in their package.json file.
  • The web part div will be assigned this scope.
  • The page will contain uncoped Office UI Fabric Core.
  • This way, as per CSS specificity rules, the scoped CSS take precedence inside the web part div.
  • The whole web part and its contents will allign to a specific version of Office UI Fabric Core the developer has chosen.

Javascript

import { SPComponentLoader } from '@microsoft/sp-loader';

export default class MyWebPart {
    constructor() {
        super();

        SPComponentLoader.loadCss('https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/6.0.0/css/fabric-6.0.0.scoped.css');
    }
}

protected render(): void {
  <div className={css('ms-Fabric--v6-0-0')}>
    { // Rest of the web part UI }
  </div>
}

Understanding this approach and its shortcomings

This approach has some shortcomings and it is best that the devlopers understand those before shipping web parts using this approach.

- This approach only works if the Microsoft user experience (i.e. page and first party web parts) use uncoped version of Office UI Fabric Core.
  i.e. ms-Icon--list and the third paty web parts use only the scoped Office UI Fabric Core css as explained above. The reason being that the
  Specificity of the scoped CSS applied on the web part overrides unscoped CSS on the page. Please note, as explained above, if CSS spcificity of
  two classes is the same then the order loading order plays a role in how the css classes will be applied. The class that loads later will take
  precedence.  Hence the higher specificity of the scoped css is important in getting a consistent experience.
  1. Office UI Fabric React:
  • We are working on switching Office UI Fabric React components to use CSS modules.
  • CSS Modules gives unique class names to all Fabric React components. i.e. ms-Button becomes ms-Button_a578389. The last part is a hash that is generated from the version of the React Fabric and the contents of the ms-Button class. This will prevent namespace conflicts. As we use newer versions of Fabric React on the surrounding page, the web part styles will not get overridden.
  • The web part devloper will need to statically link to the React Fabric components. Please see the static linking example below. This will include the React Fabric component in your web part bundle. This implies that, if the page level implementation of the Button were to change, it will not affect your web part adversly.

Javascript

// Remember to explicitly add a dependency on a specific version of office-ui-fabric-react in your package.json file.

// correct - static linking.
import { Button, ButtonType } from 'office-ui-fabric-react/lib/Button';

// incorrect - dynamic linking.
import { Button, ButtonType } from '@microsoft/office-ui-fabric-react';

Understanding this approach and its shortcomings

  • The page may slightly be less performant as it may load more css but the chances of css conflicts will be much less.
  • The static linking bloats up your web part bundle. But dynamic linking is to fragile. And hence, in the interest of reliability, static linking is the only approact that is officially supported.

Mid term

There are a few things are re-evaluating about the short term approach.

  • Although the decendancy based selectors allow you to include load your own copy of Fabric Core in your web part, we are evaluating other approaches to make the dependancy on Fabric Core completely foolproof.
  • For React Fabric also we are looking at more foolproof and dynamic approaches then CSS modules. Some examples are
    • glamor: this looks like a promising solution the global styles problem. css-in-js is a good direction to go in.
Clone this wiki locally