Practices for Harnessing SCSS with React

We have been hard at work on a client project using React. We haven’t made our way to implementing CSS Modules yet, but we’ve established a set of rules to help us keep the CSS in order.

1. Styles Are Scoped

React projects tend to break down the structure of the DOM into a lot of components, which means you’re going to have a lot of SCSS files. This is ok! It takes a little getting used to, but we have come to really like this approach to managing styles because everything we need for a component is in a single directory.  Here is an example of what a button component could look like:


/components
  /Button
    button.stories.tsx
    button.tests.tsx
    index.tsx
    styles.scss

Just as your components are ever-changing and in need of refactoring, so is the SCSS. This also goes for your test and storybook stories. To decide what should go into each style.scss file, we have been matching the style rules to the render elements of the React file.

2. SCSS Files Are Small

Keeping the CSS files small allows us to read the style rules more easily. A long, multi-nested SCSS can be hard to follow or overwhelming to people who are not as comfortable with dense style rules. Instead, keep it short and simple. 

It also seems that we have had a much higher success rate of removing unused styles with this approach.  If you’re finding your style rules too lengthy, consider refactoring the React code.

3. Top-level Component Classes Are Unique

Making it easy to search for style rules is critical when styling and refactoring elements. Because all of the style sheets are named style.scss, you may find yourself relying heavily on the text editor’s Find function to locate class and ID names.

We try not to define a style twice in two different locations. This can be challenging at first, but it will save a lot of time when it comes to refactoring and knowing where to find the style rules that affect a certain element.

A unique element name allows us to scope the CSS rules locally to that component. This can be done by keeping the style rules of that component nested inside the unique class or ID, which ensures that any children classes or IDs you create are not unintentionally affecting other component’s elements.  Then you can pull in globally defined styles from outside the component’s defined style rules when necessary using Sass’s @extend feature.


.my-great-div{

.child-div-1{}
.chile-div-2{}

}

4. Test Component’s Styles

Use Storybook to check that your component works on its own and doesn’t rely on missing classes or dependencies. With SCSS’s tendency to get unwieldy and inadvertently reach elements you didn’t want, styled Storybook has proved to be a great asset.

5. Collect Your Style Files

Use webpack or the like to collect and group your SCSS files into one CSS file for your project. This webpack article can get you going.

6. Keep it Responsive

We have been adding the media queries directly to the rule definition. This has made both refactoring and altering an element’s styles simpler, since it allows you to go to one place in the CSS to modify the rules for all layouts instead of having to traverse a file where the element may be defined multiple times. Doing this can work for both desktop and mobile-first approaches. Below is an example of this pattern, where you can easily see the .div-element-name’s border-radius being increased at each layout size.


.div-element-name{
  background: orange;
  border-radius: 5px;

  @media only screen and (max-width: $large-screen) {
    border-radius: 25px;
  }

  @media only screen and (max-width: $small-screen) {
    border-radius: 50px;
  }

  &:active{}
  &:focus{}
  &:hover{}

}

What other steps or practices do you follow to help keep CSS rules under control on your larger software projects?