React Styled Components Folder Structure Best Practices for Scalable Application

7 min read

Styled Components are an excellent way to write reusable and easily manageable CSS-in-JS code. If you’ve been following my posts here, you might have noticed styled components quite often. In this article, I will share how I personally like to organize styled components in Reactjs projects so that you can use them in your web apps and personalize them according to your aesthetics.

What should be the Folder Structure of styled components?

Maintaining proper folder structure is important for a project’s scalability, as well as for your own personal convenience and organization. A poor folder structure can make management difficult. It also happens that we don’t take structuring seriously in the start while it's apparently easier to manage, but once the project starts growing and more is added to it, organization and management start to become a pain and we regret not having taken care of the basics early on.

The most common and basic “best practice” for folder structuring in Reactjs or gatsbyjs projects is creating the src folder at the root in React. For styled components, we can create a styles folder inside the src folder. All styles are then kept in the styles folder. In my case, it has four main files:

folder structure styled components

Styled Components File Structure

  1. Theme.js
  2. Global.js
  3. Breakpoints.js
  4. Fonts.module.css

Let us discuss them one by one.

1. Theming in styled components

While working with styled-components I have noticed theming is a lot easier in styled components. You just need to create a theme object and define all your colors and other configs there like fonts, padding, margins, etc, and use them wherever you want them in your app.

export const theme = {
colors: {
primary: '#FAFAFA',
secondary: '#FFC80A',
tertiary: '#303030',
background: '#ffffff',
text: '#000000',
primaryTextColor: '#594F43',
secondaryTextColor: '#777777',
inputPlaceholder: '#C7C7C7',
darkGrayText: '#303030',
darkText: '#1A1A1A',
black: '#000000',
white: '#ffffff',
dark: '',
medium: '',
light: '',
danger: '',
success: '#66A15A',
},
fonts: {
poppins: 'Anek Malayalam',
},
paddings: {
container: '15px',
pageTop: '30px',
},
margins: {
pageTop: '30px',
},
}

How to use theme in styled components

Import ThemeProvider from styled-components that takes a props theme. Now, get all the theme properties to the components wrapped inside ThemeProvider.

import styled, { ThemeProvider } from 'styled-components'
import { GlobalStyles } from './styles/Global'
import { theme } from './styles/Theme'
const Title = styled.h1`
color: ${(props) => props.theme.colors.primaryTextColor};
`
function App() {
return (
<ThemeProvider theme={theme}>
<GlobalStyles />
<Title>Hello World!</Title>
</ThemeProvider>
)
}
export default App

2. Global.js | Global Styles in Styled Components

In global styles, we reset all the default styling.

You may have noticed I have defined font-family, color (font/text color), and background-color in body, so it impacts the whole application.

import styled, { createGlobalStyle, css } from 'styled-components'
import fontsCss from './fonts.module.css'
export const GlobalStyles = createGlobalStyle`
${fontsCss} // this works as a normal styled css
/* Box sizing rules */
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
font-size: 100%;
}
body {
margin: 0;
padding: 0;
overflow-x: hidden;
min-height: 100vh;
text-rendering: optimizeSpeed;
font-family: ${({ theme }) => theme.fonts.anekMalayalam}, sans-serif;
font-size: 1rem;
color: ${({ theme }) => theme.colors.text};
background-color: ${({ theme }) => theme.colors.background};
line-height: 1;
}
h1,
h2,
h3,
h4,
h5,
h6,
p,
ul,
figure,
blockquote,
dl,
dd {
padding: 0;
margin: 0;
}
button {
border: none;
background-color: transparent;
font-family: inherit;
padding: 0;
cursor: pointer;
}
/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */
ul[role="list"],
ol[role="list"] {
list-style: none;
}
li {
list-style-type: none;
}
/* Set core root defaults */
html:focus-within {
scroll-behavior: smooth;
}
/* A elements that don't have a class get default styles */
a:not([class]) {
text-decoration-skip-ink: auto;
}
/* Make images easier to work with */
img,
picture {
max-width: 100%;
display: block;
}
/* Inherit fonts for inputs and buttons */
input,
button,
textarea,
select {
font: inherit;
}
/* Remove all animations, transitions and smooth scroll for people that prefer not to see them */
@media (prefers-reduced-motion: reduce) {
html:focus-within {
scroll-behavior: auto;
}
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
`

3. Breakpoints in Styled Components

Breakpoints are the points at which the website content adjusts to the device width, allowing you to present the best possible layout to the user. In the given code, I have used max-width if you like you can change it to min-width and play with breakpoints values as per your need.

