Hi, I am migrating and combining some older sites into one gatsby site. I need to import global CSS on some pages, but not on others. The issue is that if I import the CSS on one page, it gets included in all the other pages.
I'm importing the CSS from the specific page that needs it, so I would expect it to show only on that page. Is this a bug?
I've seen this issue but the suggested solution there is to use css modules, and migrating to CSS modules would be very time consuming at this point (initial migration phase).
I've also tried the solution here but this inlines the CSS, whereas I'd like to have it as a separate file.
styles.css
import '../styles.css
styles.css
is included there too.Edit: I created a repo to demonstrate the issue here: https://github.com/amakk/gatsby-global-css-bug
index.js
imports style.css
while page2.js
doesn't import it. Yet, both get the style from style.css
applied.
The CSS imported on one page should only be included into that page, not on other pages.
All pages include the CSS.
System:
OS: macOS 10.14
CPU: (8) x64 Intel(R) Core(TM) i7-4850HQ CPU @ 2.30GHz
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 8.11.3 - /usr/local/bin/node
Yarn: 1.16.0 - /usr/local/bin/yarn
npm: 6.4.1 - /usr/local/bin/npm
Languages:
Python: 2.7.10 - /usr/bin/python
Browsers:
Chrome: 74.0.3729.169
Firefox: 66.0.3
Safari: 12.0
npmPackages:
gatsby: ^2.0.65 => 2.5.5
gatsby-image: ^2.0.23 => 2.1.0
gatsby-plugin-google-tagmanager: ^2.0.7 => 2.0.13
gatsby-plugin-manifest: ^2.0.11 => 2.1.1
gatsby-plugin-offline: ^2.0.19 => 2.1.1
gatsby-plugin-postcss: ^2.0.2 => 2.0.7
gatsby-plugin-react-helmet: ^3.0.4 => 3.0.12
gatsby-plugin-sass: ^2.0.11 => 2.0.11
gatsby-plugin-sharp: ^2.0.15 => 2.0.37
gatsby-plugin-styled-components: ^3.0.4 => 3.0.7
gatsby-plugin-webpack-bundle-analyzer: ^1.0.3 => 1.0.5
gatsby-source-filesystem: ^2.0.12 => 2.0.36
gatsby-transformer-sharp: ^2.1.9 => 2.1.19
npmGlobalPackages:
gatsby-cli: 2.5.15
Hi!
Sorry to hear you're running into an issue. To help us best begin debugging the underlying cause, it is incredibly helpful if you're able to create a minimal reproduction. This is a simplified example of the issue that makes it clear and obvious what the issue is and how we can begin to debug it.
If you're up for it, we'd very much appreciate if you could provide a minimal reproduction and we'll be able to take another look.
Thanks for using Gatsby! 馃挏
Hi @LekoArts, I created a repository to reproduce the issue here: https://github.com/amakk/gatsby-global-css-bug.
index.js
imports style.css
while page2.js
doesn't import it. Yet, both get the style from style.css
applied.
Thanks for your help!
CSS is global by nature. You can fix it by wrapping it with a unique class (.someclass h1), the problem is... It is too long. That is why I love sass, they can do nesting.
A possible solution is to use CSS Modules by installing PostCSS. After installing, you will have to append .module.css
to the file name. (index.css
=> index.module.css
) and import it as usual.
Facing the same issue for multiple layouts using scss.
I have two scss files style1.scss and style2.scss and I have imported style1.scss in layout1.js and style2.scss in layout2.js. But in the DOM for any layout both the scss files are overriding.
Thanks for the suggestions @vinzun and @ImedAdel. Unfortunately, these wouldn't work in my case, mainly for two reasons:
What I'm really after is an equivalent to including an external stylesheet via a link tag (which is how it's done in the current website) that I could add/remove on specific pages. I know I could just put the CSS in a static folder and create a link tag, but some of it is written in SASS and I would also lose out on cache busting.
Any other suggestions?
oh I see. Never used bootstrap before, sorry I can't help you.
Does anyone else have other ideas? Here's what I'm doing for now:
import bootstrap from '!raw-loader!bootstrap/dist/css/bootstrap.min.css'
And then putting it into a style tag:
<Helmet>
<style>{bootstrap}</style>
</Helmet>
But I'm wondering how efficient this is. If I put this in a layout component, will it get re-downloaded on each page navigation? Also, there isn't a way to tell which CSS file the styles are coming from in Chrome inspector.
@LekoArts could you update the status labels of this issue since I've added all needed info and reproduction
@amakk I can't say whether your solution is the best approach, but it's not downloading it on each page navigation, it will get it once as part of the initial JS bundle download and then use that version for subsequent page loads.
Using raw-loader
copies the entire contents of the file to a string at build time and embeds it into the final JS output, so that import
call is equivalent to
// component.js
import bootstrap from './bootstrap.min.css.js';
// bootstrap.min.css.js
export default `
.class1 { /* ... */ }
.class2 { /* ... */ }
// ...
`;
@superhawk610 Thanks, that's good to know. Would appreciate any tips on a better approach.
For smaller scale styles you can make use of CSS Modules as suggested earlier. They'll only be loaded on pages where they're required - you can find more information on using them with Gatsby here.
For your use case, I would recommend writing a separate layout component for each nested site that requires its own stylesheets, then inject the stylesheets using react-helmet and <link rel="stylesheet" />
tags. This way, each stylesheet will only be loaded when the page layout requires it!
If you'd like to discuss further, feel free to open a thread on Spectrum and link to this issue. Best of luck!
@superhawk610 Question about this: Is there a way to do this with gatsby-plugin-sass
? It seems to store the stylesheet with random names so not sure how to use that here
In my case, I am abstracting code into different npm packages and each one of them had a global imported css file
In the main gatsby website, each package was used on different pages, but all global css files were downloaded/injected in all pages (also in those not using the packages at all)
I'm now deciding how to avoid using global css files in the packages, but since I've found this issue I comment this for future readers
@amakk did you manage to find a solution? I am having a similar problem trying to generate sites based on different templates but using the same repository, the CSS problem is the only sho stopper.
Appreciate your feedback!
I've ended up with a bunch of updates to tackle the issue of having isolated templates, is not the best approach I am sure, but I'll share what I have in case it helps somebody:
.theme {
--color-main: red;
.title {
color: var(--color-red);
}
}
import main from main.module.css
<Helmet
bodyAttributes={{ class: main.theme }}
/>
And finally to avoid load the fonts of each template in all the pages, I've created separated CSS font loader files in the static/ gatsby folder. I am loading these fonts using React Helmet as well
```
import main from main.module.css
const fontsPath = 'theme-fonts-folder'
```
Most helpful comment
Facing the same issue for multiple layouts using scss.
I have two scss files style1.scss and style2.scss and I have imported style1.scss in layout1.js and style2.scss in layout2.js. But in the DOM for any layout both the scss files are overriding.