## Email for Edge team Fluent UI React uses CSS-in-JS with Atomic styles to style React components. - CSS-in-JS means styles are added to the DOM using [`sheet.insertRule`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule) API on their first use. - Atomic means that for every unique [CSS property;value] pair, a new class is created. - In order for the atomic CSS-in-JS to be deterministic, all CSS shorthands are expanded to long hands (that means `border` is expanded to 12 separate CSS properties - style, color and radius for 4 sides) Fluent UI React v0 (`@fluentui/react-northstar`) uses third party [Fela.js](https://fela.js.org/) as its CSS-in-JS engine. The upcoming version, Fluent UI React v9 (`@fluentui/react-components`) uses in-house CSS-in-JS engine called [Griffel](https://griffel.js.org/). ### Current situation in Teams Client v2 The initial render of the Teams application results in ~2000 DOM elements styled by ~2500 CSS rules. It can happen that some elements are styled using ~100 different classes: ![](https://i.imgur.com/4mdqpCw.png) All the CSS rules have been added using `insertRule` to a single `style` element. Now, after the initial render, a user performs an action which renders a new piece of the UI (just one button) and, as a result, it causes a `Recalculate Style` operation which affects ~2000 DOM elements and takes more than ~100ms (tested locally on high end Intel Macbook). ### Root causing the issue The root cause of the perf issue seems to be the `insertRule()` call on the style element itself. As a minimal repro, we have a page (plain HTML, no framework) which consists of 1000 `button` elements each having a `span` inside = 2000 elements in total. We style these elements using CSS rules which come from a single `style` element - each `button` has ~100 classnames, most of them shared among all the buttons, two of them unique for each button - this results in ~2000 CSS rules in the `style` element. (This should be DOM and CSS size comparable with Teams Client v2 after the initial render). Now we click a button which adds one additional CSS rule to the `style` element - this triggers `Recalculate Style` which affects 2000 elements and takes ~80ms on my Macbook. codesandbox: [https://codesandbox.io/s/insertrule-2000rules-chc15k?file=/index.html](https://codesandbox.io/s/insertrule-2000rules-chc15k?file=/index.html "https://codesandbox.io/s/insertrule-2000rules-chc15k?file=/index.html") Second experiment just removes the unique classes reducing the DOM to 1000 buttons, 1000 spans and ~100 CSS rules in the style elements - the `Recalculate Style` still affects 2000 elements, now it is cheaper taking ~40ms on my Macbook. codesandbox: [https://codesandbox.io/s/insertstyle-66rules-w4x38o](https://codesandbox.io/s/insertstyle-66rules-w4x38o "https://codesandbox.io/s/insertstyle-66rules-w4x38o") In both examples - start profiler, click the blue button, check console and the profile My current understanding is that whenever `insertRule` is called on the style element, all DOM elements which are styled by any rule in that style element are recomputed. The rule which we are adding in the test does NOT affect any of the elements on the page. There is no difference when we add the rule to the beginning or the end of the style element. ### Long term solution As a long term solution for Fluent UI React v9 we plan to implement static CSS extraction - extract all the CSS during build time and statically have it as part of the initial HTML. But we still need a solution for Fluent UI React v0. ### Discussion Is there anything wrong with how we use the `insertRule`? Would there be any option/plan on the browser side to optimize? We tried to prototype splitting CSS rules to multiple `style` elements - we just count the rules inserted and for every 100 CSS rules, we dynamically add a new `style` element. It improves perf (in local perf debug - ~2000 elements affected/110ms ->  ~600 elements affected/50ms) but the result is still hardly acceptable. This also raises another question - how would using multiple `style` elements affect overall browser performance? We have not identified any perf hit caused by adding a new empty `style` element dynamically, is that correct? Also will browser handle having hundreds of `style` elements in the DOM?