Closed KingScooty closed 6 years ago
Are you sure you really need css-in-js? If you trying to solve the problem of unused styles elimination than I think you should check react-universal-component
first. Especially how they handle styles splitting.
In my opinion, css-in-js is useful when you need dynamic styles based on theme or component's props. If you need to encapsulate your styles then CSSModules is to the rescue. Otherwise, all these tools can be overengineering 😉
Are you sure you really need css-in-js?
Ha! Well this is it. I don't know! 😄 I've never really thought too much about it, but it seems to be all the rage at the moment, so i thought i'd explore what it does, and what it's good at. The problem it solves is quite particular. To me it really makes sense to be able to import just the bits of css you want for a particular component. Similar to how a dependency in JS would work. CSS would really benefit from being object based, so tools can intuitively strip out what's not being used.
And when i say CSS, i mean reusable patterns. Not styling like colours. Just underlying structure. It's the same code repeated all the time. So it kinda makes sense to have as an npm package with sensible exports that you can just import.
I think you should check react-universal-component first.
I'll look into react-universal-component! I've not seen that before. I wonder if it'll integrate nicely with nextjs?
In my opinion, css-in-js is useful when you need dynamic styles based on theme or component's props. If you need to encapsulate your styles then CSSModules is to the rescue. Otherwise, all these tools can be overengineering 😉
Yeah, i tend to agree! The encapsulation is nice, but the dead code elimination is really what tempted me to try it!
Hi @KingScooty styled-jsx is string based only and composition as you want it is not possible because of the way how we transpile our styles (it might be possible though in the future with this syntax https://github.com/zeit/styled-jsx/issues/383#issuecomment-358287330).
The cost of external styles right now is double see https://github.com/zeit/styled-jsx/issues/345 We will fix that in v3.
Doing dead code (CSS) elimination with string based libraries is not that easy and can only be done for colocated and static styles only. That said when you use something like Next.js that does automatic code splitting for you having CSS in JS modules is nice. For completeness you could achieve the same using CSS Modules and including a common.css
and page-name.css
(page specific) bundles, but if you have ajax navigation etc you'd then need to add/remove link
tags on page transitions (I've built apps like this in the [very] past).
FYI styles in styled-jsx are de duped, meaning that the styles for .o-block
will render only once in your page (even if you have multiple instances of the consumer component).
Looking at your examples I would say that maybe you can make a component library rather than importing the styles all the time. For instance I would use a Block
component:
export default () => (
<Block size="small" align="right">
<Block.Image>
<img src="https://placeimg.com/400/200/animals" alt="" />
</Block.Image>
<Block.Body>
<p>This is some text.</p>
</Block.Body>
</Block>
)
// or
export default () => (
<Block size="small" align="right">
{{
image: <img src="https://placeimg.com/400/200/animals" alt="" />,
body: <p>This is some text.</p>
}}
</Block>
)
Open to discuss on the merits of Object literals based CSS-in-JS solutions (something like React Native for Web's StyleSheet is next level imho).
Hi @giuseppeg! Thanks for the reply! #383 looks interesting! It would certainly add more power to styled-jsx.
I think you're right regarding building a component library as opposed to importing styles. The more i've played with various CSS in JS implementations, the more i've realised what i was doing was very unconventional.
I really like that syntax in your first example. I've not seen that before:
export default () => (
<Block size="small" align="right">
<Block.Image>
<img src="https://placeimg.com/400/200/animals" alt="" />
</Block.Image>
<Block.Body>
<p>This is some text.</p>
</Block.Body>
</Block>
)
How are those children blocks defined? (<Block.Image>
etc.). If you could show an example of what the definition of this component looks like that would be amazing.
@KingScooty not sure if that's the best pattern but I would implement that like this https://codepen.io/giuseppegurgone/pen/bLpaGW
@giuseppeg you're a star! Thanks so much for that example! I'd actually been trying out some of @jxnblk's tools this weekend, so it's nice how this fits in with Dan's comments over at macro-components!
Nice! I am going to close this issue but feel free to reply here if you need further help/want to brainstorm.
So i really want to get into using CSS in JS, but i really feel a lot of the time it's an "all or nothing" solution to a problem that mostly goes away if you just write well structured, namespaced CSS. It's great for components like a "button", but gets quite clunky when doing bigger things. Things that would be quite fast to write in vanilla HTML and CSS end up needing a React component and then tests, and it just gets a bit too unnecessarily abstract (like grids etc).
I'm a big fan of NextJS. And normally i include a
base.css
full of reusable patterns (written in Sass) in the head, and then start writing my app—only really using CSS in JS (styled-jsx) to enrich the patterns used in mybase.css
.But a lot of the time, 50% of that css file goes to waste. It's not used in the app, which results in unnecessary downloaded bytes. This is why CSS in JS appeals to me, as you get dead code elimination for free.
I'd really like to convert my CSS pattern library (a group of reusable CSS objects, that just structure content, and don't add any visual styling like colours etc) to use something like styled-jsx. The idea would be if i exported each block small enough, I could just import the sections each component needed and then i'd get a ton of dead code elimination as i visit each page.
I'm trying out a few things, and would really like someone's input on whether i've completely lost the point with this CSS in JS stuff, or whether there's some sense in what i'm doing.
Here's an example of a CSS pattern called the block pattern that i've attempted to port over.
This could then be consumed in a component like so:
I see these patterns as global styles. Then custom styling like colours can be scoped on the component.
What i notice straight away is there would be a hell of a lot of
style
tags if i did this. Is that scalable? Or am i going to hit problems?Have i got the right idea? Or am i using
styled-jsx
wrong?Another way i could do it is be a bit more clever with the composition of my styled jsx rules, as each of the variants in that css-jsx file depend on the
base
class/variable. So is there a way i can merge the rules?Example:
flush
requiresbase
in order to work. I'm keen not to lose my syntax highlighting by removing thecss
function call, so it would be cool if i could say thatflush
requiresbase
as a dependency.That way, i'd only need to do:
Instead of:
What are people's thoughts?
I'm aware styled jsx is string based, and not object based (is that still true?), but if the styles are broken down small enough, importing just the bits you need should still be really beneficial.
I can definitely see that there's power in CSS in JS, but i'd really like to merge old world with new world. Traditional CSS enriched with JS to take advantage of the added benefits without losing the flexibility of writing raw HTML and CSS.