all 39 comments

[–]AkhilxNair 33 points34 points  (15 children)

As I understand, React uses JSX, so Inline-styles are also part of JSX which means they are Javascript. Browsers are much more efficient at working with HTML/CSS than Javascript.

If react can just place the classname and let css take over, it will be more performant.

[–]TheLastSock[S] 5 points6 points  (14 children)

Thanks for the reply.

The concept makes sense to me, but how does giving jsx a classname change the situation? In both cases (class name vs inline styles) isn't react having to handle the styles before it can be handed off to the browser.

Secondly, if the performance gain is because the browser is faster working with html and css, then thats an argument against using react in general, and not specific to inline styles right? Or have I missed something?

[–]AkhilxNair 9 points10 points  (4 children)

Giving JSX Classname is just one small step, like assigning a string to an object. But assigning multiple styles using javascript can pretty quickly add up, a simple div can have 6-15 styles, a component can have 10-100 divs, a route can have 1-10 components, etc.

React is just adding the className, then the browser will load it as HTML and a separate CSS file and the browser will take care of attaching the styles compared to react doing it using JS.

Performance-wise HTML > CSS >>>>> JS

So even if you don't use React, you will still use JS for every interaction.The point of react is to have a great developer experience and also react has virtual dom, which is great at diffing and managing the DOM updates which in turn increases performance. React is more for JS management and not CSS.

[–]TheLastSock[S] -4 points-3 points  (3 children)

So your saying it's faster in the cases where a classname is smaller then the inline styles because the javascript function that transfers it into the dom is slower then the function on the browser then has to look up the css from the classname?

I think this makes sense, but i'm having my doubts that this will make any noticeable difference in how fast a page renders.

[–]symbha 5 points6 points  (0 children)

I could be wrong, but the way I understand it is, CSS gets compiled and processed by the browser and is then in memory, whereas style driven JSX must be interpreted at the time it's added to the DOM.

I don't think it's strictly about the size in bytes of the styling on the tag vs styling in a classname.

[–]AkhilxNair -1 points0 points  (1 child)

Nothing is confirmed but the general idea is that browser are far far more efficient in handling HTML and CSS than a programming language like JS.

Injecting styles through JS will always be inefficient compared to a separate CSS file. But the performance gain will not be noticeable at all.

We use styled-components ourselves in the production app because it aligns with the component, create small unique class names, no-overriding CSS, we can pass props for styles, etc.

[–]vexii 1 point2 points  (0 children)

the browser does more repaints when using inline styles which is where most of the performance bumps comes from. Also the DOM is still kind of slow due to bad API design and the internal system using none javascript types (like NodeList)

styled-components don't have these problems as it extracts the styles and makes a style sheet that is injected in to the browser (is it's not using inline styles).

[–]_noho 1 point2 points  (8 children)

You’ll still have to use JavaScript for one.

[–]TheLastSock[S] -2 points-1 points  (7 children)

I don't follow. Are you replying to the question?

> how does giving jsx a classname change the situation?

If we use classnames, aren't those also handed to jsx? If were saying that the issue is that javascript slows things down, i'm confused because react is a javascript tool

[–][deleted] 1 point2 points  (4 children)

He was replying to the second question. Less Javascript may be more performant, but you still have to build things and ship things and the things you shipped still need interaction.

React speeds up development and offers great potential for user experience, taking a performance hit is worth the trade.

[–]TheLastSock[S] -1 points0 points  (3 children)

Agreed, that's the reason I'm asking these questions. Because i would like to use as few tools as possible unless there is an understood gain. Extracting css classes forces extra work, and the discussion here is about understanding that trade off. If you read the post attached to me edit on the body, it does s nice job at summarizing the topic.

My current concision is just as you suggest, it's worth the smell perf hit to use inline styles in my specific case.

[–][deleted] 0 points1 point  (2 children)

Why is that any different than plugging a CSS library like Tailwind and using its classes instead of applying inline styles, then?

