Search code examples
htmlcssreactjsstyled-components

How do I style elements of a component using styled-components


I have a component like this:

// MyComponent.tsx
export function MyComponent(): React.ReactElement {
  return <Wrapper>
           <Text>
             hello there
           </Text>
           <AnotherText>
             bye bye
           </AnotherText> 
         </Wrapper>
} 

export const Wrapper = styled.div`
  color: #FEB240;
  background: #f5f5f5;
  padding-bottom: 5rem;
  padding-left: 7rem;
  padding-right: 7rem;
  gap: 2rem;
`;

export const Text = styled.span`
  width: 50%;
  cursor: pointer;
  color: rgba(28, 33, 120, 1);
`;

export const AnotherText = styled.span`
  color: red;
`;

I want to be able to style the wrapper. I tried to like this (from this answer Styling Nested Components in Styled-Components), but I don't see any change:

// AnotherPlace.tsx
const NewlyStyledMyComponent = styled(MyComponent)`
  ${Wrapper} {
    color: brown;
    background: magenta;
   }
`;

Solution

  • There are indeed 2 issues:

    1. To style a custom React component (even just so that its nested components can be styled), you always need to take a className prop and to apply it on one of your rendered elements, as explained in styled-components docs:

    The styled method works perfectly on all of your own or any third-party component, as long as they attach the passed className prop to a DOM element.

    1. To style nested components, the className of the parent element must be applied on a parent DOM element as well; that is why JohnLi's answer has to add an extra <div className={className}> around the <Wrapper>.

    But in your case, you could just style MyComponent and apply the className on the <Wrapper>:

    export function MyComponent({
      className
    }: {
      className?: string;
    }): React.ReactElement {
      return (
        // Apply className directly on the Wrapper
        <Wrapper className={className}>
          This text can be re-colored
          <Text>hello there can be re-colored if styling nested Text</Text>
          <AnotherText>bye bye</AnotherText>
        </Wrapper>
      );
    }
    
    const NewlyStyledMyComponent = styled(MyComponent)`
      /* Directly style MyComponent */
      color: brown;
      background: magenta;
    
      /* Styling of nested components */
      ${Text} {
        color: white;
      }
    `;
    

    Demo: https://codesandbox.io/s/vibrant-worker-05xmil?file=/src/App.tsx