You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have summarized methods and code examples for effectively using the Emotion. Furthermore, I have validated its effectiveness by measuring and comparing its performance against other methods. This process confirms whether it is a superior choice.
The performance measurement of each method is based on the baseDuration obtained using the React.Profile component, with measurements recorded in milliseconds (ms).
1. Defining Styles Outside Components
The method involves storing style code in separate external variables rather than within tags inside components.
It enables reusability across components that require the same styles.
It enhances readability within components.
Even when used across multiple components, style serialization occurs only once, leading to better performance.
When measured against the above code, it is observed that the method of defining styles externally renders 89.96% faster on average compared to defining them internally. See Performance Comparison
Attempt
Inside
Outside
1
0.50
0.10
2
0.60
0.00
3
0.40
0.10
4
0.30
0.10
5
0.50
0.00
Avg.
0.46
0.06
2. Using CssProp Instead of Styled
Both styled from @emotion/styled and css from @emotion/react can be used to create styles in Emotion, but it's generally better to use css.
There's less boilerplate code to write when using css compared to styled.
styled has additional overhead, especially when passing props for dynamic styling.
With css, only the style-related code can be reused, and it can be used with React.memo, useMemo, etc., to prevent unnecessary style recalculations.
Rendering is faster when styles are written with css
Similar to the example in Section 1, performance is measured by rendering 12 toggle buttons. We compare the performance of writing styles using styled and css with both Object format and Tagged Template Literal format.
Comparison with Object Styles
When styles are written as objects, css renders on average 66.67% faster than styled. See Performance Comparison
Attempt
Styled
CssProp
1
0.50
0.10
2
0.30
0.00
3
0.20
0.10
4
0.40
0.30
5
0.40
0.10
Avg.
0.36
0.12
Comparison with Template Literal Styles
When styles are written with Template Literals, css renders on average 50% faster than styled. See Performance Comparison
Attempt
Styled
CssProp
1
0.10
0.10
2
0.20
0.20
3
0.50
0.00
4
0.00
0.10
5
0.20
0.10
Avg.
0.20
0.10
3. Using Object Definition over Template Literals
In Emotion, both Tagged Template Literals like css and Object formats like css({ color: 'blue' }) are supported, but using the Object format is recommended for the following reasons:
When written with Template Literals, styles are not minified for string-written styles, which is not suitable for reducing bundle size.
Template Literals require adding semicolons after each style property, which can lead to runtime errors as they cannot be caught at the code level.
When written with Objects, TypeScript can be used to prevent bugs through type checking and IntelliSense, enhancing productivity.
Object styles allow for flexible and scalable style writing, enabling the combination of predefined styles or conditional combinations.
While there's minimal performance difference between the two methods, Object styles are slightly faster.
The code example below also renders 12 toggle buttons, similar to Section 1.
After conducting around 30 trials, the rendering speed of the code defining styles in Object format shows almost no performance difference compared to Literal format, with a difference of only 0.01ms. See Performance Comparison
Attempt
Literal
Object
1
0.10
0.20
2
0.10
0.20
3
0.00
0.10
...
...
...
30
0.20
0.10
Avg.
0.08
0.07
4. Using className Within a Single Component
Instead of applying cssProp to every tag where styles need to be applied, it's better to apply a single cssProp to the top-level parent tag within a single component and add classNames to the child tags to apply styles.
Increases cohesion of related style codes.
Applying a single cssProp is faster as it reduces the number of style serializations.
The code example below is a component that simply lists information.
Applying className to each tag within a component is on average 60% faster than applying cssProp separately to each tag.
Attempt
Separate
ClassName
1
0.40
0.10
2
0.10
0.00
3
0.30
0.10
4
0.20
0.00
5
0.00
0.20
Avg.
0.20
0.08
5. Use Css Variables or className for Dynamic Styling
Dynamic styling can be approached in two aspects:
01 Cases where UI itself dynamically changes, such as animations or transitions
As described in Emotion's Best Practice, using the style prop and css variables can efficiently handle parts that need to be dynamically processed.
02 Cases where styles need to change based on props received from component users
In this scenario, although the component's styles are determined by the user, they don't change dynamically after the component is rendered. If possible, defining variations of the component in advance and applying them using className would lead to more efficient rendering. Furthermore, as shown in the example below, while it's faster even for simple color applications, it shines brighter in cases where various properties need to be changed.
Similar to Section 4, the code example below lists information, but it allows applying red, green, or blue color based on the color prop.
Applying styles with className is on average 62.5% faster than applying them dynamically for dynamic styling.
Attempt
Dynamic
ClassName
1
0.40
0.10
2
0.80
0.20
3
0.50
0.20
4
0.40
0.20
5
0.30
0.20
Avg.
0.48
0.18
6. Using JavaScript Constants and Css Variables Instead of Theme
It's better to use Css Variables like var(--color-bg) and JavaScript-defined constants rather than using ThemeProvider, withTheme, useTheme provided by Emotion to accommodate Light and Dark themes.
There's no need for separate type extensions for themes.
Eliminates the need for boilerplate code for applying themes (ThemeProvider wrapping, passing theme as a function within cssProp, etc.).
Styles that need to be applied with the theme using ThemeProvider are recalculated for each component render.
Therefore, using JavaScript constants results in faster performance.
The code example below is an Article UI that requires applying various colors. The example assumes only one theme. (If you need to support multiple themes, you'll have to define colors for each theme or define corresponding Css Variables.)
(Bad) Using ThemeProvider
import{Theme,ThemeProvider,css}from'@emotion/react'declare module '@emotion/react'{exportinterfaceTheme{color: {primary: stringsecondary: stringsuccess: stringinfo: stringwarn: stringborder: string}}}consttheme={color: {primary: 'hotpink',secondary: 'pink',success: 'green',info: 'skyblue',warn: 'orange',border: 'lightgray',},}constwithTheme=({ color }: Theme)=>css({padding: '16px',border: `1px solid ${color.border}`,h3: {fontSize: '20px',fontWeight: 'bold',marginBottom: '8px',color: color.primary,},p: {color: color.secondary,marginBottom: '8px',},'& .actions': {display: 'flex',alignItems: 'center',justifyContent: 'space-between',gap: '8px',button: {display: 'inline-flex',alignItems: 'center',justifyContent: 'center',flex: 1,paddingBlock: '8px',color: 'white',},'& .cancel': {background: color.warn,},'& .save': {background: color.success,},},})exportfunctionWithTheme(){return(<ThemeProvidertheme={theme}>{Array.from({length: 10}).map((_,idx)=>(<divcss={(emotionTheme)=>withTheme(emotionTheme)}key={idx}><h3>Performance</h3><p>
orem Ipsum is simply dummy text of the printing and typesetting
industry...
</p><divclassName='actions'><buttonclassName='cancel'>Cancel</button><buttonclassName='save'>Save</button></div></div>))}</ThemeProvider>)}
(Better) Using Constants
consttheme={color: {primary: 'hotpink',secondary: 'pink',success: 'green',info: 'skyblue',warn: 'orange',border: 'lightgray',},}constbaseCss=css({padding: '16px',border: `1px solid ${theme.color.border}`,h3: {fontSize: '20px',fontWeight: 'bold',marginBottom: '8px',color: theme.color.primary,},p: {color: theme.color.secondary,marginBottom: '8px',},'& .actions': {display: 'flex',alignItems: 'center',justifyContent: 'space-between',gap: '8px',button: {display: 'inline-flex',alignItems: 'center',justifyContent: 'center',flex: 1,paddingBlock: '8px',color: 'white',},'& .cancel': {background: theme.color.warn,},'& .save': {background: theme.color.success,},},})exportfunctionNoTheme(){return(<>{Array.from({length: 10}).map((_,idx)=>(<divcss={baseCss}key={idx}><h3>Performance</h3><p>
orem Ipsum is simply dummy text of the printing and typesetting
industry...
</p><divclassName='actions'><buttonclassName='cancel'>Cancel</button><buttonclassName='save'>Save</button></div></div>))}</>)}
Applying colors using JavaScript constants is on average 55.56% faster than using Theme.
Attempt
Theme
Constants
1
0.30
0.10
2
0.30
0.10
3
0.40
0.20
4
0.20
0.10
5
0.40
0.20
Avg.
0.32
0.14
Conclusion
The methods summarized above will streamline decision-making and facilitate making better choices. Additionally, it's essential to bear in mind the trade-off relationship between developer experience and performance when it comes to CSS-in-JS. Therefore, when applying these methods, it's crucial to weigh the performance benefits against potential decreases in developer experience.
Feel free to leave any feedback, opinions, or additional insights regarding the methods outlined in this article in the comments section!
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I have summarized methods and code examples for effectively using the Emotion. Furthermore, I have validated its effectiveness by measuring and comparing its performance against other methods. This process confirms whether it is a superior choice.
The performance measurement of each method is based on the
baseDuration
obtained using theReact.Profile
component, with measurements recorded in milliseconds (ms).1. Defining Styles Outside Components
The method involves storing style code in separate external variables rather than within tags inside components.
(Bad) Example: rendering 12 toggle buttons.
(Better) Example: rendering 12 toggle buttons.
When measured against the above code, it is observed that the method of defining styles externally renders 89.96% faster on average compared to defining them internally.
See Performance Comparison
2. Using CssProp Instead of Styled
Both
styled
from@emotion/styled
andcss
from@emotion/react
can be used to create styles in Emotion, but it's generally better to usecss
.css
compared tostyled
.styled
has additional overhead, especially when passing props for dynamic styling.css
, only the style-related code can be reused, and it can be used withReact.memo
,useMemo
, etc., to prevent unnecessary style recalculations.css
Similar to the example in Section 1, performance is measured by rendering 12 toggle buttons. We compare the performance of writing styles using styled and css with both Object format and Tagged Template Literal format.
Comparison with Object Styles
When styles are written as objects,
css
renders on average 66.67% faster thanstyled
.See Performance Comparison
Comparison with Template Literal Styles
When styles are written with Template Literals,
css
renders on average50%
faster thanstyled
.See Performance Comparison
3. Using Object Definition over Template Literals
In Emotion, both Tagged Template Literals like
css
and Object formats likecss({ color: 'blue' })
are supported, but using the Object format is recommended for the following reasons:The code example below also renders 12 toggle buttons, similar to Section 1.
(Bad) Example: Template Literal
(Good) Example: Template Literal
After conducting around 30 trials, the rendering speed of the code defining styles in Object format shows almost no performance difference compared to Literal format, with a difference of only 0.01ms.
See Performance Comparison
4. Using className Within a Single Component
Instead of applying cssProp to every tag where styles need to be applied, it's better to apply a single cssProp to the top-level parent tag within a single component and add classNames to the child tags to apply styles.
The code example below is a component that simply lists information.
(Bad) Separate Css
(Better) css with className
Applying className to each tag within a component is on average 60% faster than applying cssProp separately to each tag.
5. Use Css Variables or className for Dynamic Styling
Dynamic styling can be approached in two aspects:
01 Cases where UI itself dynamically changes, such as animations or transitions
As described in Emotion's Best Practice, using the
style
prop and css variables can efficiently handle parts that need to be dynamically processed.02 Cases where styles need to change based on props received from component users
In this scenario, although the component's styles are determined by the user, they don't change dynamically after the component is rendered. If possible, defining variations of the component in advance and applying them using className would lead to more efficient rendering. Furthermore, as shown in the example below, while it's faster even for simple color applications, it shines brighter in cases where various properties need to be changed.
Similar to Section 4, the code example below lists information, but it allows applying red, green, or blue color based on the
color
prop.(Bad) Dynamic
(Better) ClassName
Applying styles with className is on average 62.5% faster than applying them dynamically for dynamic styling.
6. Using JavaScript Constants and Css Variables Instead of Theme
It's better to use Css Variables like
var(--color-bg)
and JavaScript-defined constants rather than usingThemeProvider
,withTheme
,useTheme
provided by Emotion to accommodate Light and Dark themes.ThemeProvider
wrapping, passing theme as a function within cssProp, etc.).ThemeProvider
are recalculated for each component render.The code example below is an Article UI that requires applying various colors. The example assumes only one theme. (If you need to support multiple themes, you'll have to define colors for each theme or define corresponding Css Variables.)
(Bad) Using ThemeProvider
(Better) Using Constants
Applying colors using JavaScript constants is on average 55.56% faster than using Theme.
Conclusion
The methods summarized above will streamline decision-making and facilitate making better choices. Additionally, it's essential to bear in mind the trade-off relationship between developer experience and performance when it comes to CSS-in-JS. Therefore, when applying these methods, it's crucial to weigh the performance benefits against potential decreases in developer experience.
Feel free to leave any feedback, opinions, or additional insights regarding the methods outlined in this article in the comments section!
Beta Was this translation helpful? Give feedback.
All reactions