Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Migrate to styled-components #6115

Closed
kybarg opened this issue Feb 11, 2017 · 167 comments
Closed

[RFC] Migrate to styled-components #6115

kybarg opened this issue Feb 11, 2017 · 167 comments
Labels
discussion new feature New feature or request
Milestone

Comments

@kybarg
Copy link
Contributor

kybarg commented Feb 11, 2017

Can we switch to styled-components?

Outdated comparison

It has many advantages against JSS
Here comparison table, and next version is even going to avoid SSR styles re-render!

Features styled-components react-jss
No build requirements
Small and lightweight
Supports global CSS
Supports entirety of CSS
Colocated
Isolated
Doesn’t break inline styles
Easy to override
Theming
Server side rendering
No wrapper components
ReactNative support

Legend: ✅ = Yes, ❌ = No, 😕 = Kinda, refer to notes or parentheses

@oliviertassinari

This comment has been minimized.

@oliviertassinari
Copy link
Member

oliviertassinari commented Feb 11, 2017

@kybarg Actually, I'm not sure to fully understand what you are suggesting.
We are not using react-jss as your question suggest.

When you say we, are you talking about users or Material-UI?

@kof
Copy link
Contributor

kof commented Feb 11, 2017

My points are:

  • styled-components is a much higher level library than the JSS core, you can for sure use it in your application layer.
  • The comparison table above is about react-jss, not JSS core and is a subjective opinion of Max. It is partially not true and partially just a look from some specific perspective which we don't see from the table.
  • We are working on dynamic rules rendering for more efficient dynamic styling, jss-theme-reactor does the job right now already, its just a matter of an optimization, which is probably not very relevant for MUI.
  • What MUI uses internally should be totally out of concern for the end user. Everything a user needs to do should be possible without even knowing what MUI is internally using or at least its more or less regular cssinjs syntax for theming.
  • We need to get use cases MUI doesn't support right now and solve them. I am always happy to help the integration process and available on gitter.
  • What is react-native support anyways? Isn't it just a subset of the web platform? If so it should just work, otherwise let me know what JSS needs to be able to do to support react-native, here is the issue.

@mxstbr
Copy link

mxstbr commented Feb 11, 2017

That table is indeed very subjective and based on my own experience. FWIW, styled-components works with any third party component library:

import { Button } from 'material-ui'

const MyButton = styled(Button)`
  // Only these styles will be overridden
  background: red;
`

This works as long as the components attach the className prop internally to some DOM node:

const MaterialUIButton = (props) => {
  /* ... */
  // As long as props.className is attached, the above usage will work
  return <button className={`bla ${props.className}`} />
}

What is react-native support anyways? Isn't it just a subset of the web platform?

Nope, it's not quite that easy 😉 Adding support to JSS shouldn't be hard though, as all you have to do is pass the style object through to StyleSheet.create(). This requires a bit more effort from the styled-components side to make CSS strings work.


I've been talking to @javivelasco for a while now and love where he's going with react-toolbox. His implementation is amazing, and I'd love to see all third party component libraries adopt it. Pinging him so he can chime in with his ideas here!


No server-side rendering concurrency possible. It's relying on a singleton to collect the styles while JSS instantiate a new instance to collect styles at each request. Steaming is really limited.

Totally unrelated, mind commenting in this issue with your ideas for an API that would allow this to be the case? We haven't decided what we're going to do, so your input would very much be appreciated.

@rainice
Copy link

rainice commented Mar 17, 2017

Hi, I inquired about this in gitter. Just to get the views of others, I will post it here as well:

I know material-ui next is heavily invested in a custom jss solution.
Does anyone discovered any serious advantage of using jss over styled-components?

While jss is good as it enables several patterns like decorators (injectstyles) and plugins, I think styled-components straightforward approach is much cleaner as there is no need for decorators, custom setup and plugins cause it doesn't need to.

In styled-comp every component is already styled so no need to pass styles. and you pass props that can evaluated to produce a different style
no setup (createJss)
no plugins (prefix)
no JSON DSL

@kof
Copy link
Contributor

kof commented Mar 17, 2017

Somebody has to lock this thread.

@rainice jss doesn't have decorators, a HOC is an implementation detail of react-jss and is not used here.

@javivelasco

This comment has been minimized.

@kof

This comment has been minimized.

@mbrookes

This comment has been minimized.

@oliviertassinari
Copy link
Member

oliviertassinari commented Mar 17, 2017

I wish we could have moved forward that thread with a less coupled styling solution!
However, I think that our priority, for now, should be around finishing the migration/overall improvement of the components.

@oliviertassinari oliviertassinari changed the title [Sugestion] Change style engine [Sugestion] Change style engine to styled-components May 9, 2017
@followbl
Copy link

@mxstbr thanks for styled-components

This works as long as the components attach the className prop internally to some DOM node

this might be worth highlighting somewhere in your usage guide when mui:next is released. This comment just saved me.

@yhaiovyi
Copy link

