question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

@emotion/core vs vanilla emotion

See original GitHub issue

UPDATE: I published final writeup on this topic here. tl;dr I think vanilla emotion is a better option for the majority of React projects: https://vriad.com/blog/emotion-core-vs-vanilla-emotion


I’m a huge fan of the emotion module but am somewhat bewildered by some of the tradeoffs made in the design of @emotion/core.

I wrote up some thoughts as a blog post but haven’t published them yet. I want to give the Emotion team some time to respond to my criticisms. I don’t want to put publish a post that misrepresents this package or its design goals. It’s very possible I simply don’t understand some of the use cases you were optimizing for. Here’s a link to a Gist containing the text of my post: https://gist.github.com/vriad/23956586223e36931718399c0caa2eef

I’d hugely appreciate anyone who can shed some light on these decisions for me.

I absolutely love vanilla emotion which is why I’m sad to see it getting deprioritized in favor of core. I say this in the post but it’s worth repeating: I love Emotion and I’m hugely indebted to your guys for all your great work!

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:7
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

13reactions
Andaristcommented, Jun 2, 2020

not the inexplicably-named @emotion/core module

Just a note - we understand how this name is confusing and we are in the process of renaming this package to @emotion/react. It will be published as such when v11 gets released.

If you’re in one of those buckets, there’s a fallback solution! Just copy these two lines at the top of every React component you want to style with Emotion:

Well, truth to be told - this is the preferred way of using @emotion/core. It doesn’t require any additional configs and it works with the majority of the community tooling. It also makes it explicit for code readers that a particular file is using custom “createElement” instead of the regular one. For beginners, or just when exploring a different codebase, this might actually be seen as a positive thing - it’s inclusive.

Yes, you have to import jsx from @emotion/core even if you don’t use it.

I don’t agree with this statement - you have to only add this import if you are using jsx. In the very same way that you need to import React when you are using regular JSX - it only might be less of a pain because you often have React already in the scope anyway.

