emotion-js / emotion

👩‍🎤 CSS-in-JS library designed for high performance style composition
https://emotion.sh/
MIT License
17.43k stars 1.11k forks source link

css prop not adding styles emotion 10 nextjs #1237

Closed orpheus closed 4 years ago

orpheus commented 5 years ago

Can't seem to get emotion to work following simple examples from docs.

I cloned the nextjs/with-emotion repo to start

And then I added:

css={css`
    background-color: red;
`}

to the first div under the <Head>

(looks like)

<div css={css`
  background-color: red;
`}>

Just following the doc example from here

But when I inspect in the browser the styles don't get applied to the div and the dom node looks like:

<div css="[object Object]">...</div>

A stringified object...

I also try following the object syntax example: <div css={{ color: 'hotpink' }}>

doing: <div css:{{backgroundColor: 'red'}} />...<div> and the same thing happened.

What am I missing?

package.json

{
  "name": "emotion-test",
  "version": "1.0.0",
  "description": "testing-emotion",
  "main": "index.js",
  "author": "ohryan",
  "license": "MIT",
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "@emotion/core": "^10.0.7",
    "@emotion/styled": "^10.0.7",
    "next": "^8.0.1",
    "react": "^16.8.2",
    "react-dom": "^16.8.2"
  },
  "devDependencies": {
    "babel-plugin-emotion": "^10.0.7"
  }
}

.babelrc

{
  "presets": ["next/babel"],
  "plugins": ["emotion"]
}
orpheus commented 5 years ago

So I got a basic css`` template literal style to work by adding:

"@emotion/babel-preset-css-prop" to my .babelrc presets following this

But now I'm confused because in this documentation

It says that css`` and css(...) are built in natively. So why do I need to add babel-preset-css-prop and why is babel-plugin-emotion and plugins": ["emotion"] not enough?

baba43 commented 5 years ago

Same question. I followed the guide to integrate emotion to gatsby and get the same result.

JenniferMcIntyre-xyz commented 5 years ago

Anyone able to solve this? I'm having the same problem when working with storybook.

barrymay commented 5 years ago

Hi - I've been using emotion 10 with nextjs with minimal issues (was using 8, recently updated to nextjs 9 as well)

babel-plugin-emotion definitely helps avoid console errors, but @emotion/babel-preset-css-prop has not been necessary for me.

If you're still having issues and you want to post a link to a full code sample, I'm happy to take a look.

dmtrKovalenko commented 5 years ago

You must use babel.config.js instead of .babelrc or .babelrc.js

barrymay commented 5 years ago

Strangely, it worked fine for me with .babelrc - babel.config.js is great if you want more configurability.

tylergraf commented 5 years ago

I also had to use babel.config.js. Thanks for your help everyone.

noliiva commented 5 years ago

