13

I have the following project structure:

gatsby-config.js
/src
  /components
    layout.jsx
    /button
      button.jsx
      button.scss
  /pages
  /styles
    styles.scss
    _mixins.scss
    _variables.scss

and gatsby-config.js and styles.scss are configured respectively in the following way:

...
plugins: [
...,
`gatsby-plugin-sass`
]
...
@import 'variables',
        'mixins';

in order to access the mixins and variables, the styles.scss is being currently imported in all the components' scss files, e.g.:

//button.scss
@import './../styles/styles.scss'

This approach is working, but the problem is, as the project grows, the styles.scss is being imported multiple times and seems to be something wrong with this approach. Is it possible to import styles.scss only once, and make all mixins and variables available across all the components?

vtolentino
  • 754
  • 5
  • 14

5 Answers5

21

You are able to pass options to Sass via gatsby-plugin-sass.

The following options would globally expose the contents of ./src/styles/_styles.scss to each Sass file in the project, without the need to explicitly import it.

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-plugin-sass',
      options: {
        data: `@import "${__dirname}/src/styles/styles";`,
      }
    },
  ],
}

Note: The below might be obvious to some but it's worth mentioning for future readers.

Only do this with Sass files that contain just variables, mixins, functions, etc (Sass features that do not output any actual CSS until they are consumed). Otherwise you will end up with CSS that is repeated multiple times across your project.

Example repo

ksav
  • 20,015
  • 6
  • 46
  • 66
  • I tried your suggestion, but with no luck. The terminal was showing `File to import not found or unreadable dir1dir2dir3src/styles/styles`. For some strange reason the path shows no slashes between the directories. I tried then `data: @import "./src/styles/styles"` and the project compiled. However, the styles are added to all files and the problem with the multiple imports still remains. – vtolentino Sep 11 '19 at 16:23
  • Remove anything from the styles folder that would output any css. – ksav Sep 11 '19 at 17:41
  • And how should I include the data which produces any css? – vtolentino Sep 11 '19 at 18:02
  • You should probably import the stylesheet to the relevant component. – ksav Sep 11 '19 at 18:21
  • If you have some base css inside `styles.css`, import that into your layout component. – ksav Sep 11 '19 at 18:24
  • unfortunately I am only using `scss` files. – vtolentino Sep 11 '19 at 18:46
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/199329/discussion-between-ksav-and-vtolentino). – ksav Sep 11 '19 at 18:50
  • 2
    Update: This has been changed to `initialData` – martin Jan 23 '21 at 03:24
  • 5
    `additionalData` – martin Feb 12 '21 at 21:39
  • 1
    Not obvious at all to folks new to Gatsby! Thank you. – doublejosh May 10 '21 at 21:33
5

Providing SCSS variables globally to your components

gatsby-plugin-sass config

gatsby-config.js file:

{
  resolve: `gatsby-plugin-sass`,
  options: {
    implementation: require("sass"),
    data: `@use "${__dirname}/src/global-styles/variables" as var;`
  }
},

var will be used as namespace.

Providing variables to your scss files

./src/global-styles/_variables.scss
./src/components/main.jsx
./src/components/main.module.scss

Info about the underscore in _variables.scss, partials.

_variables.scss file:

$color-1: red;
$color-2: blue;

main.jsx file:

import React from 'react'
import style from './main.module.scss'

const Main = () => (
    <div className={style.main}>Content</div>
)

export default Main

main.module.scss file:

.main {
    color: var.$color-1;
}

But I need expose some global styles in gatsby-browser.js

Well, your are going to need @use, or follow other answers that use @import in gatsby-config.js. Mixing @import and @use may not work because of:

Heads up!

A stylesheet’s @use rules must come before any rules other than @forward, including style rules. However, you can declare variables before @use rules to use when configuring modules.

https://sass-lang.com/documentation/at-rules/use

I stopped using @import, only using @use.

global-styles.scss file:

@use "./variables" as var;

body {
    color: var.$color-2;
}

gatsby-browser.js file:

import './src/global-styles/global-styles.scss'
Undefined Behavior
  • 2,128
  • 4
  • 24
  • 34
2

Create a file named gatsby-browser.js in the root of your directory. Import the .scss file once and it will work perfectly .

In your gatsby-browser.js

import "./src/styles/styles.scss"
Ankit Sinha
  • 1,630
  • 1
  • 20
  • 19
  • 1
    I tried importing in the `gatsby-browser.js` but it did not work. In the tutorial they only mention importing css files, not scss – vtolentino Sep 11 '19 at 16:33
  • It works perfectly. What error are you getting? You need to install `node-sass` and `gatsby-plugin-sass` to make that work – Ankit Sinha Sep 12 '19 at 17:29
  • 2
    If I only include the `styles.scss` in the `gatsby-config.js` file, the variables and mixins are shown as not defined e.g. `No mixin named bpTabletPortraitUp`. – vtolentino Sep 13 '19 at 12:05
2

As Ankit Sinha mentioned, you can import your styles in gatsby-browser.js:

import './src/styles/styles.scss';

This method is mentioned in the Gatsby tutorial.

According to the docs (see Standard Styling with Global CSS Files):

The best way to add global styles is with a shared layout component.

Your project structure suggests that you are using one (layout.jsx). If that's the case, you can also import your styles in layout.jsx:

import './../styles/styles.scss';
Jelefra
  • 404
  • 6
  • 13
  • 1
    I tried importing in the `gatsby-browser.js` but it did not work. In the tutorial they only mention importing css files, not scss – vtolentino Sep 11 '19 at 16:36
1

I cant write comments yet. I dont have the reputation. But what a complete answer from Undefined Behavior.

Just to order a little bit:

  • Import your global-styles.scss in gatsby-browser.js
  • Configure something that's going to be exposed to all scss files, in your gatsby-config.js. It can be an @import or an @use. With @import you access directly to your variables and mixins and with @use you reference it. I don't really know what are the benfits of both, but you could use any.