Note: this part might change in the future though as React has introduced automatic transform recently (https://github.com/babel/babel/pull/11154), we are waiting for the support for it to get released in React itself and for it also being supported by TypeScript team which is on their roadmap (from what I believe).

The usage of a non-native css prop kneecaps the portability/extensibility of your component; it’s now unusable in any codebase that isn’t configured to use @emotion/core. Bad!

The goal is to provide predictable styling - we can only do that if we control the styling, thus this actually helps us ensure that you are using emotion-generated styles. Otherwise, you can find yourself in the middle of specificity wars once again.

Also: render props?! What is this, 2018?

This really sounds very aggressive and out of place. Even if a little bit quirky render props are still valid for some use cases and this is one of them (at least for us). I’m actively thinking about a different API for this but it has to work with 0 config SSR and that’s not an easy feat for this feature. We don’t believe this is much of an issue because you rarely should use non-emotion styles (ideally you wouldn’t have to use them at all).

don’t appreciate that Emotion tries to drive people towards @emotion/core instead of tellling them how insanely easy it is to set up SSR themselves with vanilla emotion.

Many people are tired of configuring things. The configuration also spills itself on all of the consumers. Emotion is used, sort of, as an engine for multiple other libraries, and with 0config approach they don’t have to educate their consumers (who might not even be aware of using Emotion under the hood) that they need to setup something for SSR. It just works.

Emotion provides no concrete guidance on how to do this, just a link to a sample Next.js project (this one).

Well - it’s not our responsibility to document how to integrate Emotion with all of the fancy meta frameworks. We understand that we could maybe give guidance on how to integrate with the most popular ones, but there are already dedicated packages for this, so not sure why we should bother duplicating efforts. If you feel that their docs are lacking something you can always try to improve them by providing helpful PR. Also - those packages are only needed if you want to do something custom. 0config approach is, well, 0 config so it doesn’t require any extra documentation. That’s why we recommend it - we don’t have to integrate in any special way with any other tool, things should just work if you stick to the 0 config approach. The time we can spare on the project is also not infinite, so we don’t feel like documenting the stuff we don’t really recommend.

Themeing: Touting this “feature” is preposterous

I believe many would disagree and you also sound very aggressive here which I don’t find to be OK. However, we agree that builtin theming is not needed, there is an open PR which we’d like to revive with arguments laid out against it: https://github.com/emotion-js/emotion/pull/973/files . We’ve found out that people like the builtin theming though, so we are keeping it - but we plan to emphasize that there is a better way of doing things in v11 docs.

Perhaps there are lots of great reasons to use @emotion/core that I’m not seeing and aren’t in the Emotion docs

Because we don’t give you string class names back, but rather just opaque objects, the rule insertion is lazy. This might not be as interesting on its own, but it allows us to customize injection through a <CacheProvider>. Use cases for this are not as common - but they exist and once you ever come across one then you might be very thankful for the path we’ve chosen because otherwise re-implementing stuff to accommodate new requirements could be very hard. With vanilla Emotion to customize this stuff, you need to create a custom instance and use it everywhere. Main things that can be customized:

  • prefixing rules
  • parser plugins
  • container element (very important for rendering into iframes)
  • nonce (very important for CSP)

This allows libraries built on top of Emotion don’t care about this stuff because, if needed, the final consumer can decide about this stuff.

I’ll also be incredibly thankful and indebted to them for building the true “core” emotion package, which is a glorious achievement and a huge win for developers!

If the chosen tradeoffs are not for you then you are welcome to continue using vanilla Emotion. We don’t plan to remove the support for it.

3reactions
colinhackscommented, Jun 2, 2020

@Andarist I really appreciate all this feedback! I want to apologize for the tone - it was far too aggressive in all the cases you mentioned. I got a little carried away. I certainly won’t publish this until that’s been corrected.

I’ll admit upfront I haven’t been following the API updates coming in v11 - I’ll look more deeply into that.

I agree that

  • my complaint about importing jsx is invalid
  • it’s not your job to document how to do SSR with Next/Gatsby
  • people are tired of configuring things (which is part of my problem with core!)

There’s a lot I don’t understand about the use cases you’re optimizing for. Frankly I hope I never encounter a scenario that necessitates the use of CacheProvider 😅! Sounds hard.

I don’t understand how the css prop makes styling more predictable than vanilla Emotion. Is there a resource you can direct me to that explains that a bit more? Or am I misreading that?

My primary source of my frustration is something that I only briefly alluded to in my writeup: the documentation explicitly steers people to @emotion/core over emotion, yet for a majority of cases emotion is the better choice. With core:

  1. You get theming, but theming is better handled with Context/hooks/other language features (seems we agree on this)
  2. The css prop breaks portability/encapsulation (one of the core philosophical pillars of React)
  3. You need to modify the markup to get access to cx

It seems like all of these tradeoffs were made in the name of zero-config SSR, which isn’t a consideration for a hefty majority of React-based SPAs.

My recommendation would be to make these tradeoffs more explicit in a documentation, and two present these approaches as two equally valid options (instead of explicitly recommending core for React projects). Based on npm downloads, it’s clear that emotion has plateaued in usage in the last 18 months, whereas core has tripled. I suspect in a majority of cases the developer would have been better served by vanilla, but didn’t think to go against the officially recommended route. If that developer found Emotion via NPM or this repo’s README, they may not even know about the existence of the vanilla option - it’s not mentioned anywhere.

You should know that all of my thoughts are colored by the fact that I LOVE cx. My whole approach to styling is dependent on the composition of many small utility classes. Getting rid of simple, markup-free cx usage in favor of zero-config SSR isn’t a tradeoff I agree with (and that’s okay!). But the fact that vanilla/cx aren’t the “recommended” approach (and are therefore hugely underutilized) makes me a little sad.

Thanks again for your feedback. I’ll let you know if I decide this post is worth publishing. And great work - seriously.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why you shouldn't use @emotion/core - Colin McDonnell
@emotion/core is the React-centric Emotion wrapper that gives you some extra goodies, specifically server-side rendering and theming.
Read more >
@emotion/core vs @vanilla-extract/css vs tailwindcss | npm trends
Comparing trends for @emotion/core 11.0.0 which has 4317666 weekly downloads and unknown number of GitHub stars vs. tailwindcss 3.2.1 which has 4373355 ...
Read more >
What is the benefit of @emotion/react over @emotion/css for a ...
Both are valid and each approach has its benefits: emotion/css : use vanilla react className prop; no custom jsx parser; no babel config...
Read more >
Install - Emotion
Vanilla. If you're not using React, you can use vanilla Emotion from the @emotion/css package. Most of the documentation here focuses on the...
Read more >
You probably shouldn't use @emotion/core : r/reactjs - Reddit
Unless you have need server-side rendering or custom CSS injection/prefixing behavior, vanilla emotion should really be your go-to choice ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found