Whatever I try, I run in the same problem. Including change .babelrc by babel.config.js. It works well on a previous project with @emotion/core v10.0.10 and @emotion/babel-preset-css-prop v10.0.9, but not on a new project with both libs on v10.0.14. :(

Edit: My bad... I just forgot that the previous project was ejected from Create React App and the new wasn't. So, obviously the .babelrc was not apply.

dsbrianwebster commented 5 years ago

@dmtrKovalenko or @tylergraf could you paste an example? I'm currently using babel.config.js with the config below, but css prop is still not working...

module.exports = function(api) {
  api.cache(true)

  const plugins = ["emotion"]
  const presets = ["next/babel"]

  return { plugins, presets }
}
dsbrianwebster commented 5 years ago

@noliiva yup. I can confirm it doesn't matter if one uses .babelrc or babel.config.js the key is @emotion/babel-preset-css-prop

So either of the below samples will work. Personally going to stick with .bablerc since our particular config is static.

babel.config.js

module.exports = function(api) {
  api.cache(true)

  const plugins = ["emotion"]
  const presets = ["next/babel", "@emotion/babel-preset-css-prop"]

  return { plugins, presets }
}

.bablerc

{
  "presets": [
    "next/babel",
    "@emotion/babel-preset-css-prop"
  ],
  "plugins": [
    ["emotion"]
  ]
}
barrymay commented 5 years ago

@dsbrianwebster I didn't need @emotion/babel-preset-css-prop either in mine and it worked, just

{
  "presets": ["next/babel"],
  "plugins": ["emotion"]
}

As you said, I'd like to see a problem scenario - maybe it's getting overwritten by create-react-app's eject as @nolliva saw

johot commented 5 years ago

I also had to use "@emotion/babel-preset-css-prop" to get this working.

adam-beck commented 5 years ago

Here is a CodeSanbox of it not working

If you change the .babelrc to

{
  "presets": [
    "next/babel",
    "@emotion/babel-preset-css-prop"
  ],
  "plugins": [
    [
      "emotion"
    ]
  ]
}

It will work. Although, I don't think this should be necessary according to the docs as css is supported natively.

Emiliano-Bucci commented 4 years ago

Hi to all! I'm facing some issues during jest-tests using Next.js:

This is my config inside babel.config.js:

module.exports = api => {
  api.cache(true);

  const presets = [
    "next/babel",
    [
      "@emotion/babel-preset-css-prop",
      {
        autoLabel: process.env.NODE_ENV !== "production",
        labelFormat: "[dirname]-[local]"
      }
    ]
  ];

  return {
    presets
  };
};

Next is builded correctly and styles are applied correctly, but i have this strange issue with snapshots:

css="You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."

My package.json:

{
  "name": "create-next-example-app",
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start",
    "test": "NODE_ENV=test jest --watch",
    "test:coverage": "NODE_ENV=test jest --passWithNoTests --detectOpenHandles --coverage && open ./coverage/lcov-report/index.html",
    "test:pre-push": "NODE_ENV=test jest --passWithNoTests --detectOpenHandles --coverage --watchAll=false && open ./coverage/lcov-report/index.html",
    "lint": "eslint --fix --config .eslintrc.js 'src/**/*.{ts,tsx,js}'",
    "lint:prepush": "eslint --fix --config .eslintrc.prepush.js 'src/**/*.{ts,tsx,js}'",
    "lint:precommit": "eslint --fix --config .eslintrc.precommit.js 'src/**/*.{ts,tsx,js}'",
  },
  "dependencies": {
    "@apollo/react-hooks": "^3.1.3",
    "@apollo/react-ssr": "^3.1.3",
    "@apollo/react-testing": "^3.1.3",
    "@artsy/detect-responsive-traits": "0.0.5",
    "@artsy/fresnel": "^1.0.7",
    "@emotion/babel-preset-css-prop": "^10.0.23",
    "apollo": "^2.21.0",
    "apollo-cache-inmemory": "^1.6.3",
    "apollo-client": "^2.6.4",
    "apollo-link": "^1.2.13",
    "apollo-link-batch-http": "^1.2.13",
    "apollo-link-rest": "^0.7.3",
    "axios": "^0.19.0",
    "firebase": "^7.2.3",
    "firebase-admin": "^8.7.0",
    "focus-trap-react": "^6.0.0",
    "graphql": "^14.5.8",
    "graphql-anywhere": "^4.2.4",
    "graphql-tag": "^2.10.1",
    "isomorphic-fetch": "^2.2.1",
    "js-cookie": "^2.2.1",
    "next": "^9.1.2",
    "next-cookies": "^1.1.3",
    "next-seo": "^2.2.1",
    "next-with-apollo": "^4.3.0",
    "nodemailer": "^6.3.1",
    "now": "^16.4.4",
    "password-validator": "^5.0.2",
    "qs": "^6.9.0",
    "react": "^16.11.0",
    "react-apollo": "^3.1.3",
    "react-dom": "^16.11.0",
    "validator": "^12.0.0"
  },
  "devDependencies": {
    "@emotion/core": "^10.0.22",
    "@emotion/styled": "^10.0.23",
    "@testing-library/jest-dom": "^4.2.3",
    "@testing-library/react": "^9.3.1",
    "@types/isomorphic-fetch": "0.0.35",
    "@types/js-cookie": "^2.2.4",
    "@types/node": "^12.12.5",
    "@types/nodemailer": "^6.2.2",
    "@types/react": "^16.9.11",
    "@types/svg-sprite-loader": "^3.9.1",
    "@types/validator": "^10.11.3",
    "@typescript-eslint/eslint-plugin": "^2.6.0",
    "@typescript-eslint/parser": "^2.6.0",
    "eslint": "^6.6.0",
    "eslint-config-prettier": "^6.5.0",
    "eslint-plugin-prettier": "^3.1.1",
    "eslint-plugin-react": "^7.16.0",
    "eslint-plugin-react-hooks": "^2.2.0",
    "firebase-mock": "^2.2.10",
    "husky": "^3.0.9",
    "imagemin-svgo": "^7.0.0",
    "jest": "^24.9.0",
    "jest-emotion": "^10.0.17",
    "lint-staged": "^9.4.2",
    "next-compose-plugins": "^2.2.0",
    "next-optimized-images": "^2.5.4",
    "prettier": "^1.18.2",
    "svg-sprite-loader": "^4.1.3",
    "ts-jest": "^24.1.0",
    "typescript": "^3.6.4"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "pre-push": "npm run lint && npm run test:pre-push"
    }
  },
  "lint-staged": {
    "**/*.{ts,tsx}": [
      "prettier --write",
      "npm run lint:precommit",
      "git add"
    ]
  }
}