yhaiovyi commented Nov 9, 2017

Flex styles for IE10 don't work with jss but work with styled-components like a charm

@oliviertassinari
Copy link
Member

@yhaiovyi Material-UI doesn't support IE10.

@kof
Copy link
Contributor

kof commented Nov 9, 2017

Vendor prefixer evtl. Will be fixed soon for jss, doesn't mean though it will fix all issues if mui was never tested on IE10

@yhaiovyi
Copy link

Anyway I haven't found any other problems then css flex with IE10 so far

@Danilo-Araujo-Silva
Copy link

Looks like we have 3 ways (could be easier, but not everything is flowers) to override Material UI styles with Styled Components. Here is my Gist.

@oliviertassinari
Copy link
Member

oliviertassinari commented Jan 11, 2018

You can also get a styled-components API like with few lines of code: https://material-ui.com/customization/css-in-js/#styled-components-api-15-lines-

@caub
Copy link
Contributor

caub commented Mar 11, 2018

You can also use styled-jss as well, example: https://codesandbox.io/s/32mvjyjyxq

the only downside with JSS in general is the lack of autocompletion in code editors, like said here too, but the benefits are there, parsing css to js like in styled-components is a bit an overload

edit: just noticed the referenced issue just above, interesting

@caub
Copy link
Contributor

caub commented Mar 13, 2018

What's annoying is Mui's context and withStyles HOC don't seem to play well with the core react-jss and styled-jss ThemeProvider https://codesandbox.io/s/32mvjyjyxq (I tried putting a Typography but that doesn't work, edit: nvm, still fiddling with it)

I wonder if later (post v1 I guess) it wouldn't be worth to simplify src/styles/withStyles and MuiThemeProvider + JSSProvider double layer, and have something a bit more simple like how react-jss and styled-jss have

@kof
Copy link
Contributor

kof commented Mar 13, 2018 via email

@vdjurdjevic
Copy link

@martinjlowm Yep, we are on the same page :) I think that the smartest way to go for the material UI team is to implement some kind of pluggable solution and not couple with any css in js solution, letting people choose what to use and save some bundle size that way. And also keeping classes and createMuiTheme API, because that's the most powerful part of it. For me, css in js is about easy dynamic styling based on component state, confidence when refactoring or deleting css or whole components (that's where object approach is superior), performance (not downloading a bunch of unused styles from a bunch of external stylesheets), etc.. And again, I don't understand why people like writing string with some editor highlighting. I mean, you have to use ${} to access props from context. For anything more complex than setting background od div element, that approach is messy and not readable in my opinion. I am not bashing it, just saying what I think and trying to prove a point that not every developer like styled-components, and even if they did, I don't see how it is a good deal to trade performance and flexibility for that :)

@TheHolyWaffle
Copy link
Contributor

@vdjurdjevic Indeed, coupling material-ui to one css in js solution is almost a guaranteed recipe for conflict when css-in-js practices inevitably grow in different directions.

How about some adapter pattern that applies styling with a specific css-in-js provider? The styles themselves should be defined in a consistent format within the material-ui packages. It's the applying of those styles that is performed differently by the corresponding adapters.

Something along the lines of:

import {EmotionAdapter, StyledComponentAdapter, ThemeProvider} from "@material-ui/core/styles";
...
return 
    (<ThemeProvider theme={theme} adapter={EmotionAdapter}>
        ...
    </ThemeProvider>)

@oliviertassinari
Copy link
Member

oliviertassinari commented Jul 4, 2020

@vdjurdjevic I pretty much agree with your thoughts on #6115 (comment). You might like this summary of the direction we are taking that I have recently shared in #16947 (comment).

I don't understand why people like writing string with some editor highlighting

A couple of reasons from my perspective:

  • Close to why we don't write React.createElement('div', {}).
  • People with limited experience in the web dev (they are many) struggle to learn the JavaScript API, it feels simpler with the CSS syntax. Take the designers as an example, go ask the ones in your team what they think about it :).
  • Can't copy and paste between dev tools and source (I hate this one).

@vdjurdjevic
Copy link

@oliviertassinari Ok, these are some solid points, I agree :) But still, for me (not a designer, not a beginner, senior developer), styled-components and tagged template literals would never be an option. I read your summary for the direction of further development, and I am happy to hear that css engine will be optional. I don't mind styled-components as a default (if that's what the majority of users like), as long as I can switch that. And to be honest, I think I will stick to JSS with v4 for my next project, it has some nice features (like expand and compose plugins). I had to write stylis plugin for emotion to have something similar.

PS. I am not big of a fan of JSX either :) It quickly gets messy, you end up with arrow code and for components that should render dynamic elements, you have no choice but to use createElement. Not saying that working directly with createElement is better, just saying that JSX is not ideal. In my opinion, Flutter has the best DX, I hope it will be able to handle web platform well someday.

@Icehunter
Copy link

Icehunter commented Jul 4, 2020

