Hi there! 👋
I have a feature request :). Would it be possible to provide the ability to (intentionally) scope/increase the specificity of emotion generated classNames?
Full transparency, I also opened up an issue in styled-components, and some of the folks and I are discussing this feature now.
I can't say this strategy/implementation is battle tested… but it's working well for the stuff I'm building for my company 👍 . I believe that it's a nice feature/enhancement for any CSS-in-JS library as it provides additional control and the ability to integrate into older systems.
The use case for this would be if we wanted to implement emotion React components into an older applications, with hostile pre-existing CSS rules (that probably won't/can't go away soon). The company I work for has this very use-case!!
I've refactored the styled-components-like library (I called it Fancy) that I use for my company. It now uses a enhanced forked version of Emotion under the hood.
ScopeProvider 🔎I went with the strategy of creating a ScopeProvider (wrote some docs here).
Example:
<div>
<StyledCard />
...
<ScopeProvider scope="html #App">
<div id="App">
<StyledCard />
</div>
</ScopeProvider>
...
</div>
The idea is… anything created with styled should not have to worry about scope… therefore, no need to manually add prefixes (when you create them).
If it appears under a ScopeProvider, it will then get prefixed by anything defined by the ScopeProvider. If it appears outside, it's business as usual. It allows for styled components to seamlessly be used inside/outside of scoped areas.
This strategy allows for scoping to be added to an existing application/system of styled components without changing anything, minus the root(s) where ScopeProvider needs to be added, which is nice.
The way I've written ScopeProvider works very much the same way as how ThemeProvider works (context + internal broadcast + sub/unsub for the styled component). The only tricky bit coordinating and sending that prefix (string) to stylis during the CSS processing phase (if a scope is defined).
Here's the source code. There's not much too it! The heavy lifting comes from the styled-component factory and style rule generator
If you're interested in exploring my fork (aka. HAX, haha)… I copied over various files from Emotion into my own project (thank you for making everything so modular!), and only touched what I needed to. Anything custom I wrote should have comment blocks :).
Here's a quick demo of ScopeProvider working. If you inspect element, you can see the compiled className is scoped under #App.
Yo dawg, I heard you like Scope…
I know the strategy ThemeProvider extends previously established theme configs when nesting happens. For scoping, I think it's probably simplest to assume that only the closest ScopeProvider scope will be used. No inheriting/chaining.
Thank you so much for your time!
P.S. If this idea sounds good to you, I can create a PR with this feature 🙌
Side note...
This is out of scope for this feature request, but I took the same strategy and applied it to another tricky issue that libraries like styled-components, emotion, jss, etc… have, and that is correctly rendering styles within iFrames. I did this by creating a FrameProvider.
<App>
<StyledCard />
<Frame>
<FrameProvider>
<StyledCard />
</FrameProvider>
</Frame>
</App>
The FrameProvider is used within your iFrame (folks usually use react-frame-component). If any styled components render within, the FrameProvider will provide the style generator with the correct document to render it's style tags into. (We can discuss this in another GH issue if you're interested)
Here's a quick demo of the FrameProvider working.
Thanks again for your time!!!
I've created stylis-plugin-extra-scope exactly for this. You can see my answer on how to use it here. I believe it should cover your use case completely - using different scopes etc shouldn't be needed I think.
Definitely this is an interesting problem, we could discuss it in other issue.
Both of these issues are something I'm trying to address with emotion@10 (#637).
With the the current alpha of emotion@10, I was able to create both of these APIs. The implementation isn't perfect, for example it doesn't pass theme down through the providers but that's fixable.
Just a note: The exact APIs will definitely change before the actual release of emotion@10 and you shouldn't rely on them right now.
@mitchellhamilton OH DAMN! THIS IS SO GOOD 😍😍😍
@mitchellhamilton this is bonkers 👏🔥🤩
@mitchellhamilton Wow! This is amazing! Those features are exactly what I was trying to build, but you did it way better, haha.
I guess we can close this issue up since you're working on something that resolves these requests :).
Once this is released, if FrameProvider / ScopeProvider aren't going to be part of the core emotion package(s), I'd be more than happy to write an add-on or something based on your implementation!
👏 👏 👏
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions.
any update regarding this issue ?
I'm trying to move my global scope into a specific part of the page.
Has anyone gotten this to work with with the standard syntax? (className={css...}
Here's a sandbox. Seems like the <style> tags for those applied classes don't get pulled into the iframe.
@Reklino you would have to use create-emotion package configured with a custom container.
Emotion is by default bound to document.head of the context in which it got initialized, so to your main page here.
Most helpful comment
Both of these issues are something I'm trying to address with emotion@10 (#637).
With the the current alpha of emotion@10, I was able to create both of these APIs. The implementation isn't perfect, for example it doesn't pass theme down through the providers but that's fixable.