What is the variance in performance between the sx prop and the makeStyles function in Material UI?

I recently started delving into Material UI and learned that it employs a CSS in JS approach to style its components.
I came across 2 methods in the documentation for creating styles:

First, using the sx prop:

<Box sx={{ backgroundColor: 'green' }}/>

Second, utilizing the makeStyles method:

makeStyles({
  root: {
    backgroundColor: 'green'
  }
})

While I understand that CSS in JS may not be as performant as native CSS,
which of these two methods is more performant (if there is one)?

On a side note, I am working with Material UI version 5 which boasts improved performance overall through the use of emotion instead of JSS.

Answer №1

In terms of speed, JSS edges out Emotion slightly for static styles (those not based on props). However, when it comes to dynamic styles, Emotion takes the lead as it performs similarly well for both static and dynamic styles.

For more detailed insights into the performance discrepancy between JSS and Emotion with static styles, refer to the following discussions:

JSS clocked in at approximately 10% faster than Emotion for static styles. But when it came to dynamic styles, JSS lagged behind Emotion by 6 times, leading the Material-UI team to rule out JSS from the roster of styling engines for version 5.

The documentation found at https://next.material-ui.com/system/basics/#the-sx-prop outlines the performance metrics below:

Benchmark case Code snippet Time normalized
a. Render 1,000 primitives
<div className="…">
100ms
b. Render 1,000 components <Div> 120ms
c. Render 1,000 styled components <StyledDiv> 160ms
d. Render 1,000 Box <Box sx={…}> 370ms

Directly using Emotion (via the styled method or the css prop) should align closely with Benchmark case c. The use of makeStyles for static styles may offer a slight pace advantage (around 140ms to 150ms), but not significantly. While the sx prop exhibits slower results, its added overhead amounts to only one-fifth of a millisecond per component rendered for 1,000 elements. This variance hinges on the number of CSS properties passed through the sx prop, where fewer properties (< 5) diminishes the difference observed between styled and sx.

While there are no explicit claims by Material-UI that v5 surpasses v4 in overall swiftness, v5 introduces numerous new features that maintain comparable styling efficiency to v4, despite leveraging dynamic styles. This inclusive approach allows for the addition of new functionalities without sacrificing styling performance.

A drawback of utilizing makeStyles within Material-UI v5 is the simultaneous bundling of JSS and Emotion, potentially increasing bundle size. For existing v4 applications transitioning to v5 with established usage of makeStyles, an alternative option like tss-react mirrors the syntax of makeStyles, albeit supported by Emotion and offering akin performance levels to the styled API. Additionally, a codemod now exists for migrating JSS styles to tss-react.

Related answer: Why is the `sx` prop so much slower?

Answer №2

I encountered a similar issue, but then I made the decision to revamp the makeStyles approach entirely using @emotion/css:

https://dev.to/atonchev/material-ui-5-the-easiest-way-to-migrate-from-makestyles-to-emotion-1i9l

