DEV Community

Cover image for OhSnap! Sass Folder Structure For React
Gedalya Krycer
Gedalya Krycer

Posted on • Edited on

OhSnap! Sass Folder Structure For React

The "OhSnap!" series explores bite-sized tips that you can apply today.


Intro

Today we are going to walk through the folder structure of a React project that I recently completed.

I am using the node-sass npm package, and staying always from any CSS frameworks like Bulma or Bootstrap.

After some research and trial/error, I found that the below system worked well for me. Hopefully it helps you as well.


The Folder Structure

The following has been simplified for the sake of clarity, but the essential structure is still the same. You can view the actual Github repository here.

/src
• ———— /components
•      |———— /NominationContainer
•            |———— NominationContainer.js
•            |———— nominationContainer.scss  <—— (section 2)
•
•
• ———— /sassStyles  <—— (section 1)
•      |————  _animations.scss
•      |————  _functions.scss
•      |————  _global.scss
•      |————  _mixins.scss
•      |————  _typography.scss
•      |————  _variables.scss
Enter fullscreen mode Exit fullscreen mode

Section 1

This folder sits outside of the components and holds all partials and styles that can effect multiple components. As you will see in Section 2, individual components will import from these partials as needed.

• ———— /sassStyles  <—— (section 1)
•      |————  _animations.scss
•      |————  _functions.scss
•      |————  _global.scss
•      |————  _mixins.scss
•      |————  _typography.scss
•      |————  _variables.scss
Enter fullscreen mode Exit fullscreen mode

_animations.scss

This partial stores the actual @keyframe CSS animations. It helps to drastically reduce the size of component stylesheets. In our example this file stores 22 animations, which is almost 800 lines of code! That is a lot of space saved in our component files, that now just need to reference this file.

_functions.scss

This partial contains any SASS functions which process and return a value. I didn't use them in this project, but a great example of them can be found in this StackOverflow thread.

_global.scss

This partial contains styling that overrides global elements, such as the #root or body elements. In our example it is also importing the _variable.scss file to reference a color.

_mixins.scss

This partial can hold any block of code that is repeatable. In our example I am using mixins to determine breakpoint sizes. They are also using variables, so if my overall lg size changes, it will update everywhere.

_typography.scss

This partial holds major typography element styles such as h1-h6, p, and global classes or ids. As you can see in our example, I like to stay away from applying super-specific properties here, like color. This way I have the flexibility of changing it in different parts of the app, without worrying about specificity.

_variables.scss

This partial contains repeatable property values, such as brand colors and sizes. By storing #002e25 in the variable $primaryDark2Color I can apply it to properties like color and border while preserving the option to change the color globally later on.

Section 2

This is an example of an individual component with a .js file and its associated .scss file for styling.

/src
• ———— /components
•      |———— /NominationContainer
•            |———— NominationContainer.js
•            |———— nominationContainer.scss  <—— (section 2)
Enter fullscreen mode Exit fullscreen mode

nominationContainer.scss

This is an example of an individual component's .scss file and I have included its code below. Note how it imports the animations, variables, and mixin partials.

Because of this, animations just require 2 lines of code to establish the settings. Colors are based on variables and media queries are pulled from mixins.

In the future, I can just change these in their original partial files and they will update here.

@import '../../../sassStyles/variables';
@import '../../../sassStyles/animations';
@import '../../../sassStyles/mixins';

.nom-container {
    background: $primaryDark1Color;
    height: 100%;
    padding: 26px 20px;
    margin-top: 15px;
    opacity: 0;

    -webkit-animation: fade-up 1s cubic-bezier(0.165, 0.840, 0.440, 1.000) 1.4s both;
        animation: fade-up 1s cubic-bezier(0.165, 0.840, 0.440, 1.000) 1.4s both;


    @include customMinBreakPoint(1024) {
        margin-top: 0;
        padding: 26px 0 50px 0;
        -webkit-animation: fade-left 1s cubic-bezier(0.165, 0.840, 0.440, 1.000)  both;
        animation: fade-left 1s cubic-bezier(0.165, 0.840, 0.440, 1.000)  both;
    }

    &__counter-wrapper {
        display: flex;
        justify-content: center;  
        margin-bottom: 30px;
        margin-top: 0;
        opacity: 0;

        -webkit-animation: fade-up 0.9s cubic-bezier(0.165, 0.840, 0.440, 1.000) 1.6s both;
        animation: fade-up 0.9s cubic-bezier(0.165, 0.840, 0.440, 1.000) 1.6s both;

        @include customMinBreakPoint(1024) {
            justify-content: flex-end; 
            margin-right: 50px;
            margin-bottom: 75px;

            -webkit-animation: fade-up 0.9s cubic-bezier(0.165, 0.840, 0.440, 1.000) 0.25s both;
            animation: fade-up 0.9s cubic-bezier(0.165, 0.840, 0.440, 1.000) 0.25s both;
        }

        @include customMinBreakPoint(1400) {
            margin-right: 12%;
        }

        @include customMinBreakPoint(1500) {
            margin-right: 15%;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Thumbnail designed with Figma

Top comments (4)

Collapse
 
abid413119 profile image
Abid Al - Amin

if we import variables/mixins in multiple files it may duplicate the same CSS in multiple files. Is it an optimized solution?

Collapse
 
ch1zo profile image
chizo nwazuo

My thought too... There should be a way to import all variables/mixins globally so all other scss files can reference it

Collapse
 
ggamir profile image
Amir • Edited

There are ways to configure webpack to do it (stackoverflow.com/questions/355334..., dev.to/dennisfrijlink/comment/19dh5)

And here's an option with creating an additional 'global-imports.scss' file to use across the different component scss, or to import globally through webpack.

sassStyles/_global-imports.scss:

@import './variables';
@import './mixins';
Enter fullscreen mode Exit fullscreen mode

nominationContainer.scss

@import '../../../sassStyles/global-imports';
Enter fullscreen mode Exit fullscreen mode

Variables (sass variables) and mixins are sass constructs that are not rendered as css on their own, so including them multiple times will not result in duplicated css.

Animations, however, are css definitions, so importing the animations partial multiple times across components would duplicate the css. However, there's no need to import animations into the component file to use them in the app. It would be enough to import the animations a single time into a main.scss / main.css file that is included in the app at the top level, and the browser would have those keyframe definitions loaded in and any other css that refers to it would work.

Collapse
 
ceonyema profile image
Emmanuel C. Onyema

This is exactly the issue, I'm facing. I am tempted to use for global variables and scss for the rest.