Mounting Bootstrap from NPM broke SCSS variable overrides

In my theme, I used to check in Bootstrap files manually under /assets/paige/bootstrap. The “dist” CSS and JS files, individual JS files, and SCSS files were all in that directory. By default, my theme would minimize and fingerprint /assets/paige/bootstrap/bootstrap.css.

There was a site parameter for customizing the primary Bootstrap color. According to this Stack Overflow answer, you just have to set the SCSS variable $primary before importing bootstrap.scss:

$primary: purple;
@import "bootstrap";

I had a /assets/paige/bootstrap/custom.scss file that did just this, except it was parameterized with a site config value:

$primary: {{ .Param "paige.color" | default "#0d6efd" }};
@import "bootstrap";

This worked great, even with libsass. So, if paige.color was unset, then /assets/paige/bootstrap/bootstrap.css was used; if it was set, then /assets/paige/bootstrap/custom.scss was used.

Then I noticed that the size of my repo was getting too large. I wanted to keep Bootstrap out of the repo, but have it available for building. I switched to declaring a Bootstrap dependency in package.json:

{
  "comments": {
    "dependencies": {
      "bootstrap": "project",
      "bootstrap-icons": "project",
      "katex": "project"
    },
    "devDependencies": {}
  },
  "dependencies": {
    "bootstrap": "^5.3.0-alpha1",
    "bootstrap-icons": "^1.10.3",
    "katex": "^0.16.4"
  },
  "devDependencies": {}
}

I created a package.hugo.json:

{
  "dependencies": {
    "bootstrap": "^5.3.0-alpha1",
    "bootstrap-icons": "^1.10.3",
    "katex": "^0.16.4"
  }
}

I mounted Bootstrap files into /assets/paige/bootstrap in config.yaml:

module:
  hugoVersion:
    min: "0.101.0"
    extended: true
  mounts:
  # Default mounts
  - source: "archetypes"
    target: "archetypes"
  - source: "assets"
    target: "assets"
  - source: "content"
    target: "content"
  - source: "data"
    target: "data"
  - source: "i18n"
    target: "i18n"
  - source: "layouts"
    target: "layouts"
  - source: "static"
    target: "static"
  # Bootstrap
  - source: "node_modules/bootstrap/dist/css"
    target: "assets/paige/bootstrap"
    includeFiles: ["/bootstrap.css"]
  - source: "node_modules/bootstrap/dist/js"
    target: "assets/paige/bootstrap"
    includeFiles: ["/bootstrap.bundle.js"]
  - source: "node_modules/bootstrap/js/dist"
    target: "static/paige/bootstrap"
  - source: "node_modules/bootstrap/scss"
    target: "static/paige/bootstrap"
  # Bootstrap Icons
  - source: "node_modules/bootstrap-icons/font/fonts"
    target: "static/paige/bootstrap-icons/fonts"
  - source: "node_modules/bootstrap-icons/font"
    target: "assets/paige/bootstrap-icons"
    includeFiles: ["/bootstrap-icons.css"]
  # Katex
  - source: "node_modules/katex/contrib/auto-render"
    target: "assets/paige/katex"
    includeFiles: ["/auto-render.js"]
  - source: "node_modules/katex/dist/fonts"
    target: "static/paige/katex/fonts"
  - source: "node_modules/katex/dist"
    target: "assets/paige/katex"
    includeFiles: ["/katex.css", "/katex.js"]

This all seemed to work. The Bootstrap CSS was loading and rendering as before. Great!

Fast forward to today: I noticed that if I set paige.color, nothing happens. Using binary search, I determined that it was the commit that made the above changes (mounting, etc.) that broke it.

At first, it was a “TOCSS” error about not finding “bootstrap”, if I remember correctly. Through trial and error, I figured it might be an issue with libsass, and I should switch to dartsass. I did that, and the first error went away, and the site built without errors.

However, the color is unchanged.

I checked the HTML, and the custom file is indeed being transpiled:

