Styled Components in React — Using the Atomic Design Pattern to Quickly Develop New Components

Sunny Singh
Level Up Coding
Published in
9 min readAug 15, 2020

--

As a front-end developer, we have many choices at our disposal as to how we want to style our components. However, some choices, such as using CSS files or inline styling are becoming things of the past.

The future of styling components is trending towards CSS-in-JS. What is CSS-in-JS? In simple terms, it’s a way for you to write CSS code in a JavaScript file. Styled Components is the leading CSS-in-JS library on the Internet right now.

Furthermore, companies such as Airbnb, Lyft and Google make use of Styled Components. Why does this matter? It means that Styled Components has an active base of contributors and a thriving community. I’m just one member of many in the Styled Components community.

However, this post isn’t going to be an “introduction to Styled Components”, it’s about how you can use a technology such as Styled Components in a smart manner. The goal of this post is to answer the question of “how can I use Styled Components to their full potential?”

So let’s dive right in.

Let’s take a trip back to your high school chemistry class. We know that all objects in the universe, no matter how complex, are built from atoms. Whether those objects are living or not, everything is built from the “ground up” using these atoms.

Atoms bond with other atoms to create molecules. Molecules come together to create more complex organisms such as cells. Organisms come together to create even more complex structures. Do you see the pattern?

You start off with the most basic building block, the atom, and start to develop more complex structures from it.

That sounds an awful lot like how we tend to build our React components. We take the building blocks of HTML, such as a <div> , and pair them with other building blocks of HTML to create more complex structures.

That’s the idea behind the Atomic design pattern. But how do you break down your components into their most basic elements in a smart and controlled manner? That’s where this handy-dandy Periodic Table of Elements comes in handy.

No, we’re not going to go over what hydrogen and helium is, however, we will go over what the basic building blocks of any HTML page are.

While researching this topic, I came across a very helpful graphic that you’ll want to save to your computer. Seriously, it’s that helpful. It’s essentially a “periodic table of elements” in regards to HTML elements.

These are all the possible “atoms” that you can build and apply styles to using Styled Components. For example, using Styled Components, you can give a base styling for any <table> or <img> that will ever be used on your website.

Furthermore, you can make your atoms “dynamic” and fully customizable while also maintaining a base design by leveraging the fact that you can pass in props to Styled Components. Not only that, you can pass attributes to Styled Components as well. This can be helpful if certain attributes must be defined, such as src in an image. Below is an example of this applied to an <img> element:

import styled, { css } from 'styled-components';const Image = styled.img.attrs((props) => ({
src: props.src
}))`
width: 100%;
height: auto;
border-radius: 8px;

${props => (props.shadow != undefined) && css`
box-shadow: 0px 4px 8px 0px rgba(42, 42, 42,0.25);
`}
${props => (props.circle != undefined) && css`
border-radius: 50%;
`}
`;

This is a rather simple example, however, now whenever you’re building more complex “molecules” (more on this below), you’ll have options on how to configure your <Image> styled component. For example, if you wanted your image to have a shadow in a certain place, simply pass your styled component the shadow prop and your image shall have a shadow.

const SomeComponent = () => {
return (
<Image src="..." shadow />
);
}

Say you wanted to control how your <Image> styled component looks on different screen sizes, that’s where the whole CSS-in-JS paradigm really shines. You can simply pass in a function that returns some CSS.

So, for example, if we wanted to add the option to style the <Image> component on a mobile device by just passing it a prop, you would build your Styled Component as such:

import styled, { css } from 'styled-components';const gimmeMobileStyles = (mobileStyles) => {
var styles = '@media only screen and (max-width: 480px) {';

mobileStyles.forEach((style) => {
styles += style;
});
styles += '}';

return css`${styles}`;
};
const Image = styled.img.attrs((props) => ({
src: props.src
}))`
width: 100%;
height: auto;
border-radius: 8px;

${props => (props.shadow != undefined) && css`
box-shadow: 0px 4px 8px 0px rgba(42, 42, 42,0.25);
`}
${props => (props.circle != undefined) && css`
border-radius: 50%;
`}
${props => (props.mobileStyles != undefined) &&
gimmeMobileStyles(props.mobileStyles)
}
}`;

Now, whenever you’d like your <Image> component to have different styles on a mobile device, you can pass in an array of CSS rules and they will be applied to your component using a media query.

This is just an example for mobile styling, you can pass in a prop for styling on a tablet, a small laptop, a large desktop screen, all from just passing in an array of CSS rules.

