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

Encountered an error in the React component: Unable to access property as

I just started learning React and I created a component like this: export default class CartoviewDrawer extends React.Component { constructor(props) { super(props); this.state = {open: false}; } _handleToggle() { let ...

Conceal a certain element in development using CSS

Is there a way to hide the footer section from my webpage without affecting the rest of the content? For example, using something like: "div class="poweredby" display: none", but I'm unsure of the correct method... Here is the spe ...

VueJS Error: Attempting to access a property that is undefined causing a TypeError (reading 'toLowerCase')

Whenever I attempt to filter and remove items from an array, everything works fine. However, when I try to add new items to the array, I encounter an error message that says "TypeError: Cannot read properties of undefined (reading 'toLowerCase'). ...

Utilizing various Material UI Sliders on a single page with shared color properties

After creating a component called "SliderBox", I noticed that it returns a div containing a Material UI Slider with createMuiTheme and an input component. The "SliderBox" component utilizes an onHover method on the parent div to change the component' ...

Having trouble sending an HTTPS request in NodeJS only to receive an HTTP response instead

As I develop my website using NodeJS and deploy it on Heroku, I encountered an issue upon opening the website. Here is the problem at hand: When looking at the main source file of my web application: app.get('/', (req, res) => { var data ...

What is the best way to switch back and forth between two div elements?

I've been attempting to switch between displaying div .cam1 and div .cam2, however, I can't seem to get it to work. Here's the code snippet in question: HTML: <div class="cam1"></div> <div class="cam2"></div> CS ...

What is the best way to ensure that the operations are not completed until they finish their work using RX

Is there a way to make RXJS wait until it finishes its work? Here is the function I am using: getLastOrderBeta() { return this.db.list(`Ring/${localStorage.getItem('localstorage')}`, { query: { equalTo: fa ...

Module or its corresponding type declarations not found in the specified location.ts(2307)

After creating my own npm package at https://www.npmjs.com/package/leon-theme?activeTab=code, I proceeded to set up a basic create-react-app project at https://github.com/leongaban/test-project. In the src/index.tsx file of my react app, I attempted to im ...

Item beside fill width item with a fixed width in Mui Grid

Presently, I am utilizing MUI Grid, however, I am open to exploring other options. My goal is to have two components positioned side by side: the right component occupying 400px of width while the left component taking up the remaining space. |<------- ...

Is it possible to update session values without the need to log out?

Is there a way to update a value within the session object using NextAuth.js without requiring the user to sign out and in again? For instance, after a user logs in, I utilize the URL stored in the session to display their avatar. Now, if the user wants t ...

What is the best way to display Laravel Validation feedback in a ReactJS render function?

I'm looking to showcase Laravel validation errors in a ReactJS render function. Below is the response I received: {"message":"The given data was invalid.","errors":{"phone_number":["The phone number field is required."],"group_id":["The group id fiel ...

End the child process.execution after a specific amount of time

I have been searching for information on child process waiting time or response waiting time, but I haven't found anything useful. I'm in need of something like that, so I hope someone can assist me. When I look at the code below, I am printing ...

What is the best way to personalize material-ui V1 components throughout my application by establishing a theme?

When working with material-ui v0, I discovered that it was easy to customize themes by adding properties to themeOptions for each component. This file: https://github.com/mui-org/material-ui/blob/master/src/styles/getMuiTheme.js (from the master branch), a ...

Hide the burger menu when a link is clicked

Is there a way to make my Bootstrap burger menu automatically close when the user clicks on a menu link, rather than having to click on the burger itself? I've tried using some JavaScript code but it ends up disabling the burger menu entirely. Can any ...

Ways to prioritize HTML5/CSS3 navigation menu above the content

I am attempting to position my navigation menu on top of the content. Despite using z-index and overflow = visible, the desired effect is not achieved. I want to avoid setting the position relative as it will push the content downwards. Simply put, I want ...

Splitting a td tag into multiple columns dynamically with Angular

I am attempting to dynamically split the table element into separate columns. My desired layout should resemble this: The values for name and surname are fixed at 1, but the values for subjects and grades can vary (there may be 2 or more columns). Below ...

Express Form Validation: Ensuring Data Accuracy

I have recently learned that client-side form validations may not be sufficient to prevent malicious actions from users. It is recommended to also validate the form on the server-side. Since I am new to using express, can someone provide guidance on what s ...

I am looking to adjust the height of my MUI Grid component

Recently exploring React, and I'm looking to set a height limit for MUI Grid. I've structured my project into 3 sections using MUI grid components. My goal is to restrict the page height in order to eliminate the browser scrollbar. If the conten ...

Splitting Code in React Components using Webpack within a Ruby on Rails Application

I'm currently integrating ReactJS components into my Rails application using the Webpack gem. However, I am facing an issue where the React components are only being loaded in specific areas within the layout of the Rails application. This results in ...

Border with curved edges

Having an issue with content boundaries while using CSS rounded corners in Firefox. Here is the code snippet: Code <html> <head> <style> #outter { width: 200px; margin: auto; text-align: cent ...