DEV Community

Cover image for A scalable approach to Styled Component Variants
Adrien Rahier
Adrien Rahier

Posted on

A scalable approach to Styled Component Variants

On several occasions I saw people asking the question: "What's the best way to create variants using Styled components?"

And, because this variant feature is not natively supported by Styled Components I saw different people have different ways to approach this issue.

So, today I wanted to show you a couple of solutions that actually scales.

Note that this post will be split into two parts.
In this first one we are going to focus on how to create Styled Component variants within the same file.

The problem with if else or switch statements

Let's start by creating a simple Styled Component button with 3 variants:

const ButtonStyle = styled.button`
  color: ${({ theme, flashy, disabled }) => {
    if (flashy) return "fuchsia";
    else if (disabled) return theme.grey;
    else return theme.primary;
  }};
`;
Enter fullscreen mode Exit fullscreen mode

As you can see, here you will have to maintain an if else (or switch) condition every time.
Obviously you could externalise this to a specific function determineColor but, still, the problem remains.

Solution 1

I have seen some people writing the same code as above in a more readable fashion:

const ButtonStyle = styled.button`
  color: ${(props) => props.theme.primary};
  ${({ variant }) =>
    variant == "flashy" &&
    css`
      color: "fushia";
    `}
  ${({ variant }) =>
    variant == "disabled" &&
    css`
      color: ${(props) => props.theme.grey};
    `};
`;
Enter fullscreen mode Exit fullscreen mode

Unfortunately, here again, you are kinda using an if-else statement.

Solution 2 using inheritance

My preferred solution is actually to use the built-in inheritance property of styled-components.

const ButtonStyle = styled.button`
    color: ${(props) => props.theme.primary};
`;

const ButtonStyleFlashy = styled(ButtonStyle)`
    color: fuchsia;
`;

const ButtonDisabled = styled(ButtonStyle)`
    color: ${(props) => props.theme.grey};
`;
Enter fullscreen mode Exit fullscreen mode

Here, ButtonStyleFlashy and ButtonDisabled inherits the CSS from ButtonStyle.

Zooming out

As a rule of thumb when I am creating styled component variants within the same file

▶️ If I am sure that the component will have exactly 2 variants I will use a Boolean props

const ParagraphVariant = styled.p`
    font-weight: ${(props) => (props.$bold ? `bold` : `normal`)};
`;
Enter fullscreen mode Exit fullscreen mode

▶️ If the component has x variants then I will use inheritance as seen above.

Top comments (1)

Collapse
 
redbar0n profile image
Magne

Nice post!

Stitches has the optimal solution to this, if one dares to leave styled-components: stitches.dev/blog/migrating-from-s...