CSS vs Inline
So, I was wondering if there was any performance downside to use React inline styles (I like them!) vs keep the old plain css stylesheets (that we love to override!). Of course there is, but I wanted some numbers!
I think both ways are useful actually, as Michael Chan said at React Europe ():
– the css can be used for the layout (such as the bootstrap layout classes: row-fluid, span*, etc.)
– the inline styles should be used for the “state-styles” (the style that can change according to a state, which is dynamic).
Why stupid
I decided to try something stupid and not truly relevant but anyway :
Generate a big table, one with inline styles, the other (in another page), with the same data, but with css, and then check the performance/size/time of both.
That’s why it’s not relevant because you would not generate a big table in your DOM. You will more likely have some kind of virtual scrolling / lazy rendering.
But, what about a test, just to see if that’s more slow when I scroll or not, and what about the rendering time ?
Chrome 45b, React 0.13.3 (debug and production)
Test case
So I generated a I’m going to test : Basically, the skeleton of the React component is : The style of the And the same in css for the css table : Basically, here is this beautiful design : I found no difference when scrolling, Chrome DevTools timeline supports my perception : no difference, no fps drop. Without surprise, the DOM size is huge with the inline styles and is linearly proportional to the number of rows. That’s clearly something to take into account if you do some universal javascript. 2,000,000 chars is 2MB of data. (but who sends a big table anyway?!) This is where I let the times with the development version of React, because I started with and used the production version afterwards. They should not be taken into account, it’s not relevant in our case. Yes, it takes more time to stringify our virtual DOM / mount it into the DOM. The DOM is mounted, the browser needs to render the table now. We can assume it will take longer to render the inline styles, because it has more to parse and store every Still a small overhead. I guess we could see some nice differences according to which browser is tested out! I gave a try on Edge with 10,000 rows (React production version) : It’s basically the double of Chrome times. :cry: So yes, we were kinda aware of all these behaviors, but now, we have some numbers ! This global analysis demonstrated that the inline styles take way more size and more time to be handled by the browser, but it has no more impact as soon as it’s rendered. Compared to all the advantages the inline styles offer, we just have to be aware of those potential performance bottlenecks when thinking about the . Some plugins exists to extract the inline styles to css such as : Or if you want the full power of css in javascript (media queries, pseudo-selectors, modifiers, and more!) : of 1,000 rows with 9 columns, all of them with the same content “”, then I did the same with 10,000 rows to check the trend.
– the smoothness when I scroll down the page through Chrome DevTools Timeline
– size of the DOM : useful to know for isomorphic universal javascript (server-side rendering)
– time to mount the DOM : I’m going to use componentDidMount
, this is where the DOM is available after render
is called
– time to be rendered by the browser : I’m going to use requestAnimationFrame
to know when the next frame after render
is ready
const createOneInlineStyleRow = (i) => {
return (
);
};
export default class AppInline extends React.Component {
componentDidMount() {
console.timeEnd('didMount');
}
render() {
console.time('render');
console.time('didMount');
requestAnimationFrame(function() {
console.timeEnd('render');
});
const rows = times(NB_ROWS, createOneInlineStyleRow);
return (
...
{rows}
);
}
}
:
const style = {
fontFamily: 'Consolas',
padding: 10,
color: "#444",
border: "3px solid orange",
position: "relative",
width: "15%",
height: "25px",
letterSpacing: 0,
overflow: "hidden",
fontSize: 10,
fontVariant: "small-caps"
};
.tableCss td {
font-family: Consolas;
padding: 10px;
color: #444;
border: none;
border: 3px solid orange;
position: relative;
width: 15%;
height: 25px;
letter-spacing: 0;
overflow: hidden;
font-size: 10px;
font-variant: small-caps;
}
Results
Timeline
The fact that the DOM is inline or in a proper css seems to not matter, I guess it’s already in the browser memory when it’s rendered so it does not influence the smoothness.Size of the DOM
Type
1,000 rows
10,000 rows
Ratio
CSS
517,725 chars
~5,177,250 chars
x10
Inline
2,283,742 chars
~22,837,420 chars
x10
x4.4
x4.4
Time to mount the DOM
componentDidMount
is useful. We start a timer in the render
method and end it when componentDidMount
is called.
React has done its job converting the virtual DOM into a proper DOM and has injected it into our mounted node.
Type
1,000 rows
10,000 rows
Ratio
CSS (debug)
650ms-750ms
6,000ms
~x10
Inline (debug)
1,000ms-1100ms
10,000ms
~x10
CSS
310ms
2,300ms
~x7.5
Inline
600ms
4,900ms
~x8
x2
x2.1
The delta decreases for less rows but it’s still significant: 70ms (css) against 105ms (inline) for 100 rows (x1.5).Rendering time
style
attribute of every td
.
Type
1,000 rows
10,000 rows
Ratio
CSS (debug)
1,100ms-1,200ms
9,500ms
~x10
Inline (debug)
1,500-1,600ms
14,000ms
~x10
CSS
720ms
6,000ms
~x8
Inline
1,080ms
9,400ms
~x8.7
x1.5
x1.56
What about another browser ? Edge !
Type
mount time
rendering time
CSS
4,115ms
11,591ms
Inline
11,418ms
21,113ms
We knew that
Further
– https://github.com/petehunt/jsxstyle : code inline then extract the constants to a stylesheet
– https://github.com/js-next/react-style + https://github.com/js-next/react-style-webpack-plugin :
– Radium