DEV Community

Cover image for Using emotionJs with Vite
Ajit Singh Kamal
Ajit Singh Kamal

Posted on • Updated on

Using emotionJs with Vite

Disclaimer: the post is now quite old. Vite has a dedicated react plugin which you can easily configure now to get the intended outcome. The comment section has better snippets to help you :)

Vite is the next cool thing everyone's talking about. For the uninitiated, it's a tool that provides a dev server with a blazingly fast refresh(HMR) speed and comes loaded with the Rollup module bundler for generating highly optimized builds.

Most of you would already be familiar with EmotionJs - a very popular CSS-in-JS library. It comes with a react flavor which provides a css prop that greatly enhances the overall developer experience of writing styles in your react component.

emotion's css prop official doc example
An example from the official docs

However, every time we need to use this very convenient CSS prop, we would need to add emotion's custom JSX pragma on the very top of our jsx component.

/** @jsx jsx */
import { jsx } from '@emotion/react'
Enter fullscreen mode Exit fullscreen mode

If you are planning to give Vite a shot - The good news is that you don't need to do any additional tinkering. Emotion will work without any break when using the above approach. But, there is a far better way, with which we can simply avoid importing this chunk of import in all our JSX files.

To do that - you'd need to update the esbuild options in your project's vite.config file.

import { defineConfig } from 'vite';


// https://vitejs.dev/config/

export default defineConfig({
   plugins: [...],
   esbuild: {
     jsxFactory: `jsx`,
     jsxInject: `import { jsx } from '@emotion/react'`,
   }
   ...
});

Enter fullscreen mode Exit fullscreen mode

Vite uses esbuild under the hood for compilation.

  • jsxInject simply set esbuild's --inject transformation option and auto imports the provided module in all .jsx files.

  • jsxFactory overrides the default React.creatElement with emotionsjsx` factory function.

And, that's it. You can now use emotion in all your jsx components by default.

If you want you can also import the css function along with jsx to avoid it importing later in your components to construct serialized style objects.

jsxInject: `import {jsx, css} from '@emotion/react'` 
Enter fullscreen mode Exit fullscreen mode

Oldest comments (10)

Collapse
 
cheapeone profile image
Christopher Cheape

awesome! was just messing with this today

Collapse
 
vfonic profile image
Viktor

Thanks for the tips!

It would help if the code was added using code block rather than an image. People with disabilities might not be able to read the code from the image and it's harder to copy-paste it. :)
And this code is definitely something I'm looking forward to copy-paste rather than try to type in myself (I don't see much benefit from typing and/or memorizing this)

Collapse
 
ajitsinghkamal profile image
Ajit Singh Kamal

Thanks for the suggestion Viktor. Edited my post.

Collapse
 
ondevto profile image
205g0

Nice post! How would this work with Typescript? With your solution TS complains that css does not exist on that type...

Collapse
 
glocore profile image
glocore

I faced the same issue, adding this to tsconfig.json fixed it for me:

"compilerOptions": {
  "types": ["vite/client", "@emotion/react/types/css-prop"]
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
vfonic profile image
Viktor

I'm trying to use component selectors in my emotion styles. Did you have any luck doing so?

For example, I have this OnOffSwitch component which has some child elements:

const OnOffWrapper = styled.div`
  display: inline-block;

  ${props =>
    props.isChecked
      ? `
    ${OnOffTrack} {
      background-color: ${props.color};
      border: 1px solid ${props.color};
    }
    ${OnOffHandle} {
      transform: none;
      background-color: ${props.color};
    }
  `
      : `
    ${OnOffTrack} {
      background-color: transparent;
      border: 1px solid ${colors.silver};
    }
    ${OnOffHandle} {
      transform: translateX(-100%);
      background-color: ${colors.silver};
    }
  `}
`;
Enter fullscreen mode Exit fullscreen mode

These styles (anything below display: inline-block;) are being ignored now.

I've found this, but there's no mention of how to achieve this with Vite: github.com/emotion-js/emotion/issu...
Also this, which throws an error immediately ("Uncaught SyntaxError: missing ) after argument list"):
stackoverflow.com/questions/614352...

Collapse
 
elpddev profile image
Eyal Lapid

I got emotion to work only by specifying the babel plugin on vite react plugin config as per this article

Without it, the css was not working and was seend as [[Object, Object]] in the dom.

export default defineConfig({
  plugins: [
    react({
      jsxImportSource: "@emotion/react",
      babel: {
        plugins: ["@emotion/babel-plugin"],
      },
    }),
  ],
});
Enter fullscreen mode Exit fullscreen mode
Collapse
 
standelethan profile image
Ethan Standel

This wasn't working for me (though I'm using the react-ts template). The linked article below worked immediately.

dev.to/glocore/configure-emotion-w...

Collapse
 
cretezy profile image
Charles Crete

I got it working with as little as:

export default defineConfig({
 plugins: [
    react({
      jsxImportSource: "@emotion/react",
    }),
  ],
});
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ajitsinghkamal profile image
Ajit Singh Kamal • Edited

Yes, the post is quite old now. I wrote it when Vite was just released :)
Thanks for helping other wandering developers with your comment.