Home > Designing, Others > DRY-ing up styled-components

DRY-ing up styled-components

November 23rd, 2020 Leave a comment Go to comments

I like working with styled-components. They allow you write CSS in your JavaScript, keeping your CSS in very close proximity to your JavaScript for a single component. As a front-end developer who loves to dissect a web page and break it down into reusable components, the idea of styled-components brings me joy. The approach is clean and modular and I don’t have to go digging in some gigantic CSS file to see if a class I need already exists. I also don’t have to add a class to that never-ending CSS file and feel guilty for making that already gigantic file even bigger.

However, as I continue down the path of using styled-components, I have started to realize that, while it is great to separate out CSS styles to be specific to singular components, I am starting to repeat myself a lot for the sake of organizing my styles on a per component basis. I’ve been creating new CSS declarations, and thus, new styled-components, for every component, and am seeing a great deal of duplication in my CSS. No, the styled-components aren’t always exactly the same, but two of the three lines of CSS would match two of the three lines of CSS in another component. Do I really need to repeat this code every place I need these styles?

Take flexbox, for example. Flexbox is great for responsive layouts. It will align items a certain way, and with minimal changes, can be tweaked to look good across different screen sizes. So, more often than not, I find myself writing:

display: flex;
flex-direction: row; /* the default; in react native, column is the default */

Almost as often, I found myself writing:

display: flex;
flex-direction: column;

The two code snippets above are fairly common: the first takes all of the child elements and positions them next to each other — from left to right — in a row. The second takes all of the child elements and positions them above and below each other — from top to bottom -— in a column. Each of these code snippets can be made more specific; however, we can add different properties to further specify how we want the child elements laid out on the page. If we want the elements spaced evenly across the available screen width, for example, we can add the following line to each code snippet:

justify-content: space-evenly;

Additionally, there are other properties, like align-items that we can add to further customize the layout of these elements. So, if we have three different components that all require a flexbox layout, but have additional differing properties, how can we use styled-components in a non-repetitive way?

Initially, it makes sense to create three sets of styles for each component, like this:

// component one
const ComponentOne = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
`


// component two
const ComponentTwo = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: space-between;
`


// component three
const ComponentThree = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: space-evenly;
`

The styles listed above will do the job. All three components have child elements laid out in a row — positioned from left to right — with different spacing between each child element. However, having the same two lines of code repeated three times adds CSS bloat.

To avoid repeating ourselves, we can extend a base component to each of the other components and then add the additional styes we need to those components:

// flex row component
const ExampleFlex = `
  display: flex;
  flex-direction: row;
`


// component one
const ComponentOne = styled(ExampleFlex)`
  justify-content: flex-start;
`


// component two
const ComponentTwo = styled(ExampleFlex)`
  justify-content: space-between;
`


// component three
const ComponentThree = styled(ExampleFlex)`
  justify-content: space-evenly;
`

That feels much better. Not only does this version — where we extend off of the component — remove repetitive code, but it also keeps the code related to displaying items in a row in one spot. If we needed to update that code related to the direction of the items to a column, we can do that in one spot instead of three.

Important note: When you’re extending styles off of another component, the styles that inherit from that base component need to be listed after the base component like in the example above. Placing above would cause an error that reads: Uncaught ReferenceError: Cannot access ‘ExampleFlex’ before initialization.

To take this idea one step further, the following demo shows a situation where you might need similar styles on two different UI elements on the page, but those elements each have their slight differences.

CodePen Embed Fallback

As you can see, both the navigation that lives at the top of the page and the footer that lives at the bottom of the page need to be laid out in a row direction on larger screens and then shift to a column layout on mobile devices. The two elements differ, however, in that the navigation at the top of the page needs to be aligned to the left to leave room for the logo on the right while the footer links need to be aligned right. Because of these differences, it makes sense to create two different styled components for each of these elements; the element for the top navigation and the

Categories: Designing, Others Tags:
  1. No comments yet.
  1. No trackbacks yet.
You must be logged in to post a comment.