Emotion: Specificity with css prop

Created on 17 Sep 2017  路  3Comments  路  Source: emotion-js/emotion

  • emotion version: 7.3.2
  • react version: 15.6.1

It appears the styled api has some issues working with gatsby-plugin-emotion.

Related issue: https://github.com/gatsbyjs/gatsby/pull/2129#issuecomment-329847635

Relevant code.

import styled from "react-emotion";
import { css } from "emotion";

const GreenDiv = () => (
  <div css={`background-color: green`}>{props.children}</div>
);

const RedDiv = styled(GreenDiv)`background-color: red;`;

What you did:

Used the above code to try style a div via css, and add further styles through the style API.

What happened:

Only the styles applied via css were applied. The styles applied via style() were ignored.

Reproduction:

Create a gatsby project, add the gatsby-plugin-emotion plugin. Try style a div using the css api, then style it further using the styled api.

Problem description:

The style api does not seem to apply styles when used with gatsby.

Suggested solution:

I believe the gatsby-plugin-emotion is not using react-emotion correctly (I believe this package was added since the writing of the plugin), so may need to be updated.

Most helpful comment

This is fixed in emotion 8 as long as the className is passed to the component

import styled from "react-emotion";
import { css } from "emotion";

const GreenDiv = (props) => (
  <div css={`background-color: green`} className={props.className}>{props.children}</div>
);

const RedDiv = styled(GreenDiv)`background-color: red;`;

Here's a CodeSandbox which demonstrates what the babel plugin turns the css prop with a className on the element into.

I'm gonna close this, if this still doesn't work for you on emotion 8 please reopen the issue.

All 3 comments

I'm pretty sure this isn't related to gatsby at all. gatsby-plugin-emotion itself doesn't need to use react-emotion at all. gatsby-plugin-emotion just does SSR, add the babel plugin and rehydrates after SSR.

There are still two problems here though.

Firstly, in GreenDiv you're not passing the className to the div so there is no way the styles for that div can be changed outside of GreenDiv.

Secondly, the reason this doesn't work currently is because of specificity, the RedDiv is rendered first so the styles are inserted first and then styles for GreenDiv are inserted so they have a higher specificity. This is problem that we need to solve at the emotion level by merging the styles.

You're absolutely correct, I'd tested this with a slightly different test case outside of Gatsby which worked which lead me to believe the issue was using emotion with Gatsby.

So it seems the workaround for the moment would be this:
``` const RedRule = cssbackground-color: red;`;
const RedDiv = props =>

;

const BlueRule = css composes: ${RedRule}; background-color: blue; ;
const BlueDiv = props =>

;
```

This is fixed in emotion 8 as long as the className is passed to the component

import styled from "react-emotion";
import { css } from "emotion";

const GreenDiv = (props) => (
  <div css={`background-color: green`} className={props.className}>{props.children}</div>
);

const RedDiv = styled(GreenDiv)`background-color: red;`;

Here's a CodeSandbox which demonstrates what the babel plugin turns the css prop with a className on the element into.

I'm gonna close this, if this still doesn't work for you on emotion 8 please reopen the issue.

Was this page helpful?
0 / 5 - 0 ratings