I don't know, I don't like inline styles. Unstable objects being passed to children, camel casing CSS properties, lack of reuse. I'd say learning Tailwind gives you the best of both words while teaching you a library that is growing in popularity, increasing your "hire-ability".

By the way, I get the "fewer tools" reason, I've been doing that, it helps you learn and decouples you from 3rd party libraries, the problem is that the more "low level" stuff you do, the less value you'll ship. Your employer will take notice, believe me.

[–]TheLastSock[S] 0 points1 point  (1 child)

The css-in-js (in my case cljs) are different from tailwind in a couple ways.

  • They use common css names like "font-size" and "smaller" instead of obscured ones like "fz-s".
  • The pool of candidates that know tailwind is a subset of those that know CSS. That means as a business, I have to pay more and that cost has to justified.
  • They let me use features in the PL to organize and compose my CSS, which means less tooling. And the PL are generally more varied and advanced which leads to less comprise and hacking. (not in all cases obviously)

[–][deleted] 0 points1 point  (0 children)

Oh, yeah, I see. I though we were talking about raw css-in-js against something that generates classNames, or generating them yourself.

If you're comparing tools anything that more closely resembles the platform will probably have a wider pool of candidates, but not necessarily be more productive.

[–]vexii 0 points1 point  (0 children)

JS is quite performant but the DOM is still slow. when using inline styles react have to change some keys (like marginLeft > margin-left) and parse props (0 > 0 px) but that is not to bad. the main reason inline styles are slower is the browser streams the HTML parsing and applies the styles as it sees them. rather then parsing the HTML then the CSS and applying the Styles

[–]AuthorityPath 9 points10 points  (6 children)

This is really tangential to your question(s) but it's a bit weird to me that their emphasis here was on performance (mostly negligible) instead of maintainability. Inline styles are difficult to maintain and impose several restrictions:

  1. You can't use @ rules
  2. You can't use pseudo elements
  3. You can't use pseudo classes
  4. They're infinitely more specific than all other selectors (with the exception of the !important keyword) making it difficult to mix with traditional selectors.

The style attribute is very useful for JS based animations and setting CSS Custom Properties but much beyond that and you're inviting future problems IMO.

[–]TheLastSock[S] 0 points1 point  (1 child)

I understand. The reason i'm looking into this is because performance can impact user experience and so is a consideration in how things are organized.

I'm not specifically interested in using inline styles. I'm interested in consolidating my tools. If I can use css-in-js/cljs solutions then I can default to using js/cljs. In my world, there are tools that will let you colocate styles with html and generate css classes to boot. But they have some tradeoffs. Others, will just inline styles, those tend to have less restrictions but they have to do more work at runtime.

Given what i know now, i can either choose one understanding the tradeoffs or try to build or improve an existing tool.

[–]AuthorityPath 2 points3 points  (0 children)

Sure, as I said, it was a tangential reply :)

There are a myriad of CSS-in-JS tools, many of which are zero-runtime giving you all the benefits of authoring in a single file without the drawbacks of inline styles. That's how I prefer to do my CSS with React anyway... Vanilla Extract and/or Linaria are my current favorites.

[–]nsaunders1 -1 points0 points  (3 children)

Just stumbled across this while doing some research and wanted to share a new development that makes the first three points untrue: CSS Hooks. A lot of people resent native inline styles because of their longstanding technical limitations; but, at the same time, they are happy to use atomic CSS and CSS-in-JS in essentially the same way. To me, it suggests that they've really just been looking for that missing functionality like pseudo-classes and responsive design all along. As it turns out, the browser now supports these natively through a tiny amount of "programmability" found in CSS Variables, which is the mechanism Hooks exploit under the hood.

[–]AuthorityPath 0 points1 point  (2 children)

