Do you want to request a feature or report a bug?
Feature
What is the current behavior?
-
If the current behavior is a bug, please provide the steps to reproduce and a minimal repository on GitHub that we can yarn install and yarn test.
What is the expected behavior?
The current behavior is
// Input
const header = css`
text-transform: uppercase;
font-family: ${fonts.heading};
font-size: ${modularScale(2)};
`;
// Current Output
const header = 'header_t1ugh8t9';
// Expected Output
const header = 'tt_swer3 ff_Sers34 fs_5tsdf';
/*
tt_swer3 -> text-transform
ff_Sers34 -> font-family
fs_5tsdf -> font-size
*/
Please provide your exact Babel configuration and mention your Linaria, Node, Yarn/npm version and operating system.
@satya164 I very excited about this and if you are fine with this feature, I am ready to experiment by integrating https://github.com/linkedin/opticss with linaria to optimize the output.
Note: This can be added as non-breaking change by adding this as feature flag until it gets stable.
@asvny I think it'll be great. maybe we would want to have a separate package or entry point linaria/atomic if the implementation diverges too much. The only problem I see is that this feature can only work with css tags. With styled tags, there will be specificity issues when decorating existing styled component.
@satya164 I am not able to get this point
With styled tags, there will be specificity issues when decorating existing styled component.
Can you please provide an example?
@asvny so for example, say you have this:
const Button = styled.button`
background: orange;
`;
const FancyButton = styled(Button)`
background: blue;
`;
here, the background of FancyButton will override the background of Button because we generate a more specific selector (Button will generate something like .abcdef and FancyButton will generate something like .abcdef.tyuio). could be difficult with atomic class names. but probably we can avoid atomic class names for components like FancyButton too properly handle it.
it is possible to resolve the styles if you use a specific naming convention and process the atomic class names right to left when applying them. I do that in DSS https://survivejs.com/blog/dss-interview/ and in https://github.com/giuseppeg/style-sheet
I'm closing this issue because it's pretty old and not upvoted, we have other priorities right now
I would have loved to see this coming though! So sad to see it has been closed!
This is the approach taken by the new Facebook style lib, which would be open source at some point.
But I think, considering it seems that lib is quite opinionated in the way to write CSS (ReactNative style), it would be good to see this in Linaria as an opt-in feature.
If I have some time, does anyone mind me spiking it?
@giuseppeg I'm impressed with your work on this, and as you are waay ahead of me, any chance we could have a brief conversation about how to possibly spike this in Linaria as a POC?
(It would still be Callstack final say if they are happy to integrate this or not and how)
@jayu mind reopening then? :) I think being able to have atomic css would be great, because it scales well in larger codebases.
I'm a big fan of this proposal 鈥斅燼nd as Stylex will likely be open-sourced at some point, it makes sense to be ahead of the ball on implementing this.
The great benefit is that it results in logarithmic instead of linear growth of CSS when adding new features with styling. This can result in massive savings for large apps (in Facebook's case it reduced their CSS payload by 80%)
Well said @jayu and @Jayphen!
There's also an element of bringing the same innovation that company like Facebook are discovering and promoting outside of those companies tools, to be part of open source alternatives that have a different model.
I'm personally a big big fan of Linaria, as I thing THAT is how CSS-in-JS should be done.
But there's also a less opinionated view on top of this, which is the one that CSS-in-JS with a JS runtime does not suit every use case (i.e. a Gatsby blog or other types of mostly static pages with few interactions). The idea of using CSS-in-JS just as a Dev Experience tool as opposed to pay the cost in the final result as well, is something that brings us closer to how the browser uses the resources.
Plus, compile time, I mean, I don't think can be beaten...
That's why I think that generated Atomic CSS is a good combination with this as it fits the paradigm of Linaria very well, where you write CSS the way you learned it, so this is just an optimisation on top...
Good to see some discussion in this repo :D I'm not opossed to the feature, I was doing issue triage a month ago and I closed this since it wasn't upvoted and I didn't get the idea behind it.
I still don't have time to implement it myself, but I'm open to check any PoC! This is not easy thing to implement in linaria, but if someone will manage to do it, I'm good.
I'm a bit afraid about build time, but we will see :D
Hey @jayu!
Definitely I'd like to make a PoC of this and see how it goes.
It will be challenging for sure, that's why I might just make a PoC of the final outcome and open a PR to discuss all the point where we need to improve it, which I will need some help on probably even just to understand some behind the scenes mechanisms...
I looked into how atomic CSS might work and unfortunately, due to we support nesting in linaria, it would be impossible to have both atomic output and nesting classnames. We could probably have atomic CSS as a derivation or however it could be called, with restricted syntax support. Atomic CSS would make it very hard to make https://github.com/callstack/linaria/issues/244 work.
I'm also wondering how we could deal with redundantly generated class names.
The problem is we process each file with babel, but the next file does not about the previous processing, so we may end up with a declaration for a particular class name repeated 10 times.
We could implement some cache that will save the information about whether the class was already generated or not, how to decide then for which file the class should be generated. What if the class will be removed from the file, but needed by other files. We will need a different build configuration for production and development then. It will be definitely challenging :D
StyleX will probably have some super fancy compiler for that, we are not that advanced :P
My two cents ...
StyleX is not magical but actually quite simple and follows react-native stylesheet pattern. It is authored like
const styles = stylex.create({
backgroundColor: 'red',
color: 'white'
})
I possibly assume that they force developers to author only longhand properties and think in terms of logical properties like margin-inline, block-size etc..,
Then babel compiles it
const styles = {
backgroundColor: 'hash1',
color: 'hash2'
}
When it needs to resolve multiple object styles, it does something similar to Object.assign
const styles1 = {
backgroundColor: 'hash1',
color: 'hash2'
}
const styles2 = {
backgroundColor: 'hash3',
textTransform: 'hash4'
}
const classes = Object.values(Object.assign({}, styles1, styles2));
So coming back to Linaria, it is hard to get it right because of the nesting problem. There are two things that we can do
The reason why I suggested Opticss is that for efficient atomic CSS generation, we have to know the template/jsx on how it is being used and based on that we can allow certain combinator selectors (like the ones you see in LinkedIn's CSS Blocks). OptiCSS has ways to solve cascade by analyzing the document/jsx etc...(https://github.com/linkedin/opticss/blob/master/packages/resolve-cascade/README.md). And I think at the sample time, OptiCSS is experimental and not yet ready for production usage.
It definitely is a hard problem to solve, given the case nesting is allowed.
fwiw style-sheet my (pof) CSS in JS library is based on the same principles of stylex, actually I started to build it way before FB talked about it publicly.
To extract styles it uses Linaria's evaluation helper, taken from Linaria's Babel plugin. It's just hasn't been updated in a while https://github.com/giuseppeg/style-sheet/pull/17
I can see the challenges in this using babel @jayu .
I was thinking to use webpack for it instead, but yeah not sure if feasible.
On @giuseppeg's comment, I wonder if it's applicable without using objects, using simple strings as Linaria does (which is mainly why I like Linaria, as it's easier to migrate to and keeps syntax aligned and compatible with standard CSS)...
For what's worth, on @asvny's comment, https://github.com/CraigCav/css-zero :)
If you are interested in stylex, I have created an open-source implementation of it here.
Very interesting conversation 馃槏
Wanted to mention Fela which produces atomic CSS like this:
.a { text-align: center }
.b { padding: 5px 10px }
.c { font-size: 14pt }
.d { border-radius: 5px }
.e:hover { font-size: 16pt #}
鉂わ笍馃殌
Most helpful comment
I would have loved to see this coming though! So sad to see it has been closed!
This is the approach taken by the new Facebook style lib, which would be open source at some point.
But I think, considering it seems that lib is quite opinionated in the way to write CSS (ReactNative style), it would be good to see this in Linaria as an opt-in feature.
If I have some time, does anyone mind me spiking it?