It seems that the only way to make it work is adding the pragma, which it doesn't make any sense since i'm using babel plugin.

Any clues on this? Thanks! :)

Andarist commented 4 years ago

@Emiliano-Bucci this should only happen if you pass css output to className props (instead of to css prop). Could you prepare a runnable repro case? Hard to be sure without investigating the code.

Emiliano-Bucci commented 4 years ago

@Andarist Yes, i've already prepared :) It's a very simple one, but it replicates in a very basic way the repo in which i'm working on (this was a sort of boilerplate project) -> https://github.com/Emiliano-Bucci/emotion-css-issue

It's a Next js project; i've created a index page, and added a <div /> with basic styles, and then i 've created a simple snapshot test src/test.test.tsx and as you can see in the snapshot, i'm getting that warning message

Andarist commented 4 years ago

From ts-jest docs:

ts-jest by default does NOT use Babel. But you may want to use it, especially if your code rely on Babel plugins to make some transformations. ts-jest can call the BabelJest processor once TypeScript has transformed the source into JavaScript.

This happens because you transpile JSX with TS first so Babel doesn't ever see JSX in a file and doesn't handle it with @emotion/babel-preset-css-prop.

If you would just use jsx pragma directly everything would work as TS would recognize it and just use it.

Emiliano-Bucci commented 4 years ago

@Andarist That's correct! But in the docs it also says that it can be configured in order to make ts-jest to pick a custom babel config, which is what i'm doing (a babel.config.js) but it seems that it isn't working as expected

Andarist commented 4 years ago

As mentioned in the quoted docs - custom babel config can be used together with ts-jest, it's only that Babel runs AFTER TS transpiles your code and not the other way around. So that's why this is not working "as expected".

Andarist commented 4 years ago

Other than that the issue here seems to be about configuring babel correctly - number of solutions have been described etc. Most likely the OP's problem has been solved already - so I'm going to close this issue.

If any of you still have any problems with emotion then please just open a new issue with a runnable repro case and a proper description. Hope you understand.

michaeljaltamirano commented 4 years ago

Anyone able to solve this? I'm having the same problem when working with storybook.

For what it's worth I was encountering this issue when I had incompatible versions of @emotion installed (in my case, older versions of direct dependencies, and, when paired with @storybook/react@5.2.8, caused this issue).

reverse-eng commented 4 years ago

