Are you familiarized with React's Context API? From styled-components docs:

styled-components has full theming support by exporting a <ThemeProvider> wrapper component. This component provides a theme to all React components underneath itself via the context API.

Let's see how we could implement a ThemeProvider with styled-components.

1. First we need to create a Context to encapsulate our theming logic

We should also create a "custom hook" to ease access to our context throughout our app.

theme-context.jsx

import React from 'react'

export const ThemeContext = React.createContext({
  // our theme object
  theme: {},
  // our color modes ('dark' || 'light')
  colorMode: '',
  // a method to toggle our theme from `dark` to `light` and vice-versa
  setColorMode: () => null,
})

// export our custom hook for quick access to our context
export function useTheme() {
  return React.useContext(ThemeContext)
}
2. Now we need to extend styled-components native <ThemeProvider> to create our own ThemeProvider

Since we'll need access to our themes, I'll add two very contrived theme objects (for the sake of simplicity) as well.

theme-provider.jsx

import React from 'react'
import { ThemeProvider as StyledProvider } from 'styled-components'
import { ThemeContext } from './theme-context'

// our theme objects
const lightTheme = { colorMode: 'light', bg: '#fff', text: '#000' }
const darkTheme = { colorMode: 'dark', bg: '#000', text: '#fff' }

// our iterable theme "store"
const myThemes = [lightTheme, darkTheme]

// our default color mode
const defaultColorMode = 'light'

const ThemeProvider = ({ children, ...props }) => {
  // get fallback values from the parent ThemeProvider (if exists)
  const {
    theme: fallbackTheme,
    colorMode: fallbackColorMode,
  } = useTheme()

  // initialize our state
  const theme = props.theme ?? fallbackTheme
  const [colorMode, setColorMode] = React.useState(
    props.colorMode ?? fallbackColorMode ?? defaultColorMode,
  )

  // memoize the current theme
  const resolvedTheme = React.useMemo(() => {
    const theme = myThemes.find(t => t.colorMode === colorMode)
    if (theme) return theme
    return lightTheme
  }, [theme, myThemes, colorMode])

  // update our state if props change
  React.useEffect(() => {
    setColorMode(props.colorMode ?? fallbackColorMode ?? defaultColorMode)
  }, [props.colorMode, fallbackColorMode])

 return (
    <ThemeContext.Provider
      value={{
        theme: resolvedTheme,
        colorMode,
        setColorMode,
      }}
    >
      <StyledProvider theme={resolvedTheme}>{children}</StyledProvider>
    </ThemeContext.Provider>
  )
}

export default ThemeProvider
3. Our final step is wrapping up our main <App /> component within our ThemeProvider

app.jsx

import React from 'react'
import ThemeProvider from './theme-provider'

const App = () => {
  const [themeType, setThemeType] = React.useState('light')
  const switchThemes = () => {
    setThemeType(last => (last === 'dark' ? 'light' : 'dark'))
  }

  return (
    <ThemeProvider colorMode={themeType}>
      <MySwitch onClick={switchThemes} />
    </ThemeProvider>
  )
}

And that's it. We should now be able to toggle our theme by clicking on MySwitch. Hope that helps!

Let me know how it goes? Cheers

Answer from Moa on Stack Overflow
๐ŸŒ
styled-components
styled-components.com โ€บ docs โ€บ advanced
styled-components
styled-components has full theming support by exporting a <ThemeProvider> wrapper component. This component provides a theme to all React components underneath itself via the context API.
๐ŸŒ
DEV Community
dev.to โ€บ aromanarguello โ€บ how-to-use-themes-in-styled-components-49h
How to use Themes in styled-components - DEV Community
November 26, 2022 - First things first, import React from the react dependency, and then we import ThemeProvider from the styled-components file. Theme provider uses context to provide the properties to its descendants.
Discussions

Implement different themes using styled components
styled-components has full theming support by exporting a wrapper component. This component provides a theme to all React components underneath itself via the context API. More on stackoverflow.com
๐ŸŒ stackoverflow.com
Default theme for components without parent ThemeProvider
Problem: When you are using styled-components to create a component library that supports themes, the components require a ThemeProvider in the tree. This can be undesirable if the components are m... More on github.com
๐ŸŒ github.com
9
January 13, 2020
Using Styled-Components with a theme provider. How should I organize my colors?
Thereโ€™s a lot of ways to do this, Iโ€™ve often had more than the simple obiect you have there, with groups of arrays containing color steps. One thing to look into is a library called Style Dictionary made by Amazon that you can use to build design tokens to use in any number of formats. They have lots of examples on how to format your tokens for that system, and they get exported to flat, named tokens for you to use. More on reddit.com
๐ŸŒ r/reactjs
1
4
June 3, 2022
reactjs - Dynamic Theme in Styled Components - Stack Overflow
I'm using styled-components in my React app and wanting to use a dynamic theme. Some areas it will use my dark theme, some will use the light. Because the styled components have to be declared outs... More on stackoverflow.com
๐ŸŒ stackoverflow.com
๐ŸŒ
GitHub
github.com โ€บ styled-components โ€บ styled-theming
GitHub - styled-components/styled-theming: Create themes for your app using styled-components
import React from 'react'; import styled, {ThemeProvider} from 'styled-components'; import theme from 'styled-theming'; const boxBackgroundColor = theme('mode', { light: '#fff', dark: '#000', }); const Box = styled.div` background-color: ${boxBackgroundColor}; `; export default function App() { return ( <ThemeProvider theme={{ mode: 'light' }}> <Box> Hello World </Box> </ThemeProvider> ); }
Starred by 1.2K users
Forked by 25 users
Languages ย  JavaScript 97.6% | HTML 2.4% | JavaScript 97.6% | HTML 2.4%
Top answer
1 of 1
2

Are you familiarized with React's Context API? From styled-components docs:

styled-components has full theming support by exporting a <ThemeProvider> wrapper component. This component provides a theme to all React components underneath itself via the context API.

Let's see how we could implement a ThemeProvider with styled-components.

1. First we need to create a Context to encapsulate our theming logic

We should also create a "custom hook" to ease access to our context throughout our app.

theme-context.jsx

import React from 'react'

export const ThemeContext = React.createContext({
  // our theme object
  theme: {},
  // our color modes ('dark' || 'light')
  colorMode: '',
  // a method to toggle our theme from `dark` to `light` and vice-versa
  setColorMode: () => null,
})

// export our custom hook for quick access to our context
export function useTheme() {
  return React.useContext(ThemeContext)
}
2. Now we need to extend styled-components native <ThemeProvider> to create our own ThemeProvider

Since we'll need access to our themes, I'll add two very contrived theme objects (for the sake of simplicity) as well.

theme-provider.jsx

import React from 'react'
import { ThemeProvider as StyledProvider } from 'styled-components'
import { ThemeContext } from './theme-context'

// our theme objects
const lightTheme = { colorMode: 'light', bg: '#fff', text: '#000' }
const darkTheme = { colorMode: 'dark', bg: '#000', text: '#fff' }

// our iterable theme "store"
const myThemes = [lightTheme, darkTheme]

// our default color mode
const defaultColorMode = 'light'

const ThemeProvider = ({ children, ...props }) => {
  // get fallback values from the parent ThemeProvider (if exists)
  const {
    theme: fallbackTheme,
    colorMode: fallbackColorMode,
  } = useTheme()

  // initialize our state
  const theme = props.theme ?? fallbackTheme
  const [colorMode, setColorMode] = React.useState(
    props.colorMode ?? fallbackColorMode ?? defaultColorMode,
  )

  // memoize the current theme
  const resolvedTheme = React.useMemo(() => {
    const theme = myThemes.find(t => t.colorMode === colorMode)
    if (theme) return theme
    return lightTheme
  }, [theme, myThemes, colorMode])

  // update our state if props change
  React.useEffect(() => {
    setColorMode(props.colorMode ?? fallbackColorMode ?? defaultColorMode)
  }, [props.colorMode, fallbackColorMode])

 return (
    <ThemeContext.Provider
      value={{
        theme: resolvedTheme,
        colorMode,
        setColorMode,
      }}
    >
      <StyledProvider theme={resolvedTheme}>{children}</StyledProvider>
    </ThemeContext.Provider>
  )
}

export default ThemeProvider
3. Our final step is wrapping up our main <App /> component within our ThemeProvider

app.jsx

import React from 'react'
import ThemeProvider from './theme-provider'

const App = () => {
  const [themeType, setThemeType] = React.useState('light')
  const switchThemes = () => {
    setThemeType(last => (last === 'dark' ? 'light' : 'dark'))
  }

  return (
    <ThemeProvider colorMode={themeType}>
      <MySwitch onClick={switchThemes} />
    </ThemeProvider>
  )
}

And that's it. We should now be able to toggle our theme by clicking on MySwitch. Hope that helps!

Let me know how it goes? Cheers

๐ŸŒ
Theme-ui
theme-ui.com โ€บ guides โ€บ styled-components
Styled Components โ€“ Theme UI
Theme UI itself doesnโ€™t expose an API for styled components, but works seamlessly with the styled API from the @emotion/styled package. Components written with it should have access to the same theming context that Theme UI uses. Instead of using the ThemeProvider component from @emotion/react, import and use the Theme UI provider at your appโ€™s root level.
๐ŸŒ
LogRocket
blog.logrocket.com โ€บ home โ€บ build a react theme switcher app with styled-components
Build a React theme switcher app with styled-components - LogRocket Blog
June 4, 2024 - Full theming support: the ThemeProvider wrapper component allows us to pass the theme to all React components underneath it in the render tree ยท Efficiency: styled-components uses the React Context API which offers a Theme Context that we can ...
๐ŸŒ
egghead.io
egghead.io โ€บ lessons โ€บ react-theme-your-application-with-styled-components-and-themeprovider
Theme your application with styled-components and 'ThemeProvider' | egghead.io
[00:20] Let's define a theme object, and we'll have a primary property where we'll setup brand color. To make these theme properties available everywhere, we'll rap our root component inside the theme provider. Now, we can pass our theme object in a theme property, so we can access it in children style components.
Published ย  February 1, 2020
Find elsewhere
๐ŸŒ
CSS-Tricks
css-tricks.com โ€บ theming-and-theme-switching-with-react-and-styled-components
Theming and Theme Switching with React and styled-components | CSS-Tricks
June 15, 2022 - It provides out-of-the-box theming support using a wrapper component called, <ThemeProvider>. This component is responsible for providing the theme to all other React components that are wrapped within it.
๐ŸŒ
GitHub
github.com โ€บ styled-components โ€บ styled-components โ€บ issues โ€บ 2960
Default theme for components without parent ThemeProvider ยท Issue #2960 ยท styled-components/styled-components
January 13, 2020 - Create a library constructor module that re-exports the whole library scoped to a custom context: const {styled, ThemeProvider} = createStyledComponents(defaultTheme) Allow anything that subscribes to context to take a custom context reference as a prop, which could be set to a custom context that does have a default value. This is what Redux does for connected components.
Author ย  alexkrolick
๐ŸŒ
Reddit
reddit.com โ€บ r/reactjs โ€บ using styled-components with a theme provider. how should i organize my colors?
r/reactjs on Reddit: Using Styled-Components with a theme provider. How should I organize my colors?
June 3, 2022 -

I'm making a design system for our company using Styled Components. I can create a theme and use that theme for any component that needs to reuse padding, colors, etc.

export const Theme = (props) => (
  <ThemeProvider theme={{
    fontWeights: {
      bold: 700;
      normal: 400,
      light: 100
    },
    ...
  }}>{props.children}</ThemeProvider>
);

export const Button = styled.button(props => `
  font-weight: props.theme.fontWeight.normal,
  ...
`);

The problem I'm having is colors. I don't want to specify the same HTML color codes everywhere, so I want to have them in the theme. But how do I organize them?

If I try this solution, then when I find a new situation I need to amend the color object, and it grows out of control with duplicated values and inconsistent variable names:

theme = {
  colors: {
    success: {
      font: "#2dce89",
      disabledBackground: "#abebd0",
      glow: ...
      active: ...
      borderDisabled: ...
      ...
    }
  }
}

Design sites suggest using numbers. But if I have to style a button, how do I know which color weight to use? And where do greyed versions for disabled go? What about other variants?

success: {
  100: "#d5f5e7",
  200: "#abebd0",
  300: "#81e2b8",
  400: "#57d8a1",
  500: "#2dce89",
  600: "#24a56e",
  700: "#1b7c52",
  800: "#125237",
  900: "#09291b",
},

Is there a better way to organize my colors so it is easy to be consistent across multiple components without having an explosion of one-off variables or duplicated values?

๐ŸŒ
Pieces
pieces.app โ€บ home
Styling Components with React Themes
Pieces for Developers โ€“ Long-Term Memory Agent
Styled-components supports multiple themes for React apps; use ThemeProvider to provide the theme via a context API. Pieces is your AI long-term memory agent that captures live context from browsers to IDEs and tools, manages snippets, and supports multiple LLMs. This app has dramatically improved my workflow!
Rating: 5 โ€‹
๐ŸŒ
DEV Community
dev.to โ€บ boywithsilverwings โ€บ theming-with-styled-components-3ig2
Theming with Styled Components - DEV Community
March 4, 2020 - A theme can be accessed in a styled component with props.theme usage. The only consideration being that where this Button is rendered should be wrapped somewhere in it's parent with ThemeProvider that provides it's theme.
๐ŸŒ
Medium
medium.com โ€บ @akbar123jason โ€บ styling-in-react-with-styled-components-a-guide-to-implementing-themes-e5f6ae375371
Styling in React with Styled-Components: A Guide to Implementing Themes | by Akbarjason | Medium
September 21, 2023 - By using ThemeProvider, we pass the theme to our components. Now, the Button component can access the theme's properties for styling. This simplifies theme management and ensures a consistent look and feel across your application.
๐ŸŒ
egghead.io
egghead.io โ€บ lessons โ€บ react-create-and-use-a-theme-in-styled-components
Create and use a Theme in Styled Components | egghead.io
Sara Vieira: [0:01] Let's import ThemeProvider from styled-components, so import -- we import it like this because it's not the default export -- {ThemeProvider} from "styled-components".
๐ŸŒ
Emotion
emotion.sh โ€บ docs โ€บ theming
Emotion โ€“ Theming
A React hook that provides the current theme as its value. If the theme is updated, the child component will be re-rendered accordingly. import { ThemeProvider, useTheme } from '@emotion/react' ... Thanks goes to the styled-components team and their contributors who designed this API.
๐ŸŒ
Northflank
northflank.com โ€บ blog โ€บ adding-themes-to-a-react-app-using-styled-components
How (and Why) to Add Themes to your React App Using Styled-Components | Blog โ€” Northflank
January 25, 2022 - As well as our standard light & dark offerings, we provide a few themes that match with popular IDE colour schemes and seasonal designs, as well as letting users customise their own themes. styled-components is a JavaScript styling library.
Top answer
1 of 3
44

That's exactly what the ThemeProvider component is for!

Your styled components have access to a special theme prop when they interpolate a function:

const Button = styled.button`
  background: ${props => props.theme.primary};
`

This <Button /> component will now respond dynamically to a theme defined by a ThemeProvider. How do you define a theme? Pass any object to the theme prop of the ThemeProvider:

const theme = {
  primary: 'palevioletred',
};

<ThemeProvider theme={theme}>
  <Button>I'm now palevioletred!</Button>
</ThemeProvider>

We provide the theme to your styled components via context, meaning no matter how many components or DOM nodes are in between the component and the ThemeProvider it'll still work exactly the same:

const theme = {
  primary: 'palevioletred',
};

<ThemeProvider theme={theme}>
  <div>
    <SidebarContainer>
      <Sidebar>
        <Button>I'm still palevioletred!</Button>
      </Sidebar>
    </SidebarContainer>
  </div>
</ThemeProvider>

This means you can wrap your entire app in a single ThemeProvider, and all of your styled components will get that theme. You can swap that one property out dynamically to change between a light and a dark theme!

You can have as few or as many ThemeProviders in your app as you want. Most apps will only need one to wrap the entire app, but to have a part of your app be light themed and some other part dark themed you would just wrap them in two ThemeProviders that have different themes:

const darkTheme = {
  primary: 'black',
};

const lightTheme = {
  primary: 'white',
};

<div>
  <ThemeProvider theme={lightTheme}>
    <Main />
  </ThemeProvider>

  <ThemeProvider theme={darkTheme}>
    <Sidebar />
  </ThemeProvider>
</div>

Any styled component anywhere inside Main will now be light themed, and any styled component anywhere inside Sidebar will be dark themed. They adapt depending on which area of the application they are rendered in, and you don't have to do anything to make it happen!

I encourage you to check out our docs about theming, as styled-components was very much built with that in mind.

One of the big pain points of styles in JS before styled-components existed was that the previous libraries did encapsulation and colocation of styles very well, but none of them had proper theming support. If you want to learn more about other pain points we had with existing libraries I'd encourage you to watch my talk at ReactNL where I released styled-components. (note: styled-components' first appearance is at ~25 minutes in, don't be surprised!)

2 of 3
14

While this question was originally for having multiple themes running at the same time, I personally wanted to dynamically switch in runtime one single theme for the whole app.

Here's how I achieved it: (I'll be using TypeScript and hooks in here. For plain JavaScript just remove the types, as, and interface):

I have also included all the imports at the top of each block code just in case.

We define our theme.ts file

//theme.ts
import baseStyled, { ThemedStyledInterface } from 'styled-components';

export const lightTheme = {
  all: {
    borderRadius: '0.5rem',
  },
  main: {
    color: '#FAFAFA',
    textColor: '#212121',
    bodyColor: '#FFF',
  },
  secondary: {
    color: '#757575',
  },
};

// Force both themes to be consistent!
export const darkTheme: Theme = {
  // Make properties the same on both!
  all: { ...lightTheme.all },
  main: {
    color: '#212121',
    textColor: '#FAFAFA',
    bodyColor: '#424242',
  },
  secondary: {
    color: '#616161',
  },
};

export type Theme = typeof lightTheme;
export const styled = baseStyled as ThemedStyledInterface<Theme>;

Then in our main entry, in this case App.tsx we define the <ThemeProvider> before every component that's going to use the theme.

// app.tsx
import React, { memo, Suspense, lazy, useState } from 'react';
import { Router } from '@reach/router';

// The header component that switches the styles.
import Header from './components/header';
// Personal component
import { Loading } from './components';

import { ThemeProvider } from 'styled-components';

// Bring either the lightTheme, or darkTheme, whichever you want to make the default
import { lightTheme } from './components/styles/theme';

// Own code.
const Home = lazy(() => import('./views/home'));
const BestSeller = lazy(() => import('./views/best-seller'));

/**
 * Where the React APP main layout resides:
 */
function App() {
// Here we set the default theme of the app. In this case,
// we are setting the lightTheme. If you want the dark, import the `darkTheme` object.
  const [theme, setTheme] = useState(lightTheme);
  return (
    <Suspense fallback={<Loading />}>
      <ThemeProvider theme={theme}>
        <React.Fragment>
         {/* We pass the setTheme function (lift state up) to the Header */}
          <Header setTheme={setTheme} />
          <Router>
            <Home path="/" />
            <BestSeller path="/:listNameEncoded" />
          </Router>
        </React.Fragment>
      </ThemeProvider>
    </Suspense>
  );
}

export default memo(App);

And in header.tsx we pass the setTheme to the component (Lifting the state up):

// header.tsx
import React, { memo, useState } from 'react';
import styled, { ThemedStyledInterface } from 'styled-components';
import { Theme, lightTheme, darkTheme } from '../styles/theme';

// We have nice autocomplete functionality 
const Nav = styled.nav`
  background-color: ${props => props.theme.colors.primary};
`;

// We define the props that will receive the setTheme
type HeaderProps = {
  setTheme: React.Dispatch<React.SetStateAction<Theme>>;
};

function Header(props: 
  function setLightTheme() {
    props.setTheme(lightTheme);
  }

  function setDarkTheme() {
    props.setTheme(darkTheme);
  }
// We then set the light or dark theme according to what we want.
  return (
    <Nav>
      <h1>Book App</h1>
      <button onClick={setLightTheme}>Light </button>
      <button onClick={setDarkTheme}> Dark </button>
    </Nav>
  );
}

export default memo(Header);
Top answer
1 of 4
40

You can use the useTheme hook since v5.0:

import React, { useTheme } from 'styled-components';

export function MyComponent() {
  const theme = useTheme();

  return <p style={{ color: theme.color }}>Text</p>;
}

You can also use the withTheme higher order component that I contributed a long time ago since v1.2:

import { withTheme } from 'styled-components'

class MyComponent extends React.Component {
  render() {
    const { theme } = this.props

    console.log('Current theme: ', theme);
    // ...
  }
}

export default withTheme(MyComponent)



original response below (ignore this!)

While there is no official solution, I came up by now:

Create a Higher Order Component that will be responsable to get the current theme and pass as a prop to a component:

import React from 'react';
import { CHANNEL } from 'styled-components/lib/models/ThemeProvider';

export default Component => class extends React.Component {
  static contextTypes = {
    [CHANNEL]: React.PropTypes.func,
  };

  state = {
    theme: undefined,
  };

  componentWillMount() {
    const subscribe = this.context[CHANNEL];
    this.unsubscribe = subscribe(theme => {
      this.setState({ theme })
    });
  }

  componentWillUnmount() {
    if (typeof this.unsubscribe === 'function') this.unsubscribe();
  }

  render() {
    const { theme } = this.state;

    return <Component theme={theme} {...this.props} />
  }
}

Then, call it on the component you need to access the theme:

import Themable from './Themable.js'
  
const Component = ({ theme }) => <Card color={theme.color} />

export default Themable(Component);
2 of 4
17

You can use useTheme hook

import { useTheme } from 'styled-components';

const ExampleComponent = () => {
  const theme = useTheme();

  return (
    <View>
       <Card aCustomColorProperty={theme.color.sampleColor} />
    </View>
  );
};
๐ŸŒ
Medium
rossbulat.medium.com โ€บ creating-themes-in-react-with-styled-components-6fce744b4e54
Theming in React with Styled Components | by Ross Bulat | Medium
June 16, 2019 - This is the beauty of using the package; defining styles where they are used as opposed to importing a stylesheet that a multitude of components may be using, decreasing the complexity of maintaining styles. Within <ThemeProvider /> we provide a value for the mode theme.