Essentially, you will need to create a custom hook useClasses, which will transform your theme => ({... function or styles object into classes that can be used in the same manner as makeStyles.

In my opinion, there is a significant advantage to adopting this method over the one proposed in the mui codemod:

https://github.com/mui-org/material-ui/blob/v5.0.0-beta.2/packages/material-ui-codemod/README.md#jss-to-styled

This is because emotion/css caches identical styles under one className, allowing for the reuse of classes. For example:

const styles1 ={
  someClass1: { color: 'black' }
}

const styles2 ={
  someClass2: { color: 'black' }
}

both styles1.someClass1 and styles2.someClass2 will share the same class name in production, such as css-1qs4g5r. I have tested it myself. Whereas, with the mui codemode approach, unique class names are generated, making them less reusable.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Create a random word from a single string within the data in Nuxt.js

I am in need of assistance. In my Vue Nuxtjs project, I am fetching random words generated from my backend Laravel application through an API response. I need to generate multiple random words from a single string value in the data obtained from my Axios r ...

Issue with Tooltip Position when Scrolling Sidebar is causing display problems

My goal is to create a Sidebar with Tooltip attached to its <li> elements similar to this example: Screenshot - Good Tooltip However, I am facing an issue where the position of the Tooltip breaks when scrolling to the bottom of the sidebar, causing ...

The dynamic route parameter does not currently have compatibility with languages that utilize Unicode characters apart from the English

NextJS 13 (beta) Official Documentation provides information on dynamic route parameters in this link. Clarification: app/shop/[slug]/page.js To retrieve the slug, use params.slug. Example: app/shop/this-is-shop/page.js In this case, params.slug will o ...

Managing authentication in React using Reflux

I recently started learning ReactJS and decided to follow this tutorial: After making some adjustments to the code to make it compatible with my setup, I was able to successfully log in. However, upon reloading the page, the SessionStore appeared to be em ...

What could be causing the dropdown menu to be unresponsive in my HTML and CSS code?

I am struggling to figure out why my drop-down menu is not appearing on my website. Even after removing the 'hidden' property, it still doesn't look right when I hover over the 'servicios' tab. I can't seem to pinpoint the iss ...

The onChange function in Material UI Text Field is preventing users from inputting additional values

My application contains a custom TextField component. I am facing an issue where I cannot increase the value of the first TextField due to the presence of the onChange method. However, the second TextField does not have the onChange method, and I can succe ...

Divs in jQuery smoothly slide down when a category is chosen

As I work on a large website, I have hidden div tags in my HTML that I want to be displayed when a user selects a specific category. However, due to the size of the site, there are many hidden divs that need to be revealed based on different categories sel ...

Experiencing an excessive amount of re-renders

Encountering the error of too many re-renders Attempted to utilize useEffect to render only when weather changes function DashboardHeaderContent({ looks, weather }) { const [seasonRange, setSeasonRange] = React.useState(); function renderLook(look) ...

The default padding and margin in Bootstrap are making the images protrude beyond the edges of the container

I have an issue where my images are stretching into the padding or margin that bootstrap uses to separate columns. I want to maintain the column division but avoid having the images stretch. While I have managed to shrink the image using padding, the white ...

Angularjs 2 Error: Unable to access the 'infos' property of an undefined object using the Http Client

I've been working on an AngularJS app for about a week now, developing a backoffice application for my service. My main challenge lies in using data retrieved from a remote server. I have 4 HTTP GET requests in my app - 2 of them fetching lists of us ...

Collaborating on the state between two reducers

I have a situation where I am working with two different reducers. One is responsible for fetching data, while the other filters that data based on certain criteria. However, I have come across information suggesting that using combineReducers may not be t ...

Is it possible to create an image or logo that moves in sync with the user's scrolling

Having trouble articulating this question, but I'm trying to replicate the logo in the top right corner of this website: I want the logo to move along with the user as they scroll down, remaining visible at all times. Any ideas on how to achieve this ...

Creating a visually appealing table in HTML or experimenting with a tableless design can greatly enhance your website's layout

Presenting data with headers in HTML has been a challenge for me. Below is the portion of the header I'm having difficulty with. Although I've successfully rotated the text, the issue I'm facing now is text overlap. Here's the code st ...

jQuery: Issue with controller function execution when using ajax

Currently, I am working on developing a web application using C# MVC that dynamically fetches information from a server to enhance performance. However, I have encountered some errors and I am having trouble pinpointing the exact cause. Allow me to provid ...

Tips for extracting CSS data with Selenium webdriver's executescript function

Just starting to learn Javascript in a Node environment... I'm trying to use the code snippet below to extract CSS values for a specific web element, but I'm having trouble parsing it in JavaScript. driver.executeScript(script, ele).then(p ...

Eliminate all elements marked with a particular class when the user clicks outside of a

I am currently building upon a project that I previously started here. Essentially, what I'm doing is dynamically generating tooltip popups that appear next to a link when it is clicked. However, I now need these tooltips to close when any click even ...

Having trouble getting two divs to align on the same line using the 'inline' method

I am struggling to align multiple buttons within divs on the same line. Two of these buttons should only be displayed when a specific value is greater than 0. I attempted using display:inline-block in a container div, along with style="float:right", but it ...

VueJS 3 - Issue with applying the <router-link-active> class to routes that share the same path starting name

In my navigation bar, I have created 3 links which are all declared at the root level of the router object. I've applied some simple styling to highlight the active link on the navbar using the <router-link-active> class. Everything works as exp ...

Interacting with a JavaScript button using C# WebBrowser

Can someone please assist me with a problem I'm facing? I have a webpage coded in HTML and Javascript. Whenever I use webBrowser1.Document.GetElementById("hmenu").InvokeMember("click");, the menu pops up on my screen. However, I am unsure how to cli ...

Ensure that Javascript waits for the image to be fully loaded before triggering the Ajax function

function addResource() { var imgIndex = getIndexByImageID(currentDraggedImgID); var newImageID = resourceCollectionSize.length; // Insert the image $('#thePage').append('<img alt="Large" id="image' + newImageID + &a ...