const size = {
xs: '400px', // for small screen mobile
sm: '600px', // for mobile screen
md: '900px', // for tablets
lg: '1280px', // for laptops
xl: '1440px', // for desktop / monitors
xxl: '1920px', // for big screens
}
export const device = {
xs: `(max-width: ${size.xs})`,
sm: `(max-width: ${size.sm})`,
md: `(max-width: ${size.md})`,
lg: `(max-width: ${size.lg})`,
xl: `(max-width: ${size.xl})`,
xxl: `(max-width: ${size.xxl})`,
}

How to use breakpoint in media queries in styled components

To use break point in styled component we have imported the device object from BreakPoints file, and after that use the required size.

import styled, { ThemeProvider } from 'styled-components'
import { device } from './styles/BreakPoints'
import { theme } from './styles/Theme'
const Title = styled.h1`
color: ${(props) => props.theme.colors.primaryTextColor};
font-size: 48px;
@media ${device.md} {
font-size: 32px;
}
`
function App() {
return (
<ThemeProvider theme={theme}>
<Title>Hello world</Title>
</ThemeProvider>
)
}
export default App

I learned this technique from Mario Kandut this article

4. Using woff2 and Woff font in Styled Components

I have downloaded fonts in woff2 and woff format, the lighter and recommended font format to use, and added them to assets/fonts folder.

woff format fonts styled components

/* woff2 : Super Modern Browsers */
/* woff :Modern Browsers */
@font-face {
font-family: 'Anek Malayalam';
font-style: normal;
font-weight: 100;
src: url('../assets/fonts/anek-malayalam-v4-malayalam-100.woff2') format('woff2'),
url('../assets/fonts/anek-malayalam-v4-malayalam-100.woff') format('woff');
font-display: swap;
}
@font-face {
font-family: 'Anek Malayalam';
font-style: normal;
font-weight: 200;
src: url('../assets/fonts/anek-malayalam-v4-malayalam-200.woff2') format('woff2'),
url('../assets/fonts/anek-malayalam-v4-malayalam-200.woff') format('woff');
font-display: swap;
}
@font-face {
font-family: 'Anek Malayalam';
font-style: normal;
font-weight: 300;
src: url('../assets/fonts/anek-malayalam-v4-malayalam-300.woff2') format('woff2'),
url('../assets/fonts/anek-malayalam-v4-malayalam-300.woff') format('woff');
font-display: swap;
}
@font-face {
font-family: 'Anek Malayalam';
font-style: normal;
font-weight: 400;
src: url('../assets/fonts/anek-malayalam-v4-malayalam-400.woff2') format('woff2'),
url('../assets/fonts/anek-malayalam-v4-malayalam-400.woff') format('woff');
font-display: swap;
}
@font-face {
font-family: 'Anek Malayalam';
font-style: normal;
font-weight: 500;
src: url('../assets/fonts/anek-malayalam-v4-malayalam-500.woff2') format('woff2'),
url('../assets/fonts/anek-malayalam-v4-malayalam-500.woff') format('woff');
font-display: swap;
}
@font-face {
font-family: 'Anek Malayalam';
font-style: normal;
font-weight: 600;
src: url('../assets/fonts/anek-malayalam-v4-malayalam-600.woff2') format('woff2'),
url('../assets/fonts/anek-malayalam-v4-malayalam-600.woff') format('woff');
font-display: swap;
}
@font-face {
font-family: 'Anek Malayalam';
font-style: normal;
font-weight: 700;
src: url('../assets/fonts/anek-malayalam-v4-malayalam-700.woff2') format('woff2'),
url('../assets/fonts/anek-malayalam-v4-malayalam-700.woff') format('woff');
font-display: swap;
}
@font-face {
font-family: 'Anek Malayalam';
font-style: normal;
font-weight: 800;
src: url('../assets/fonts/anek-malayalam-v4-malayalam-800.woff2') format('woff2'),
url('../assets/fonts/anek-malayalam-v4-malayalam-800.woff') format('woff');
font-display: swap;
}

Note

JS file for fonts was reloading on every activity on the screen. We used a CSS file for fonts to fix this issue.

Testing Fonts in Styled Components

It’s time to test the fonts to see if we have it all set up correctly. For that, I have tested fonts from font-weight: 100 to font-weight: 800 in App.js.

Besides I used WhatFont google chrome extension to verify it.

testing font with what font

And that’s it, guys. We looked at folder structuring in the context of styled components, as well as the files that are part of the styles folder. Hope it added to your knowledge.

You can access these codes from this GitHub Repository. Moreover, if you like the information provided in the repository. consider giving it a star on GitHub. 😉