Probably outside the scope of this module, but we could document how to make this work:
<script jsx type="text/sass">{`
p {
color: red;
& a {
color: #fff;
}
}
`}</script>
Note: whoever writes this transformation must be aware that we auto-prefix already. I know that many SASS compilers do that as well, so we'd have to avoid it
I'm looking into adding this to stylis, ping me if you have implementation ideas.
Having a documentation about how to add own css transformation rules would be really useful.
Note: whoever writes this transformation must be aware that we auto-prefix already.
Btw, this is also important part missing in docs. Autoprefixing should be at least configurable to define supported browsers.
@rauchg @thysultan @operatino why not simply do it like csjs? They allow compile time babel transforms:
Links:
https://github.com/tizmagik/react-csjs
https://github.com/rtsao/babel-plugin-csjs-postcss
Real world example using CSSNext, Autoprefixer and a minifier/compressor:
https://www.reddit.com/r/reactjs/comments/5gjc08/styled_components_the_future_of_react_styling_in/dat7wr0/
That way any postCSS transform can run over the css, you'd open this up to an entire, existing eco system instead of porting a single thing. You could safely remove the autoprefixer as well as it's no longer needed. PostCSS prefixers are fully configurable so there goes another issue.
{
"plugins": [["csjs-postcss", {
"plugins": [["autoprefixer", {"browsers": ["last 2 versions"]}]]
}]]
}
So i already got a working version of this for stylis that i'll push with the next release and it's only like ~40 lines so i'm pretty impressed with the results, the way it works is when it finds a block it skips it but adds it as a block to the end of the string buffer namespaced to it's parent, when the parser finally comes across it again the same thing will happen for any nested blocks within it, recursively until there are no more nested blocks.
so this...
h1, div {
color: red;
h2, &:before {
color: red;
}
color: blue;
header {
font-size: 12px;
}
}
becomes this...
h1,
div { color: red; color: blue; }
h1 h2,
h1:before,
div h2,
div:before { color: red; }
h1 header,
div header{ font-size: 12px; }
^^ v0.8.0 now supports this.
+1 to cssnext, we would avoid lot's of bugs ( like #68 ) with full-featured css transpiler. Dependency size is not an issue since it's compile time step
...also it's not mutually-exclusive to stylis! postcss is a css-to-css compiler, so styled-jsx can easily do postcss -> stylis. stylis can take care of the [data-jsx] scoping, postcss can take care of the rest.
Personally I'm looking forward to using postcss-import and postcss-cssnext.
<style jsx>{`
@import './variables.css';
.button {
& .icon { background: var(--color-danger); }
}
`}</style>
In fact, you can use this approach above to take the CSS out of your .jsx files, if mixing them together isn't for you :)
/* components/button/index.js */
<div>
<a href='' class='button'>Click me</a>
<style jsx>{`@import './style.css';`}</style>
</div>
/* components/button/style.css */
.button { background: var(--color-danger); }
Btw, I tried looking at getting postcss implemented in styled-jsx, but postcss's API is async while (afaik) Babel plugins are sync :\
Dependency size is not an issue since it's compile time step
Good point. Unlike styled-components we don't compile at run-time so we could as well use PostCSS and take advantage of its ecosystem and the AST. cc @rauchg
More specifically, cssnext is a perfect fit for the styled-jsx paradigm, since it's basically like "babel for CSS." It takes proposed CSS additions and implements them. I'd love to see a more standard approach to CSS variables.
Using PostCSS sounds like a good idea but I wouldn't go as far as picking an opinionated preset of plugins (like cssnext) that sometimes can't fully polyfill css features (e.g. custom properties or color functions).
IMHO we would need a custom plugin to add scoping, autoprefixer and :global. Then we can make the preprocessor so that users can load custom plugins with postcss-load-plugins or like we do it in suitcss preprocessor.
Babel plugins are sync
correct
One of the reasons I don't like postcss is that it increases the compilation time and memory allocation very significantly :(
That said, I think there's a lot of merit to supporting features like darken(), & etc that come from the SASS / stylus / LESS crowd.
@import is actually a bit controversial for _us_. We had it in the original Next.js and it led to a lot of really questionable decisions, like using big stylesheets to style a bunch of elements at once instead of creating neatly separated components. We ended up with a bunch of big stylesheets all over the place, and we found that taking away the feature was a really good idea.
@drcmda I wrote that plugin for styled-jsx! Actually I never read your post and while I was writing the babel plugin I found the csjs one 馃槄 (should have read the thread more carefully)
https://www.npmjs.com/package/styled-jsx-postcss
It works on styled-jsx transformed code so autoprefixing is still done by styled-jsx.
Hope you find it useful. cc @rstacruz @operatino @sidorares
I'd love to see a more standard approach to CSS variables.
@rstacruz Like scss? I'm adding this in the next version of stylis and other scss like features see the changelog, including the possibility for @imports via middleware, though i'm still not yet sure if middleware should be a single function that you can optionally compose from many functions as well or an array of middlewares that are composed internally.
It works on styled-jsx transformed code so autoprefixing is still done by styled-jsx.
@giuseppeg , this is amazing. Exactly what i was looking for, but i am having difficulties with implementing it with nextjs. Fails at babel compilation with below error.
Any pointers or examples i can look at that implements into nextjs, since styled-components is used by default.
Property value expected type of number but got string
at Object.validate (/Users/ganeshu/Code/mysite/node_modules/babel-types/lib/definitions/index.js:161:13)
Below is my .babelrc
{
"presets": [
"next/babel"
],
"plugins": [
"styled-jsx-postcss/babel"
]
}
@raavanan can you open an issue on the styled-jsx-postcss repo? I need to update the dependency to ^0.4.0
@rauchg people who want advanced features/preprocessing can now use styled-jsx-postcss. I could add a section to the README if you want. Can we close this issue or do you want to keep it open for reference?
Just for reference, a styled-jsx-postcss example is at next.js/examples/with-styled-jsx-postcss
That said, I think there's a lot of merit to supporting features like darken(), & etc that come from the SASS / stylus / LESS crowd.
I couldn't agree more, I think these are pretty mandatory actually, especially &
Those can all be achieved with postcss plugins and https://www.npmjs.com/package/styled-jsx-postcss
@giuseppeg this is awesome. Thanks a lot!
What about stylus?
/cc @giuseppeg
I would really like to see example how to use scss syntax with styled-jsx-postcss. PostCSS with ton of plugins and modules makes me confused how to even integrate it with webpack and react. :)
Most helpful comment
What I'd rather see is postcss support.
More specifically, cssnext is a perfect fit for the styled-jsx paradigm, since it's basically like "babel for CSS." It takes proposed CSS additions and implements them. I'd love to see a more standard approach to CSS variables.