Just wanted to note I had this issue and adding /* @jsx jsx / import { jsx } from '@emotion/core';

fixed the error for me.

MujunZ commented 4 years ago

Just wanted to note I had this issue and adding /* @jsx jsx / import { jsx } from '@emotion/core';

fixed the error for me.

It solved my problems too. Just to clarify, you have to add /** @jsx jsx */; on top of the entire file.

jspears commented 4 years ago

I fixed it by adding


["babel-plugin-jsx-pragmatic", {
            "module": "@emotion/core",
            "export": "jsx",
            "import": "jsx"
 }],
["@babel/plugin-transform-react-jsx", { "pragma": "jsx"}]

to my babel configuration. That way I don't need to add the import stuff.

Just wanted to note I had this issue and adding /* @jsx jsx / import { jsx } from '@emotion/core'; fixed the error for me.

It solved my problems too. Just to clarify, you have to add /** @jsx jsx */; on top of the entire file.

boycce commented 4 years ago

How are you guys linking your source-mapped CSS in Chrome Devtools? Source-maps don't seem to link to the filesystem out of the box (notice there is no green circle next to home.jsx)

I have opened an issue here which will help.

image

tommulkins commented 4 years ago

Here's what I had to do in my React project using @emotion/core and @emotion/babel-preset-css-prop:

babel.config.json Add "@emotion/babel-preset-css-prop" to presets array

In any file using Emotion Add /**@jsx jsx */ at line 1 import { css, jsx } from "@emotion/core"

Then you can pass css prop to element being styled, i.e.

<header
    css={css`
      background-color: #333;
      padding: 15px;
    `}
  >
Andarist commented 4 years ago

When using @emotion/babel-preset-css-prop you shouldn't have to use jsx pragma.

tommulkins commented 4 years ago

When using @emotion/babel-preset-css-prop you shouldn't have to use jsx pragma.

I didn't think so either but when I don't I get the following rendered as a css property:

css="You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."

I figured I had to do that after seeing this example https://emotion.sh/docs/install

Andarist commented 4 years ago

If you share the repro case for your issue I could take a look. I suspect that your babel config was not loaded correctly and thus @emotion/babel-preset-css-prop was not used at all.

tommulkins commented 4 years ago

If you share the repro case for your issue I could take a look. I suspect that your babel config was not loaded correctly and thus @emotion/babel-preset-css-prop was not used at all.

Thank you for that! 🙏

My repo is at https://github.com/tommulkins/introtoreact in the exercises branch. The babel config is pretty straightforward but maybe there's something missing I'm not aware of.

The component using emotion is located in src/NavBar.js

Andarist commented 4 years ago

@tommulkins It seems that Parcel doesn't respect babel.config.json nor babel.config.js. You can only use .babelrc, .babelrc.js or "babel" key in package.json to configure Babel with Parcel v1.

tommulkins commented 4 years ago

@tommulkins It seems that Parcel doesn't respect babel.config.json nor babel.config.js. You can only use .babelrc, .babelrc.js or "babel" key in package.json to configure Babel with Parcel v1.

Thank you @Andarist !

nathan5x commented 4 years ago

Following @MujunZ's solution works for me! 👍

Just wanted to note I had this issue and adding /* @jsx jsx / import { jsx } from '@emotion/core';

fixed the error for me.

leohxj commented 3 years ago

If you include the plugin @babel/plugin-transform-react-inline-elements in your .babelrc your styles will not be applied. The plugin is not compatible with the css prop.

Khraken commented 3 years ago

Here is a working config with emotion and Next.js

npm install @emotion/react @emotion/styled && npm i --save-dev @emotion/babel-plugin or yarn add @emotion/react @emotion/styled && yarn add -D @emotion/babel-plugin

.babelrc

{ "presets": [ [ "next/babel", { "preset-react": { "runtime": "automatic", "importSource": "@emotion/react" } } ] ], "plugins": ["@emotion/babel-plugin"] }

package.json

"dependencies": { "next": "10.1.3", "react": "17.0.2", "react-dom": "17.0.2" "@emotion/react": "^11.1.5", "@emotion/styled": "^11.3.0", }, "devDependencies": { "@emotion/babel-plugin": "^11.3.0" }