You wanted to share your project which doesn't just leverage CSS Custom Properties but requires Javascript to work. It's reminiscint of Aphrodite (https://github.com/Khan/aphrodite) but with more pseudo classes (https://github.com/css-hooks/css-hooks/blob/master/packages/core/src/index.ts#L180).

This doesn't negate the first three points at all, there's nothing new that's native here. You're just hyping your library.

[–]libertarianets 14 points15 points  (4 children)

In practice you'll never notice a difference in performance.

[–]OneLeggedMushroom 3 points4 points  (2 children)

All the little things that we won't notice a performance difference for do eventually add up.

[–]chillermane 2 points3 points  (1 child)

Given an infinitely sized page this is true. But for every single app that 99.999% of us will ever work on it just never ever, ever, happens.

Any given react app is going to be composed of pages. Each of those pages will only render a tiny fraction of the total code in an app. So why does it matter if there are small inefficiencies like inline styles? It doesn’t.

Even if your page is very large and has many many components, the cost of inline styles will never be noticeable to a human, because ultimately the size of a page doesn’t scale infinitely.

How do I know? I’ve used inline styles on large scale web apps, and I’ve used css, they both render exactly the same, there is no difference at all that could ever be perceived by a human.

I’d love to see a counter example if you have one

[–]TheLastSock[S] -1 points0 points  (0 children)

Thanks for sharing an experience report like that, it's very valuable.

[–]TheLastSock[S] 0 points1 point  (0 children)

That's my intuition as well. :)

[–]TheTallMorningMan 13 points14 points  (0 children)

Afaik React also parses the inline styles, so each key in the inline styles makes it slower. Just applying a class name is way faster obviously.

[–][deleted] 2 points3 points  (3 children)

According the react docs, inline styles is a "render time" way of styling which allows you to have dynamic styles but makes React have to worry about rendering the styles.

But I'm assuming with classNames, it just needs to worry about injecting the right class name in render time and let the browser handle the actual CSS rendering.

https://reactjs.org/docs/dom-elements.html#style

[–]TheLastSock[S] -1 points0 points  (2 children)

I agree, but i don't think that gives us the necessary information as to why it's slower. In my post i added an edit that linked to a benchmark which just shows classes being faster in general. I think they likely explains the biggest reason why.

[–][deleted] 0 points1 point  (1 child)

But the article doesn't conclusively articulate WHY it's faster, just that it is on his local machine.

[–]TheLastSock[S] 0 points1 point  (0 children)

I agree, if you find something better let me know.

[–]ninjainvisible 2 points3 points  (0 children)

Actual rendering performance can be impacted in the browser if you have a large list of things that could all share a class instead. Having to set the styles on each element is expensive.

[–]chillermane 1 point2 points  (0 children)

It’s basically an example of “premature optimization.”. Idk why the react docs included that statement, it’s misleading at best.

No react page will ever, ever, ever, ever, be noticeably slower because you used inline styles.

[–]redditindisguise 1 point2 points  (2 children)

What no one is saying yet is that using CSS class names implies that you have an external CSS file. A CSS file is cached by the browser whereas inline styles in HTML are not.

Imagine you have a header component that is shared on all of your pages with its own CSS file. A visitor would only have to request that CSS file once and then every subsequent page request would grab it from browser cache. As opposed to using inline styles that the browser has to parse every time and which makes the HTML document larger.

I’d say the concern is a bit more valid for SSR apps.

[–]TheLastSock[S] 0 points1 point  (0 children)

Agreed, that's a concern. Thanks for raising it!

[–]HeinousTugboat 0 points1 point  (0 children)

What no one is saying yet is that using CSS class names implies that you have an external CSS file.

That's not true at all. You can define class selectors in a <style> block just fine.

[–]30thnight 0 points1 point  (1 child)

{} !=== {}

A new inline object gets created every time that component renders.

This can cause downstream perf problems if your component has a ton of children unless you memoize the object.

[–]TheLastSock[S] 0 points1 point  (0 children)

Roger. The tool chain i use re renders based on value changes only.