Styled-components version 5 brings some interesting enhancements to the StyleSheetManager
component, a helper component that you can use for modifying the processing of your CSS styles.
In addition to the sheet
property, used to provide a StyleSheet
object with custom configuration, and the target
property, used to provide the DOM node where the styles will be injected, the StyleSheetManager
component now has the following properties:
disableCSSOMInjection
disableVendorPrefixes
stylisPlugins
Let’s review them in detail.
The property disableCSSOMInjections
allows us to switch from the CSS Object Model (CSSOM) API to a text node-based CSS injection system.
When a browser parses the HTML code of a page, in addition to creating a tree of nodes called the DOM (Document Object Model), it creates a CSS object model in the form of a tree where each node contains CSS style information for a particular DOM element.
This way, to insert or modify the style of a particular node, we can use either the DOM API:
document.getElementById('myDiv').style.background = 'blue'
Or the CSSOM API:
// Assuming there's a stylesheet in the HTML page const style = document.styleSheets[0]; style.sheet.insertRule('#myDiv {background-color: blue}');
This way, when the property disableCSSOMInjections
is present or you assign it the value true
:
ReactDOM.render( <StyleSheetManager disableCSSOMInjections={true}> <App /> </StyleSheetManager>, root );
Styled-components will use a text node-based CSS system for getting, inserting and deleting styles:
export class TextTag implements Tag { element: HTMLStyleElement; nodes: NodeList<Node>; length: number; // ... insertRule(index: number, rule: string): boolean { // ... this.element.insertBefore(node, refNode || null); // ... } deleteRule(index: number): void { this.element.removeChild(this.nodes[index]); // ... } getRule(index: number): string { // ... return this.nodes[index].textContent; } }
Instead of the CSSOM API:
export class CSSOMTag implements Tag { element: HTMLStyleElement; sheet: CSSStyleSheet; length: number; // ... insertRule(index: number, rule: string): boolean { // .. this.sheet.insertRule(rule, index); // ... } deleteRule(index: number): void { this.sheet.deleteRule(index); // ... } getRule(index: number): string { const rule = this.sheet.cssRules[index]; // .. return rule.cssText; } }
Here you can see the entire source code of these components to see how it’s done.
However, probably you’ll only need to use this property when having integration issues with third-party tools since the CSSOM API performs better and is the recommended option.
As the name implies, the property disableVendorPrefixes
disables the generation of CSS vendor prefixes (also known as CSS browser prefixes):
-webkit-
-moz-
-ms-
-o-
For example, the rule transform: rotate(15deg)
is generated with vendor prefixes by default:
But if the property disableVendorPrefixes
is present or you assign it the value true
, the vendor prefixes won’t be generated:
Try it here.
Use this property only if you don’t need legacy browser support.
At a high level, this is what styled-components does when you declare a style:
What’s new in version 5 is the ability to use plugins to customize the way Stylis preprocesses the CSS rules with the property stylisPlugins
.
The most popular plugin at this time seems to be stylis-plugin-rtl, which adds RTL (right-to-left) support to the app (notice that this plugin is a fork of the original Stylis RTL plugin).
Basically, RTL changes the values of the CSS properties that deal with horizontal values, such as box and text shadows, border, left, and right positions, among others.
To use this plugin, we just have to import it and pass it to the stylisPlugins
property, which accepts an array of plugins. Here’s an example using the radius of a border:
import rtlPlugin from "stylis-plugin-rtl"; const Title = styled.h1` border: solid 5px; border-radius: 35px 0px 0 35px; /* top-left top-right bottom-right bottom-left */ color: red; `; // ... <StyleSheetManager stylisPlugins={ [rtlPlugin]} > <div className="App"> <Title>Hello world!</Title> </div> </StyleSheetManager>
Without the plugin:
With the plugin:
Here you can try an example of this RTL plugin and another plugin that adds support for the mso-
vendor prefix.
You can look for more stylis plugins on NPM. However, at the time of this writing, not all of them are completely compatible with styled-components.
For example, some plugins will throw the following error:
A stylis plugin has been supplied that is not named. We need a name for each plugin to be able to prevent styling collisions between different stylis configurations within the same app. Before you pass your plugin to
<StyleSheetManager stylisPlugins={[]}>
, please make sure each plugin is uniquely-named.
If this is the case, you’ll only need to add a name
property to the plugin instance, like this:
import msoPlugin from "stylis-plugin-mso"; Object.defineProperty(msoPlugin, "name", { value: "msoPlugin" });
On the other hand, some plugins work by returning a string that represents the processed CSS rule. The original rule will be replaced with this string.
But other plugins don’t return a value, they process the CSS rules using the references passed as arguments.
Here’s the signature of a plugin function, where the most important parameters are context
, the current stage of the processing, and content
, the CSS rule that is being processed:
function stylisPlugin(context, content, selectors, parent, line, column, length) { // ... }
In most cases, these types of plugins (that don’t return a value) are not compatible with styled-components.
If you want to build a custom plugin, you can learn more here.
Released in January 2020, styled-components v5 extends the ability to customize the way your CSS styles are processed without any breaking changes to its API.
You have learned about the three new properties of the StyleSheetManager
component:
disableCSSOMInjection
— to switch to a text node-based CSS injection system for adding styles to the DOM instead of using the CSS Object Model (CSSOM) APIdisableVendorPrefixes
— to disable the generation of browser prefixes for some CSS propertiesstylisPlugins
— to process your CSS rules with Stylis pluginsProbably the last one is going to be the most popular property, just keep in mind the caveats mentioned above when using Stylis plugins.
Happy coding!
As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app, mobile app, or website. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.
Modernize how you debug web and mobile apps — start monitoring for free.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowBuild scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.
Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.
In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.
Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]