Naming Styled Components

The S.ecret is in the import.

Look at those pixels.

Context

At Inturn we spend a lot of time debating and crafting best practices around common patterns. Recently, after converting our styling system to emotion (a styled component library), we ran into a question: “How should we name these things?”

Problem

The issue we were running into mostly stemmed from our styled container components. Traditionally, when using classes, you would give the root element of the component a class with a name that matches the component name.

Something like this:

const Navigation = () => (
<div className=”Navigation”>
{/* links */}
</div>
);

When we began building new components using a styled component system, it made sense to follow a similar convention so that the root element was named the same as the actual component.

As you can imagine, this causes some problems:

const Navigation = styled.div`/* styles */`;
const Navigation = () => (
<Navigation />
);
// => JS interpreter: “I can’t believe you’ve done this x_x”

So we ended up writing code similar to this:

import Header from ‘Components/Header’;
import { Wrapper, Content } from ‘./styles’;
const Navigation = () => (
<Wrapper> {/* 🤔 */}
<Header>{headerContent}</Header>
<Content>{content}</Content>
</Wrapper>
);

But is that good? What should we call that root component? We had a few conversations, but none of us were too happy with the outcomes.

  • Container — has some redux/data related connotations
  • Root — we already have a component named Root in our App
  • Wrapper — it’s ok?
  • Styled<MyComponentName> — lets us know its a styled component but is a bit clunky

The main issue with Root, Container, and Wrapper as naming conventions was that it didn’t necessarily indicate that the component was a styled-component. It could be anything (and in the case of Root, an actual component we already had). Name-spacing everything with Styled fixed the issue of being specific, and gave us a somewhat traditional naming convention but it felt too heavy-handed.

We eventually landed on a hybrid system that we felt was ok. We named the root styled-component the same as that file’s component name with a Styled prefix; any other styled component would be named regularly. It looked like this:

import Header from ‘Components/Header’;
import { StyledNavigation, Content } from ‘./styles’;
const Navigation = () => (
<StyledNavigation>
<Header>{headerContent}</Header>
<Content>{content}</Content>
</StyledNavigation>
);

It worked, but it still felt slightly off. It’s kinda ugly and aside from the root component, it was tough to tell whether the children components were actually being imported from other parts of the app, or just styles. It was also not an easy rule to enforce or keep consistent. Even after coming together as a team and discussing this convention, there was still some code released that didn’t follow our newly prescribed pattern.

Inspiration

One day, one of our engineers came across a tweet that would change how we wrote and name-spaced styled components. The suggestion in the tweet was simple, elegant, and solved all the issues we had been running into.

The benefits to this solution were clear, and we pretty much decided to adopt this pattern on the spot. Our code now looked like this:

import Header from ‘Components/Header’;
import * as S from ‘./styles';
const Navigation = () => (
<S.Navigation>
<Header>{headerContent}</Header>
<S.Content>{content}</S.Content>
</S.Navigation>
);

It’s now immediately apparent which components are styled and which aren’t 🙌. We also get the added benefit of not having to import every single style (which can quickly grow to 10+ if you’re not careful).

It’s not a perfect system…

One of our initial hangups with switching to this pattern is that because of the import * syntax, tree shaking failed to remove unused code and our linter failed to point out any extraneous styles. Another small (and not fully resolved) issue we ran into is how we handle smaller components where we define the styles in the same file. One proposal is to create an S object that houses the styled components, so that we follow a similar pattern as our other components. For example:

import Header from ‘Components/Header’;
const S = {};
S.Navigation = styled.div`/* styles */`;
S.Content = styled.div`/* styles */`;
const Navigation = () => (
<S.Navigation>
<Header>{headerContent}</Header>
<S.Content>{content}</S.Content>
</S.Navigation>
);

It’s kinda strange, but it serves the purpose.

Other options would be to force importing styles from another file or just forget about this pattern entirely for non-imported styles (my least favorite personally).

Wrap-up

The S-dot naming convention isn’t perfect, but it’s pretty darn great. For us, the benefits far outweigh the cons and it’s so simple to integrate. I recommend trying it out and seeing if it fits into your workflow. If you have any suggestions or wanna share how you handle your styled components please let us know!