Published on

How to Style Nested Components in Styled-Components

Authors
  • Name
    Ripal & Zalak
    Twitter

How to Style Nested Components in Styled-Components

When working with Styled Components in React, a common challenge arises when trying to override the styles of nested components without directly importing them. This guide explores different methods to effectively style nested components inside a parent component.

Problem Statement

Consider a Dropdown component structured as follows:

import styled from 'styled-components'

const Dropdown = (
  <DropdownBase>
    <Trigger>{title}</Trigger>
    <Submenu>{children}</Submenu>
  </DropdownBase>
)

const DropdownBase = styled.div`
  /* Default Styles */
`

const Trigger = styled.a`
  /* Default Styles */
`

const Submenu = styled.div`
  /* Default Styles */
`

If you import only Dropdown, how do you override DropdownBase, Trigger, and Submenu?

Solution 1: Export Nested Components

One approach is to export nested components and style them individually.

Step 1: Modify Export Structure

export { Dropdown, DropdownBase, Trigger, Submenu }

Step 2: Override Styles

import { Dropdown, DropdownBase, Trigger, Submenu } from '../path/to/dropdown'
import styled from 'styled-components'

const StyledDropdown = styled(Dropdown)`
  ${DropdownBase} {
    background-color: lightgray;
  }
  ${Trigger} {
    color: blue;
  }
  ${Submenu} {
    border: 1px solid black;
  }
`

Solution 2: Using Dot Notation for Nested Components

Another approach is attaching nested components to the main component:

Dropdown.Base = DropdownBase
Dropdown.Trigger = Trigger
Dropdown.Submenu = Submenu

Now, you can style it like this:

import { Dropdown } from '../path/to/dropdown'
import styled from 'styled-components'

const StyledDropdown = styled(Dropdown)`
  ${Dropdown.Base} {
    background-color: lightblue;
  }
  ${Dropdown.Trigger} {
    font-weight: bold;
  }
  ${Dropdown.Submenu} {
    padding: 10px;
  }
`

Solution 3: Using Class Names

You can assign custom class names and use .attrs to style them:

const StyledDropdown = styled(Dropdown).attrs({
  dropdownBaseClassName: 'dropdown-base',
  triggerClassName: 'trigger',
  submenuClassName: 'submenu',
})`
  .dropdown-base {
    background-color: pink;
  }
  .trigger {
    color: green;
  }
  .submenu {
    border-radius: 8px;
  }
`

Solution 4: Using Theme Provider

If you want a flexible and dynamic approach, using themes is a great option:

import { ThemeProvider } from 'styled-components'

const defaultTheme = { color: 'black' }
const customTheme = { color: 'red' }

const StyledComponent = () => (
  <ThemeProvider theme={customTheme}>
    <Dropdown>Your Custom Dropdown</Dropdown>
  </ThemeProvider>
)

Which Solution Should You Use?

SolutionProsCons
Export ComponentsSimple, direct, and modularRequires additional exports
Dot NotationKeeps code clean and autocompletes in IDESlightly unconventional
Class NamesWorks well with global stylesRequires extra attributes
Theme ProviderDynamic styling with themesMay be overkill for small changes

FAQs

1. Can I use styled-components with TypeScript?

Yes, you can use styled-components with TypeScript by defining prop types properly.

2. What happens if I try to style a nested component without exporting it?

It won’t work because styled-components does not have access to non-exported components.

3. How do I debug styling issues with styled-components?

Use React DevTools and Styled Components’ class names to inspect applied styles.