loading...

Reusing CSS With Styled Components

stephencweiss profile image Stephen Charles Weiss Originally published at stephencharlesweiss.com on ・2 min read

Styled components are really nice in compartmentalizing styling and keeping it close to the components that use it.

I wasn’t around for the “good old days” when we had a single master CSS file, but I can imagine how challenging it would be.

That’s why I thought it was interesting when I came across an example where I wanted to share styling across different components in a sudo-object-oriented way.

In this example, I have two components. They’re both inputs, but they’re built off of different bases (we’ll take this as granted for the sake of this example). The styling, however, is nearly identical with the second one building on the base of the first.

How could I re-use the styling with Styled-Components without duplicating code and potentially diverging in the future when I forget to update one?

What follows is a simple example demonstrating how I used css helper function within styled-components to effortlessly reuse my css without duplicating code.1

My original styled input:

import styled from styled-components;

export const DefaultInput = styled.input`
  border: 1px solid ${({error})=>( error ? `red` : `grey` )};
  border-radius: 4px;
  outline: none;
  padding: 0.5em;
`;

Since my second component actually isn’t going to be an input (it will be a button), I unfortunately can’t just do:

import styled from styled-components;

export const SecondComponent = styled(DefaultInput)`
  /* make changes as needed*/
`;

This would be ideal since I could simply extend the CSS I defined originally.

Enter the CSS helper function from styled components!

import styled, { css } from styled-components;

const baseInputStyles = css`
  border: 1px solid ${({error})=>( error ? `red` : `grey` )};
  border-radius: 4px;
  outline: none;
  padding: 0.5em;
`;

export const DefaultInput = styled.input`
  ${baseInputStyles}
`;

export const SecondComponent = styled.button`
  ${baseInputStyles}
    /* make changes as needed*/
`;

resources

Discussion

pic
Editor guide
Collapse
piavgh profile image
Hoang Trinh

Since my second component actually isn’t an input, I unfortunately can’t just do...

I don't understand the above statement.

Can you please explain what is the difference between your 2 examples?

Collapse
stephencweiss profile image
Stephen Charles Weiss Author

Oy - thank you for pointing that out! That's a mistake on my end.

I've updated the post to reflect what I meant. Bear in mind that the use of input and button are purely illustrative and could be anything. The bigger point is that the base elements are different and so can't simply be extended.

But we can use the css method to create a shared UI and eliminate some duplication.

Collapse
mglavall profile image
Marçal

Styled components has a property for this kind of use cases: styled-components.com/docs/api#as-...

If you want to keep all the styling you've applied to a component but just switch out what's being ultimately rendered (be it a different HTML tag or a different custom component), you can use the "as" prop to do this at runtime.

Collapse
stephencweiss profile image
Stephen Charles Weiss Author

Good point! When I wrote this I hadn't yet found polymorphic components. When I did a few weeks later, I wrote about them as well: stephencharlesweiss.com/blog/2019-... :)

(One point: I have had trouble with polymorphic components in my typescript app. Haven't dug into it too deeply yet, but just something to keep in mind)