Since atoms are something that are meant to be re-used over and over again throughout your application, you can start to group certain atoms together into the same file and simply export them.

Your file structure could look like the following:

components
|__ atoms
|__ typography.js
|__ tables.js
|__ ...

A sneak peek into typography.js :

// components/atoms/typography.jsimport styled from 'styled-components';const gimmeMobileStyles = () => { ... };export const HeaderOne = styled.h1`...`;
export const HeaderTwo = styled.h2`...`;
export const HeaderThree = styled.h3`...';
...

Now you have all your typography based atoms in one single file, which it makes quick and easy to access. If you’re working on a component that requires your styled h1 , you can simply import it with the following import statement: import { HeaderOne } from 'components/atoms/typography.js';

From here, we can use atoms to build molecules. With the molecules, we can build organisms and so on. Let’s walk through each step.

Now that you’ve defined and styled all your atoms, it’s time to start building more exciting structures with these atoms. Generally speaking, in chemistry, usually a few atoms come together to form a “molecule”, such as H2O.

In the same manner, by putting together a few atoms, you can start to create more interesting components which are called “molecules.”

For example, we can combine a styled <Label> and a styled <Input> component together to create the <FormInput> styled component.

By stitching together different molecules, you can start to create organisms. This is where things start to get really interesting. Just like in biology, simple organisms usually have a single purpose.

For example, we can use multiple <FormInput> components to create a <SignupForm> component. The purpose of this organism is to help a user sign up. By having this mindset that an organism should only have one purpose, you can be smarter about how you define your organisms.

Want to know what makes an ant colony capable of doing extraordinary tasks such as waging war with other ant colonies? After all, one ant by itself isn’t able to do much by itself. So how can a bunch of rather useless ants come together to do something useful?

They’re able to do this because of something called emergence theory. It essentially states that “the sum of the whole is greater than the sum of the individual parts.” If you didn’t quite catch that, here’s the same statement in a mathematical format applied to our ant example:

(capability of whole colony) > (capability of ant 1) + (capability of ant 2) + ...

The same theory can be applied to our React organisms. Each organism can really only do one thing, however, by putting them together, they can start to create complex user interfaces.

For example, by putting a <BlogBody> organism next to a <Sidebar> organism, you‘re starting to create what is to be the content of any blog page.

Another common example is that of the navbar. You generally will have a <Logo> component, some <NavLink> components and maybe a <SearchBar> component. By putting these organisms together, you’ve created a <Navbar> component.

A good rule of thumb to know if you’re working on a layout is to see how many “positioning” and “sizing” CSS rules you are writing versus “pixel styling” CSS rules. For example, if you’re mainly using styles such as position , display, flex , width or height , you’re most likely working on a layout.

The final step in the Atomic design pattern is take your layouts and arrange them so that it creates a full page. This can be a rather simple step, however, the satisfaction you get when you only have to write a few lines of JSX to create an entire page, it’s priceless.

For example, we could have the following layouts: <Navbar>, <BlogPost> and <Footer> . By arranging them in order, we can have an entire blog post page done. Seriously, you’re JSX is going to look like the following:

return (
<BaseHTML>
<Navbar some_props />
<BlogPost some_props />
<Footer some_props />
</BaseHTML>
);

Note: If you take a look at the periodic table of elements, you’ll notice that there’s an <html> tag included in the top left corner. Whatever base styles you want on any page is the <BaseHTML> component above.

We have to remember that Styled Components is just a tool at the end of the day. It’s not going to automatically solve your styling issues. You still have to know how to use the tool correctly. That’s where the Atomic design pattern can help.

A quick summary of each of the levels in the Atomic design pattern and how they rely on the level below it to wrap things up:

  1. Atoms: The most basic building blocks of any HTML page.
  2. Molecules: A component comprised of a few different atoms.
  3. Organisms: Multiple molecules put together with a single purpose.
  4. Layouts: Organisms put together to create complex user interfaces.
  5. Pages: Layouts arranged to make an entire page.

Finally, a tool that can be combined with Styled Components and the Atomic design pattern is called Storybook. It helps you develop, organize, document and test components in an isolated manner, which is perfect for adhering to the Atomic design pattern. If you’re really serious about upgrading your frontend architecture, learn about Storybook and how to add it to your React project here.

Still Got Questions?

If you have any questions about Styled Components or the Atomic design pattern, feel free to reach out to me via email or Twitter.

--

--

Backend developer passionate about leveraging practical solutions. Sharing insights on using software development and AI to solve problems. Connect for more!