<link crossorigin="anonymous" href="/paige/bootstrap/custom.min.a0c9268bba8796b8f41a578eded55c047b6b2e9d7cd1b2d5b845bc474a2f669b.css" integrity="sha256-oMkmi7qHlrj0GleO3tVcBHtrLp180bLVuEW8R0ovZps=" referrerpolicy="no-referrer" rel="stylesheet">

However, the primary color appears to be unchanged (set to #ff0000):

    --bs-primary: #0d6efd;

Even if you hard-code it in custom.scss:

$primary: #ff0000;
@import "bootstrap";

Adding a little test to make sure the variable is working:

$primary: #ff0000;
.wjf { color: $primary; }
@import "bootstrap";

has the expected result:

.wjf {
    color: red
}
/*!* Bootstrap v5.3.0-alpha1 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)*/

:root, [data-bs-theme=light] {

except --bs-primary is still unaffected:

    --bs-primary: #0d6efd;

So I’m left wondering: How has mounting Bootstrap resulted in Bootstrap variable overrides no longer working? And how can I get it working again?

Thanks for reading.

Edit: Hugo info:

$ hugo env
hugo v0.111.1+extended darwin/amd64 BuildDate=unknown
GOOS="darwin"
GOARCH="amd64"
GOVERSION="go1.20.1"
github.com/sass/libsass="3.6.5"
github.com/webmproject/libwebp="v1.2.4"
github.com/sass/dart-sass-embedded/protocol="1.2.0"
github.com/sass/dart-sass-embedded/compiler="1.58.3"
github.com/sass/dart-sass-embedded/implementation="1.58.3"

Links:

Didn’t take a close look into this, but you’re importing the pre-built Bootstrap CSS (The SCSS have been transformed to CSS already) instead of SCSS, so the SCSS variables won’t work.

The Bootstrap SCSS files are located in node_modules/bootstrap/scss.

// config.yaml
module:
  mounts:
    // ...
    - source: "node_modules/bootstrap/scss"
    target: "assets/paige/bootstrap"
    # includeFiles: ["/bootstrap.css"]

You’ll need to adjust the following code as well, since there is not paige/bootstrap/bootstrap.css imported.

{{ if $page.Param "paige.color" }}
    {{ partial "paige/link.html" (dict "href" "paige/bootstrap/custom.scss" "page" $page "sass" true) }}
{{ else }}
    {{ partial "paige/link.html" (dict "href" "paige/bootstrap/bootstrap.css") }}
{{ end }}

Preview:

// config.yaml
params:
  paige:
    color: red

image

I did not read your whole conversation, but as far as I understand, adding Bootstrap as a Hugo module did break your site. The explanation for this is that Bootstrap is also using Hugo for its website, and the configuration for the Hugo site of Bootstrap might “seep through” to your site’s configuration. Check out the docs for configuring modules and disable the config of Bootstrap in your module like this:

[module]
[[module.imports]]
ignoreConfig = true
path = 'your bootstrap module path'

I might be wrong, but I had this exact issue on all my Bootstrap driven sites.

PS: I just read that every single response to your post said something along the lines of “didn’t read all of it”. Sorry for that :] I promise to read all responses to my tip :wink:

@razon You were close! It turned out I mounted the Bootstrap SCSS files into /static instead of /assets. All I had to do was fix that, and it worked.

--- a/config.yaml
+++ b/config.yaml
@@ -28,7 +28,7 @@ module:
   - source: "node_modules/bootstrap/js/dist"
     target: "static/paige/bootstrap"
   - source: "node_modules/bootstrap/scss"
-    target: "static/paige/bootstrap"
+    target: "assets/paige/bootstrap"
   # Bootstrap Icons
   - source: "node_modules/bootstrap-icons/font/fonts"
     target: "static/paige/bootstrap-icons/fonts"

The @import in custom.scss must have resolved to bootstrap.css, since bootstrap.scss didn’t exist.

Thank you and @davidsneighbour for your help!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.