@oliviertassinari Per our ongoing perf testing as noted in #6115 (comment) I just hope the material team doesn't just choose styled components because it's popular. It's slow. Always has been. Personally it's a point of being a dev that you need to learn things like JS notation of CSS.

It's part of the job.

Making devs lives easier is part of our job as package maintainers (for my own projects I'm speaking from) but there comes a line between making it easy and making it performant.

It's why I only use makeStyles and always have since it was introduced.

My last teams architect wouldn't listen and plowed ahead with styled components and now the site is slow. I switched out to makeStyles in a test branch and saved 50% (10 seconds) on TTI on mobile devices, but just like you said in that comment, JS notation isn't known by everyone so it wasn't accepted.

Internally material can choose whatever it wants but please make it performant by default.

@eps1lon eps1lon changed the title Migrate to styled-components [RFC] Migrate to styled-components Jul 7, 2020
@eps1lon eps1lon added discussion and removed priority: important This change can make a difference labels Jul 7, 2020
@haysclark

This comment has been minimized.

@mbrookes

This comment has been minimized.

@haysclark

This comment has been minimized.

@Nvveen
Copy link

Nvveen commented Aug 16, 2020

Does anyone know if @emotion/styled (which has basically the same API as styled-components) would be equally slow? I'm just wondering if there's anything about their implementation that might be better optimized.

https://codesandbox.io/s/css-in-js-comparison-sej1m

image

About as fast as styled components. Still not as fast as makeStyles. The issue I see for the most part is object creation and object caching/memoization differences.

I was wondering what the performance of the Box component would be compared to your profiling, and added Chakra-UI's Box for good measure, and the results were... surprising :P
https://codesandbox.io/s/css-in-js-comparison-forked-mg3gx?file=/src/App.js

image

@re-thc
Copy link

re-thc commented Aug 16, 2020

@Nvveen have you tried Chakra-UI v1? It's been rewritten and hopefully should be better. There's also emotion v11, although still in beta.

@Nvveen
Copy link

Nvveen commented Aug 16, 2020

@Nvveen have you tried Chakra-UI v1? It's been rewritten and hopefully should be better. There's also emotion v11, although still in beta.

Just tried it with the latest RC, but no noticeable difference; it's still about 1.5x to 2x as slow as regular SC. Biggest question to me is why the MUI Box is so slow.

@re-thc
Copy link

re-thc commented Aug 16, 2020

@Nvveen have you tried Chakra-UI v1? It's been rewritten and hopefully should be better. There's also emotion v11, although still in beta.

Just tried it with the latest RC, but no noticeable difference; it's still about 1.5x to 2x as slow as regular SC. Biggest question to me is why the MUI Box is so slow.

It uses Jss. SC is at least somewhat better.

@oliviertassinari
Copy link
Member

oliviertassinari commented Aug 16, 2020

On my machine, the order in which the test cases are run impact the results. Compare

  1. Box first https://codesandbox.io/s/css-in-js-comparison-forked-tqlg1?file=/src/App.js

Capture d’écran 2020-08-16 à 19 49 55

  1. Box last https://codesandbox.io/s/css-in-js-comparison-forked-js6th?file=/src/App.js

Capture d’écran 2020-08-16 à 19 49 45

@re-thc
Copy link

re-thc commented Aug 16, 2020

@oliviertassinari garbage collection and jit from v8 is what's causing it. Better to have test runs isolated / separated really. The later tests have better jit, but once in a while it'll trigger garbage collection.

@jedwards1211
Copy link
Contributor

jedwards1211 commented Aug 18, 2020

It looks like Emotion, SC, and Chakra are all close to a theoretical maximum perf for when each little component has its own styles to mount, with MUI styled not quite fully optimized yet. Seems like the only way to get better perf than that is to have one style sheet for the whole component tree as in makeStyles/pure CSS. I'd guess the additional 30 ms for emotion, SC etc. is the unavoidable overhead of each little component having to make sure its styles are mounted.

@re-thc
Copy link

re-thc commented Aug 19, 2020

@jedwards1211 if it's about keeping the dx, Atlassian made a lib that compiles it to css, called compiled

@mbrookes mbrookes unpinned this issue Aug 24, 2020
@oliviertassinari oliviertassinari removed their assignment Sep 8, 2020
@oliviertassinari
Copy link
Member

I'm closing for #22342. We are migrated to emotion by default, with a simple way to swap the engine to styled-components. Thanks all for the discussion, it took us 4 years, we are really close now: #24405.

@CloutProject
Copy link

@oliviertassinari Could you please add an example to the repo covering Next.js with the styling engine swapped to styled-components? I just updated to MUI v5 and I'm having a hard time figuring things out.

@oliviertassinari
Copy link
Member

@CloutProject Adding an example with Next.js + Styled components sounds like a great idea. It now growing faster than create react app, the only tool for wish we have an example. Our approach is the same as Preact, so you could start from the official example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion new feature New feature or request
Projects
None yet
Development

No branches or pull requests