Problems with naming in Styled Components
Tags: react, javascript, typescript
Published: 2023-06-11 20:23:10

For a while now, our company has been using `styled-components`. I'm generally a fan. When you've got to update some component's styles, it's easy. The styles are scoped, and they're co-located with the other markup.

What I don't love is the fact that you have to give every styled component a name. You end up having a lot more names in the code than you would otherwise. And everybody seems to follow a different tack, when it comes to naming.

## Adding a generic prefix

Often, developers will just add a generic prefix, like `Styled-` to the name.

```jsx
const StyledH1 = styled.h1`
  font-size: 64px;
`
<StyledH1>My Big Heading</StyledH1>
```

This sort of circumvents the naming requirement altogether. Which in principle is a good thing. Because every time you add a new name to a codebase, it's like you're saying to the next developer:

> Hey! This thing is meaningfully different from that other thing, pay attention to this!

This avoids that.

But in practice, you end up having to come up with new names anyway, because you can't have name clashes. You can't have, say, two `<StyledDiv>`s. So you end up with something like this:

```jsx
const StyledWrapper = styled.div`...`
const StyledHeader = styled.div`...`
const StyledBody = styled.div`...`

<StyledWrapper>
  <StyledHeader>
    <h1>{heading}</h1>
  </StyledHeader>
  <StyledBody>
    <p>{description}</p>
  </StyledBody>
</StyledWrapper>
```

Which is a lot of words just to say, "I've got 3 divs here".

## Dropping the prefix

Since you're creating a new name anyway, you might as well just drop the prefix:

```jsx
<Wrapper>
  <Header>
    <h1>{heading}</h1>
  </Header>
  <Body>
    <p>{description}</p>
  </Body>
</Wrapper>
```

But then you're left with the problem of distinguishing "styled" components from components with that have added functionality too.

```jsx
/**
 * 🤔
 * Which of these is defined in our Design system, and which of these is
 * defined locally?
 */

<OutlinedButton>Click me</OutlinedButton>
<GhostButton>Click me</GhostButton>
```

Maybe that's okay. After all, this approach aligns better with the component paradigm. Everything's a component after all, so why bother distinguishing between components that are just styled, and other components?

Well, sometimes, using a generic prefix actually seems best. Like when you're augmenting an imported component with a couple of extra style declarations. Positioning is a common example:

```jsx
import { Button } from '@/ui'
const StyledButton = styled(Button)`
  margin-left: 8px;
`
<StyledButton>Click me</StyledButton>
```

In this case, you could do one better by giving it a more meaningful name, like `<PositionedButton>`. But as soon as you add more styles, you quickly think, maybe a generic `Styled-` prefix was best after all.

```jsx
// ❌ What does box-shadow have to do with positioning?
const PositionedButton = styled(Button)`
  box-shadow: 0 0 0 2px #000;
  margin-left: 8px;
`
```

## More names == good?

Maybe we're thinking about this all wrong. Maybe names are an opportunity and not a burden. After all, names give us the opportunity to communicate intent. And it can pretty difficult deriving intent from markup like this:

```jsx
<div className="container padded card border-light text-center">{/**/}</div>
// or this (CSS modules):
<div className={styles.wrapper}>{/**/}</div>
// or this (Tailwind):
<div className="shadow-sm border-b left-4 relative">{/**/}</div>
```

`styled-components` gives us the opportunity to name almost everythng in our markup. Because almost every element needs at least one style declaration.

Ultimately though, whether those names are helpful or harmful depends on the quality of those names. And anybody knows, naming things is hard.

## No easy solutions

I don't think there's an easy answer here. What I can say is that introducing `styled-components` to your codebase also introduces a heck of a lot of names. And that's sure different from a library like Tailwind, which requires no new names at all by default.

I think there are definitely cases for going with a CSS-in-JS solution like `styled-components`. But these days I'm spending more time with Tailwind. Time will tell whether Tailwind is more or less maintainable.