Skip to content
Advertisement

Responsive Props In ReactJS Styled Components

I have an idea of how to do responsive props using Styled Components, but I can’t figure out how to implement it. My idea goes something like this:

<MyComponent 
  sm={{color: 'red', bg: 'green', }}
  md={{color: 'yellow', bg: 'orange' }}

/>

In this case color and bg are just props that I set in my styled component:

The idea is that I have a top-level prop that is for a particular media query and that within that I have an object full of props that whose values that are props that I want to set at that media query.

Now, I know how to do a check for the props of color and bg — i.e., like this:

const MyComponent = styled.div`
  ${props => props.color && `color: ${props.color};`}
  ${props => props.bg && `background-color: ${props.bg};`}
`

But is it possible for me to do something like this:

const MyComponent = styled.div`
  ${props => props.sm &&  MEDIA_QUERY_WITH_OBJECT_WITH_COLOR_AND_BG_PROPS}
  ${props => props.md && MEDIA_QUERY_WITH_OBJECT_WITH_COLOR_AND_BG_PROPS};`}
`

Or is there some way to accomplish to do this?

Advertisement

Answer

You can keep using your component just as you have it already:

<MyComponent 
  sm={{color: 'red', bg: 'green', }}
  md={{color: 'yellow', bg: 'orange' }}
/>

and defined it like this:

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

const MyComponent = styled.div`
  ${props => props.sm && css`
    color: ${props.sm.color};
    background-color: ${props.sm.bg};
  `}
  ${props => props.md && css`
    color: ${props.md.color};
    background-color: ${props.md.bg};
  `}
`;

The css method from Styled Components could actually be omitted here, but you should always use it when you create CSS strings like this, as the method will make sure all the interpolations work like in any other styled component. Plus, without it you probably don’t get syntax highlighting in your editor.

Since there’s some repeated logic here (converting the CSS object to a CSS string), we can extract that behavior to a separate function:

const objectToCss = (style) => style && css`
  color: ${style.color};
  background-color: ${style.bg};
`;

const MyComponent = styled.div`
  ${props => objectToCSS(props.sm)}
  ${props => objectToCSS(props.md)}
`;

And this final one is just my personal taste, I like to just get the props once at the top of the styled component instead of doing it every time:

const MyComponent = styled.div(({ sm, md }) => css`
  position: absolute;
  ${objectToCSS(sm)}
  ${objectToCSS(md)}
  border-width: 1px;
`);

(I added some extra CSS lines just as an example in case it isn’t clear that this is still a normal Styled Components string)

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement