At work, I've been using SCSS for a few years. I've now just started my own React project and want to use it as well. To this end I installed dart-sass
. I prefer building React component "bundles" where a folder with the same name as the component (ex. Button
) contains the following files:
The main point here is that I mostly prefer the *.module.scss
approach because it keeps the styles isolated.
However, I realize that there will be occasions for global styles. To this end, I've created a sass/styles.scss
file into which I can import partial style files like _variables.scss
, _fonts.scss
, etc.
What I'm unclear on is where should I best be importing styles.scss
? The highest level files, index.tsx
or App.tsx
seem like candidates but I'm hoping that the community could give me some best practice tips on this. Thank you.
That depends on the nature of the different SCSS files. Bear with me if I repeat anything you know already, I try to make my answer somewhat comprehensive.
Silent files: SCSS files that produce no CSS output are silent; mixins
, functions
, and variables
($-scss-vars
, not --css-vars
) are silent. So typically we would import _mixins.scss
/ _functions.scss
/ _variables.scss
only into other SCSS files, but we can do so without regret, anywhere and as often as we like without fear of introducing duplicates into the CSS.
Component style files: The typical Button.module.scss
files; scoped to one component only; and imported only there.
App scoped style files: If your app does not "own" the whole page and needs to play nicely with potential neighboring content on the page without leaking any styling, you can scope it to your app root (technically this is just a css module for your App.tsx). Skip this step if your app is basically the whole page and just apply global styles.
// App.scoped.normalize.module.scss
@import "style/font";
.app-scoped-normalize {
&, *, ::after, ::before {
box-sizing: border-box;
margin: 0;
padding: 0;
border: none;
outline: none;
}
font-family: $bodycopy-font-family;
color: var(--font-color);
font-size: $font-size-regular;
line-height: $line-height;
h1, h2, h3, h4, h5, h6 {
font-family: $heading-font-family;
}
ul, ol {
list-style: none;
}
}
// App.tsx - here import order is relevant if css rules have equal specifity
import normalize from './App.scoped.normalize.module.scss';
import colors from './App.scoped.colors.module.scss';
import style from './App.module.scss';
// ...
return (
<div className={classnames(
normalize.appScopedNormalize,
colors.appScopedColors,
style.appRoot,
)}>
// ...
</div>
);
index.tsx
; order of imports is relevant, so you might want to import it before App.tsx
:// index.tsx
import './global.scss';
import { App } from './App';
// ...render App...
As others have pointed out, you could import any global styles in App.tsx
. I always try to reach a lucid mental model of all involved parts, and translate that mental model into code to the best of my abilities; and to me it feels more natural to keep the globals out of the App.tsx
.
And it helps with keeping the order of imports clear.