71

trying to port some code from jss to styled-components, jss code looks something like:

//...
const styles = {
  myStyles: {
    color: 'green'
  }
}

const {classes} = jss.createStyleSheet(styles).attach()

export default function(props) {
  return (
     <div>
       <Widget1 className={classes.myStyles}/>
       <Widget2 className={classes.myStyles}/>
     </div>
  )
}

my question is what would be the idiomatic way to accomplish this sharing of the same styles across multiple components?

Sagiv b.g
  • 30,379
  • 9
  • 68
  • 99
tony_k
  • 1,983
  • 2
  • 20
  • 27

3 Answers3

157

You can either share actual CSS strings or share styled-components components:

  • Share CSS strings:
import {css} from 'styled-components'
const sharedStyle = css`
  color: green
`

// then later

const ComponentOne = styled.div`
  ${sharedStyle}
  /* some non-shared styles */
`
const ComponentTwo = styled.div`
  ${sharedStyle}
  /* some non-shared styles */
`
  • Share actual styled-components:
const Shared = styled.div`
  color: green;
`

// ... then later

const ComponentOne = styled(Shared)`
  /* some non-shared styles */
`
const ComponentTwo = styled(Shared)`
  /* some non-shared styles */
`

Update: Based on questions in the comments, I created an example to show that passing props to styled-components's css function works the same way as passing props to the components themselves: https://codesandbox.io/s/2488xq91qj?fontsize=14. The official recommendation from styled-components is to always wrap strings you will pass to styled-components in the css tag function. In this example, the Test component receives it background and foreground colors through passed-in props embedded in the cssString variable created by invoking the css function.

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
Huy Nguyen
  • 2,840
  • 1
  • 14
  • 18
  • thanks @huy, that's kind of what i could gather, but just wanted to verify from someone with more experience. seems to be a little more verbose than a solution that hands out generated classes in that it requires extra lines to define styled components, but i guess they don't call it styled *components* for nuthin :) – tony_k Apr 03 '18 at 13:20
  • this is great, but do you know how to pass props to `css`? – Paul Fitzgerald Feb 27 '19 at 17:47
  • 1
    @PaulFitzgerald you can create a function that accepts props and returns the `css`. styled-components will pass them automatically – Sagiv b.g Mar 04 '19 at 13:23
  • @PaulFitzgerald I create an example to show that passing props to `styled-components`'s `css` function works the same way as passing props to the components themselves: https://codesandbox.io/s/2488xq91qj?fontsize=14. In the example, the `Test` component receives it background and foreground colors through passed-in props embedded in the `cssString` variable created by invoking the `css` function. – Huy Nguyen Mar 07 '19 at 16:05
  • 2
    You can also create a new component with the same css rules as another component but changing the html tag simply by using [withComponent](https://www.styled-components.com/docs/api#withcomponent). Quick example: `const PrimaryLink = PrimaryButton.withComponent('a');` – Alex Salomon Oct 16 '19 at 19:16
  • What about the concept of a "baseStyle" and an extended variant? For example, I want a button to have a gray / super basic style, and then have a primary variant in dark blue. – httpete Mar 25 '21 at 01:17
33

In addition to the posted answer, you can also create a function that accepts props / theme and returns the css``.

styled-components will check the type of the value provided eg: ${shared} and if its a function it will invoke it with the relevant props / theme.

import styled, {css} from 'styled-components';

const shared = ({theme, myProp}) => css`
  color: ${theme.color};
`

/* ------------   */

const Component1 = styled.div`
  ${shared};
  /* more styles ... */
`
const Component2 = styled.div`
  ${shared};
  /* more styles ... */
`
David Harkness
  • 35,992
  • 10
  • 112
  • 134
Sagiv b.g
  • 30,379
  • 9
  • 68
  • 99
  • its unnecessary to create this extra function, `shared` could just be its css. types are even propagated through although not using a wrapping function or explicitly setting the types on the components under – Gabriel Petersson Jul 15 '22 at 09:54
3

In addition to the 2 answers above, you can also share style between tags as such:

const MyText = styled.div`
  color: orange;
`

const MyLink = MyText.withComponent("a")
Gabriel Petersson
  • 8,434
  • 4
  • 32
  • 41