-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Fabric React CSS Styling: to inline, to modulecss, or to scope #983
Comments
We could set few extra rules to make the system flexible and easy to use:
|
@dzearing did you guys evaluate https://github.com/styled-components/styled-components Provides easy theming and extensibility and v2 is in rc. |
I would suggest styled-jsx as it is the closest alternative to native CSS, but there are 2 important missing features still WIP which are dynamic styles mode and external stylesheet support. |
@davidye @leesiongchan Sorry, missed your comments. We definitely evaluated styled-components, the issue is that the styles are all string based. We need the styles to work well with theming and ideally they'd be javascript objects so that we can avoid string parsing. We're leaning towards glamor right now, https://github.com/threepointone/glamor Which until recently I believe styled-components was using under the hood for the hashing. |
@dzearing Just in case you misread, I am suggesting styled-jsx not styled-components. To me writing native CSS code in JS is much more natural than writing JS objects and I think they can be theming quite easily as well. |
I'm going to open this issue up for discussion, I would really love to hear peoples' opinions.
We are looking at a number of options to improve how we define the component css. We want a few things:
Safe to use, no conflicts. If you accidentally load 2 different versions of the same Component, they never will collide each other. We can achieve this using a number of approaches that have their pros and cons.
Easy to theme. We want you to be able to define your pallette, maybe custom font, and overrides in a theme manager. We want "dark" mode to be provided automatically. It would be ideal to support rendering isolated themes within a DIV (using react context to absorb them.)
Predictable to customize. Using css class names is a completely flimsy contract that is bound to break people. Class names can change, dom can change, even styling can change. Changing heights of buttons, text fields, app bars, should be easy. Using
className
has been a real problem because of css specificity. Either you use!important
on all your rules or fight specificity by adding multiple classes.Server side rendering friendly. Right now
load-themed-styles
is missing a function to wrap rendering to string and on completion returning the html + detokenized styles as a string.Bundle sizes should be minimal. We want bytes downloaded to be tiny. Today with load-themed-styles tokenization, the format, while heavily compressible, is verbose and could be way better. Even raw css rules are very verbose compared to json styling.
Ideally, a rich contractual theme subsystem such that intellisense just works.
There are a few ways we can approach this, but none of them are perfect.
Inline styling (Radium)
Inline styling looks really attractive, because it would completely obliterate the mess that is CSS. It would move the styling into the TypeScript world, which would be vastly superior to SCSS, since we get all sorts of programmatic goodies (e.g. calculating the dark theme that meets minimum contrast requirements.) It would never conflict with any other rules. Rendering a foo component would look exactly correct without any additional steps ever.
Pseudo selectors are where there is a huge issue. If you want a hover effect, you would need to listen to mouse events to update a state, then conditionally update based on that state. Same goes for focus. Pseudo selectors like
:before
and:after
and media queries can't even be supported without a css shim.You also totally lose out on some of the nice things in CSS, like customizing a child element based on the parent's hover/active/disabled state. There is no more cascading; state is your friend.
There is also a performance cost. Depending on the scenario it may not be significant, but there are some anecdotal jsperf tests floating around that all seem to point at inline being significantly slower.
https://jsperf.com/class-vs-inline-styles/2
I experimented with Radium, a pretty popular inline styling solution that abstracts the hover/focus/active state management. I don't think it will work well. There are some basic scenarios that work ok, but things like :focus just don't quite work right (in particular calling
Radium.getState
to get current focus state doesn't work.) It's also not being actively maintained (last checkin was almost a year ago.) It would also be pretty bad for perf, given how much more javascript will be executing. Also for server rendered scenarios, it's not that good since inline styling would create lots of redundant rules which would bloat the initial string tremendously.Pseudo inline styling (Aphrodite)
I'm currently looking at Aphrodite. This feels very much similar to Radium, but instead of injecting inline styles, it converts your javascript styling into effectively css module hashed classes on the fly. This gives us a bunch of benefits, such as defining rules in typescript and making a safe theme story that is super easy to use, but lets us use real css pseudo selectors. It also works really well with server rendering, by doing what I suggested above which is to expose a helper to get both rendered html and style strings.
This feels like a better solution than just scss converted into module css. We did some bundle size evaluation here. Turning on module css bulks up the bundle size from where we're at now, because the names turn into hashes which require extra typescript mappings to be output and consumed.
CSS Modules
Another option is to turn on css modules. This means that
.ms-Button
becomes.ms-Button_afe322ad
hash based on content of rule I believe. This removes the risk of collisions which is the most important point here, but it makes more complex theming features difficult... like calculating dark theme. This adds bulk to our bundle which we also don't like.Are there other options that are worth investigating?
The text was updated successfully, but these errors were encountered: