# v8 IE11 polyfill alternative
Originally for v8, our IE11 plan was to use a polyfill for supporting CSS variables. Initial testing (with internal fixes) with static css files showed it working well. However after more testing, and afterswitching to using dynamically created styles, and updating to the latest version, numerous problems have been revealed.
* The polyfill stops reacting at some point to new DOM mutations, so styles stop getting updated
* Severe performance concerns
* Some rules don't get reflected, like `::before` and `::after` pseudo selectors.
* Does not react to insertRule calls
So, we will use an alternative approach:
We will provide a way to "inject" an IE11-specific implementation to makeVariantClasses. This version will on-the-fly replace variable values with resolved variables, allowing us to leverage
## Injecting it
There are two ways we can allow the polyfill to be injected: global state and context. Global state is better for browser scenarios, because we can avoid any risk of impacting bundle size. Context is better for encapsulation, but risks penalizing bundle size if async imports aren't leveraged.
Through global state:
App developers should inject the Fluent UI polyfills script:
```html
<html>
<head>
<script type="text/javascript">
if (typeof navigator !== 'undefined' && /rv:11.0/.test(navigator.userAgent)) {
document.write('https://cdn.com/fui-ie11-polyfill.js');
}
</script>
</head>
</html>
)
```
This will place a an alternative implementation of `makeVariantClasses` on the `window.__fui__overrides` global, which the utility will use as an alternative implementation for resolving classes. This ensures that non-ie11 users will be unaffected in runtime performance and bundle size, while IE11 will still enable variants work to ship.
For more details on polyfill work, see issue:
https://github.com/microsoft/fluentui/issues/15591
f
## How it works
`makeVariantClasses` take in as input styles (css rules) and variants (tokens):
```jsx=
makeVariantClasses({
styles: {
root: {
background: 'var(--button-background)',
'&:hover': {
background: 'var(--button-hovered-background, var(--button-background))'
}
},
},
variants: {
root: {
background: 'red',
hovered: {
background: 'pink'
}
},
primary: {
background: 'blue'
hovered: {
background: 'lightblue'
}
}
}
})
```
We produce the following:
1. css objects which are passed to the style renderer
1. return the class map returned from the renderer
```jsx=
stylesThatGotRegistered = '.root-1{background: var(--button-background);--button-background:red;} etc.';
classes = {
root: 'root-1', // the styles + the root variant css variables
_primary: 'primary-2' // the variable overrides to apply when primary.
}
```
Using css variables, the primary class can be 1 single class which defines many values. Those values can be referenced from within any selector, which in turn can target any sub element in the component.
In IE11, because we don't have variables support, we will need to re-evaluate the styles not just on unique window/theme/direction, but also each unique variant permutation we encounter.
### Alternative IE11 path
Pre-requisites:
* Variants can not use css variables; or we need to support that. They can use the theme object directly.
Instead of this:
```jsx=
variants: {
root: {
iconSize: 'var(--global-icon-size1)'
}
}
```
This:
```jsx=
variants: (theme: Theme) => ({
root: {
iconSize: theme.global.icon.size1
}
})
```
* Variables can not easily cascade to children
#### Execution steps:
1. We need to resolve the root tokens (flatten to an object) using `processVariants`.
2. Based on the state input we need to know which variants apply. (E.g. `primary` is variant; is `state.primary` truthy, or does `state.variant` equal `primary`?)
3. For each applicable variant, we resolve those tokens into a flattened object and merge on top of the flattented root tokens. This creates a list of replacable values.
4. Iterate through `styles` and replace `var(...)` matches with values from the list. Take fallbacks into consideration.
5. Register classes, return result.
6. Optionally, we can cache the result if variant match results (true/false) are added to the graph key.
### Functions
https://codesandbox.io/s/replace-css-variables-x6v4q?file=/src/replaceCSSVariables.ts
`replaceCSSVariables(inputCSS, variableMap)` replaces variable values in the input css with the values defined in the map.
`resolveCSSVariableValue(value, variableMap` returns the css property value based on if the value contains `var(...)` references, and if thos values are available in the given map.