11

In my application I have a component that I want to style with the css prop from outside.

function Component({css}:{css?: React.CSSProperties}) {
  // some stuff going on here
  return (
    <div
      css={{
        color: blue,
        ...css
      }}
    >
       // some stuff going on here
    </div>
  )
}

The background is as follows: I want to use Component in different scenarios where I have to style the container based on the surrounding layout. E.g. flex, grid or in combination with some components I have to add different margins.

Now instead of introducing many props for all possible scenarios, I want to be able to style the container from outside the component.

E.g. usages of the component could be:

function Layout() {
  return (
    // some other components
    <Component css={{margin: 12}}/>
    // some other components
  )
}

or

import {css} from "@emotion/react"

const style = css({margin: 12})

function Layout() {
  return (
    // some other components
    <Component css={style}/>
    // some other components
  )
}

or

import {css} from "@emotion/react"

const style1 = css({margin: 12})
const style2 = css({color: 'red'})

function Layout() {
  return (
    // some other components
    <Component css={[style1, style2]}/>
    // some other components
  )
}

I have the following problems:

  1. If I use css as the prop name (as in the above example) the style is not applied. If I change the name of the prop to e.g. newCss it works as expected
  2. React.CSSProperties is not the right prop type to handle all the possibilities of emotions css prop.
  3. How can I merge the different css prop possibilities (object, list) with the css prop from Component?

2 Answers 2

15

In fact, we don't need to use the extra props. As Ben Laniado mentioned, the official documentation states

Any component or element that accepts a className prop can also use the css prop.

https://emotion.sh/docs/css-prop#use-the-css-prop

So what we need is accepting className and css as props and add className to the component. (We don't need css to the component but need it for types)

type ComponentProps = {
  css?: SerializedStyles;
  className?: string;
};
const Component: VFC<ComponentProps> = ({ className }) => {
  return (
    <div css={{ color: blue }} className={className}>
      hello world
    </div>
  );
};
export default function App() {
  return (
    <div className="App">
      <Component css={{ margin: 12 }} />
    </div>
  );
}

This is the full working example.
https://codesandbox.io/s/react-component-accepting-emotion-css-prop-wskbh?file=/src/App.tsx

Sign up to request clarification or add additional context in comments.

2 Comments

You don't actually have to implement the css prop in Component, you only have to implement the className prop.
@MartinOmacht thanks, you are right. I updated the examples.
1

The right way of achieving this functionality is modifying the component to accept extra props. This way the css prop passed into the component would be merged with the one within the component.

function Component({prop1, prop2, propN, ...props}) {
  // some stuff going on here
  return (
    <div
      css={{
        color: blue,
      }}
      {...props}
    >
       // some stuff going on here
    </div>
  )
}

Now you can use additional styles on your component and it will be rendered properly.

function Layout() {
  return (
    // some other components
    <Component css={{marginTop: "1em"}}/>
    // some other components
  )
}

The side effect of this solution that any additional prop would be passed directly to the HTML element inside the component that takes {...props}.

2 Comments

thanks! I am surprised the solution is that simple :)
Actually, if you want to be more accurate. You component will need to implement className and apply it where you want your CSS-IN-JS style. emotion.sh/docs/css-prop#use-the-css-prop

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.