Problem description:
We love to use emotion in our React projects, the problem is that we also have a static non React webpage (the start page basically). Our react pages share the same styling as this non React page so we are currently using sass and className (in React) to share styling between them (where needed).
_The question is, does emotion have or have plans for solution where we can extract the css out from a styled component? I know it's very common to do it the other way (converting old sass/less to a styled component) but this is basically doing that backwards._
This would allow us to use our styled components as the "source of truth" and then do some kind of build step where we can take all exported styled components and convert them back to a regular .css stylesheet to use in non React apps.
Suggested solution:
I have actually built a version of this that kind of works (by using the innerRef of a styled component, findings its css class and reading it's innerHtml during render) but I wonder if a better or "official" way exists?
It would look something like this:
export const PinkHeader = styled("h1")(props => ({
fontSize: props.primary ? 40 : 20,
color: "hotpink"
}));
getCssFromComponent(<PinkHeader />, "pink-header");
// Returns //.pink-header {font-size:20px;color:hotpink;}
getCssFromComponent(<PinkHeader primary />, "pink-header-primary");
// Returns //.pink-header-primary {font-size:40px;color:hotpink;}
This would allow us to build regular stylesheets from our styled components to use in the non React pages.
Can we achieve this somehow today, if not is it something worth building? 馃槉
Thanks for a great library!
There is currently no official way of doing this, but I know that people done this in example here. This possibly could be extracted to separate project (and possibly also automated even more, i think they are putting labels manually into their styled calls) and in general I think this would be very useful.
EDIT: Checked out your link and just like they did I could get this to work without rendering to the DOM using react-test-renderer and emotion.caches. Interesting...
Yes it would be a really nice feature to have! For anyone interested I just made a really simple implementation using a "convert to css" component (for testing purposes) that spits out the css in the console. Not working with media queries etc right not but just a simple example of one way, but I bet there are far better ways than this hack, just using the fact that I can easily get hold of the DOM node this way 馃槉
Usage:
return (
<div>
<ConvertToCss outputClassName="pink-header-normal" component={() => <PinkHeader />} />
<ConvertToCss outputClassName="pink-header-big" component={() => <PinkHeader primary />} />
<ConvertToCss outputClassName="avatar" component={() => <Avatar />} />
</div>
);
Source:
export class ConvertToCss extends React.Component<ConvertToCssProps> {
componentDidMount() {
const html = findDOMNode(this) as HTMLElement;
const className = html.className;
console.log("." + this.props.outputClassName + " {" + this.getStyleSheetPropertyValue("." + className) + "}");
}
getStyleSheetPropertyValue = (selectorText: string) => {
// search backwards because the last match is more likely the right one
for (var s = document.styleSheets.length - 1; s >= 0; s--) {
// To handle Chrome security exceptions locally
try {
if (document.styleSheets[s] && (document.styleSheets[s] as any).rules) {
var cssRules = (document.styleSheets[s] as any).rules;
for (var c = 0; c < cssRules.length; c++) {
if (cssRules[c].selectorText === selectorText) {
return cssRules[c].style.cssText;
}
}
}
} catch (error) {}
}
return null;
};
public render() {
return this.props.component();
}
}
This would be extremely useful for integrating a React frontend into a Wordpress TinyMCE custom styles. As we can have the source of truth for styles be react and then "build" a stylesheet just for TinyMCE.
I'm looking for the same functionality too, I was hoping that the createCache will store the styles in the cache, but unfortunately, it doesn't. Was hoping that there's an equivalent of extractCritical available during render so that I can extract the styles immediately.
Nice to have feature!
This is currently out of emotion's scope. One of the main selling points of CSS-in-JS is auto-generation of unique class names and dynamic composition. It's really hard to extract stable human-readable class names having those constraints (especially the dynamic composition).
This can probably be done, with the help of code conventions and such - but the implementation of this would have to come from the community. We don't have plans to work on this right now.
Most helpful comment
EDIT: Checked out your link and just like they did I could get this to work without rendering to the DOM using
react-test-rendererandemotion.caches. Interesting...Yes it would be a really nice feature to have! For anyone interested I just made a really simple implementation using a "convert to css" component (for testing purposes) that spits out the css in the console. Not working with media queries etc right not but just a simple example of one way, but I bet there are far better ways than this hack, just using the fact that I can easily get hold of the DOM node this way 馃槉
Usage:
Source: