What if you're working on a React based project and suddenly your design team says:
"Yo, we need to completely change the entire theme of the app due to blah and blah reasons..."
Maybe you're not convinced with their reasons or maybe you just need to do this for fun. Whatever the reason, it's quite annoying if youโre just using plain old CSS (even with variables) to apply the global or per-element styles.
What comes to the rescue is some method by which you can easily change the entire color, font, gradient, etc. values in one go, a place where all of these are defined in a central place so you donโt have to change things here and there.
What I'm talking about is creating your own theme with styled-components.
A quick note on styled-components ๐
styled-components is a library that allows you to write actual CSS code to style your components inside a JS file. This follows the CSS-in-JS concept which allows developers to style using tagged template literals giving extensive flexibility and more control.
All in all, a great merger of CSS and JS! Here are some of its features:
Automatic critical CSS: it keeps track of which components are rendered and injects their styles and nothing else, automatically.
No class name bugs: there are no duplication, overlap, or misspellings.
Easier deletion of CSS: if the component is unused and gets deleted, all its styles get deleted with it.
Simple dynamic styling: styling of a component based on its props without having to manually manage dozens of classes.
What we will be styling? ๐
This:
We will be theming out two buttons using styled-components. Notice that we have:
- Different default and hover colors.
- Different font styles.
Not this:
Create global styles! ๐
After you're done installing the library, head over to your index.js file. Here, all the theme data will go such as the colors, fonts, etc.
STEP 1๏ธโฃ : Create a theme
object
This will house all the theme objects we need. Currently, we are only changing the colors
and fonts
.
const theme = {
colors: {
primary: "#6200ee",
primaryVariant: "#ede6ff",
secondary: "#008073",
secondaryVariant: "#deffff"
},
fonts: {
material: "Roboto",
default: "Montserrat"
}
};
As we can see, there are four color options, one for each variant; primary and secondary. As for the font, we also need to include them in our index.html file via the <link>
method as follows:
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet" />
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;700&display=swap" rel="stylesheet" />
STEP 2๏ธโฃ : Use the ThemeProvider
component
Next, import the ThemeProvider
helper component from styled-components
. This is used to inject the theme into all styled-components in the component tree, via the Context API.
We need to wrap our top-level component i.e. <App />
with this. But for it to actually recognize the theme
object we wrote above, we need it to pass it on as:
<ThemeProvider theme={theme}>
<React.StrictMode>
<App />
</React.StrictMode>
</ThemeProvider>
Hence, now the render methods becomes:
ReactDOM.render(
<ThemeProvider theme={theme}>
<React.StrictMode>
<App />
</React.StrictMode>
</ThemeProvider>,
rootElement
);
STEP 3๏ธโฃ : Create the buttons and add the theme!
Before we hop into the buttons, did you see that the body color of the demo is not white but instead off-white? Well, here, the global style of the app was triggered.
Using the createGlobalStyle
helper function, we can change or reset the base styles of the entire application.
For this to happen, we need to add the <Global />
component just before the <App />
starts inside the App()
function.
Now we can add global styles by defining the usual styled-component:
const Global = createGlobalStyle`
body {
width: 50%;
padding: 10px;
background: #fffaeb;
}
`;
Okay, let's move to those two buttons. We can create two components; <PrimaryButton />
and <DefaultButton />
The usual styles (without colors and fonts) for the buttons are as follows:
.
.
.
width: 50%;
height: 50px;
cursor: pointer;
transition: all 200ms ease;
text-decoration: none;
outline: none;
border: none;
border-radius: 10px;
float: left;
.
.
.
To get the value from the theme
which is passed via the ThemeProvider
component, we will use our good old friend in React, i.e. props!
Start with the template literal syntax to pass on the props
parameter to our arrow function, this can now get the global theme object via props.theme
. Now we got the theme
object, so we can assign the values as follows:
background: ${(props) => props.theme.colors.primary};
color: ${(props) => props.theme.colors.primaryVariant};
We applied the colors, now what about the hover effect? styled-components makes it really easy to add pseudo-classes whether it's :hover
or :active
. Just invert the values of the background
and color
inside the :hover
object:
:hover {
background: ${(props) => props.theme.colors.primaryVariant};
color: ${(props) => props.theme.colors.primary};
}
The same method is applied to other objects inside our theme
such as for the different fonts:
.
.
.
font-family: '${(props) => props.theme.fonts.material}';
font-weight: 500;
.
.
And that's pretty much it! You have used a theme in styled-components. Of course, this is just the beginning, you can bring in the entire library of design assets and tokens with your theme to make it even more dynamic.
More resources ๐คฉ
Go ahead with theming when you read from these resources:
- Theming docs by styled-components
- How to use Themes in styled-components by @aromanarguello
- styled-theming repo by styled-components
Thanks for reading, I appreciate it! Have a good day. (โฟโโฟโโฟ)
When the going gets tough, the tough get going. ๐ช
โ Microsoft Developer UK (@msdevUK) November 6, 2020
Image source: https://t.co/f3Mij3xXQs#DevHumour #CodingMemes #Developer pic.twitter.com/bouXm7eVlx
Top comments (2)
Very helpful!
Thanks for reading! :)