bootstrap: Updated .bg-* and .text-* utilities break when CSS variables are not enabled in v5.1.0

In one of my projects I include the needed Bootstrap SCSS files manually and specifically exclude bootstrap/scss/root, first because I don’t rely on most of the CSS variables and secondly because adding all CSS variables increases the CSS file size by about 50-60kb (uncompressed).

With v5.1.0 all .bg-* and .text-* utilities break, as the needed CSS variables are missing, e.g.

.text-white {
    --bs-text-opacity: 1;
    color: rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important; // --bs-white-rgb is not set
}

Is there a simple way to disable CSS variables generation or to reduce the number of CSS variables? The only way forward right now would be to revert the utility sets back to $theme-colors, but that still leaves an additional --bs-text-opacity: 1; and does not take care of --bs-body-color and the like:

$utilities-text-colors: $theme-colors;
$utilities-bg-colors: $theme-colors;

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 8
  • Comments: 39 (16 by maintainers)

Most upvoted comments

The whole bg-, text- update in 5.1.0 has seemingly complicated the entire process of adding a new theme-color. The only way I could find to get the bg- and text- classes regenerated for the new “custom” theme color is…

@import "functions";
@import "variables";
@import "mixins";

$custom: #df711b;

$custom-theme-colors: (
  "custom": $custom
);

$theme-colors: map-merge($theme-colors, $custom-theme-colors);
$theme-colors-rgb: map-loop($theme-colors, to-rgb, "$value");
$utilities-colors: map-merge($utilities-colors, $theme-colors-rgb);
$utilities-text-colors: map-loop($utilities-colors, rgba-css-var, "$key", "text");
$utilities-bg-colors: map-loop($utilities-colors, rgba-css-var, "$key", "bg");

@import "bootstrap";

I discovered this on an SO question and here’s the working code demo


Whereas in 5.0.2 one could simply follow the example in the docs…

@import "functions";
@import "variables";
@import "mixins";

$custom-colors: (
  "custom-color": #df711b
);

$theme-colors: map-merge($theme-colors, $custom-colors);

The whole bg-, text- update in 5.1.0 has seemingly complicated the entire process of adding a new theme-color. The only way I could find to get the bg- and text- classes regenerated for the new “custom” theme color is…

@import "functions";
@import "variables";
@import "mixins";

Thanks! This really needs to be written in the official documentation!

Left a comment at https://github.com/twbs/bootstrap/issues/34734#issuecomment-916290592, but cross posting here and closing that as a duplicate. Please read and let me know what you all think about that potential solution. Seems like the best path forward to me so far.


After investigating a bit more, I think the best path forward might to split out some of our reassigned Sass maps into a separate _maps.scss file, and import that after the _variables.scss file. This would allow folks to insert new additions to the $theme-colors map that would be reflected in the subsequent maps.

For example:

// Configuration
@import "functions";
@import "variables";

$starorange: #df711b !default;

$custom-theme-colors: (
  "starorange": $starorange
) !default;

$theme-colors: map-merge($theme-colors, $custom-theme-colors); // stylelint-disable-line scss/dollar-variable-default

@import "maps";
@import "mixins";
@import "utilities";

// Layout & components
// ...

Inside _maps.scss would be the Sass maps for $theme-colors-rgb, $utilities-colors, $utilities-text, and $utilities-bg. I tried this locally and it works for me—both button variants and utilities are generated for the custom color.

arrrggghhhh add +1 to frustration of note. this change has had me tearing my hair out.

i sort of got it working with

_variables.scss (my custom variables)

@import "../../../../../node_modules/bootstrap/scss/functions";
@import "../../../../../node_modules/bootstrap/scss/variables";
@import "../../../../../node_modules/bootstrap/scss/mixins";

$colors: (
...
);
$theme-colors: (
...
);
$theme-colors-rgb: map-loop($theme-colors, to-rgb, "$value");
$utilities-colors: map-merge($utilities-colors, $theme-colors-rgb);
$utilities-text-colors: map-loop($utilities-colors, rgba-css-var, "$key", "text");
$utilities-bg-colors: map-loop($utilities-colors, rgba-css-var, "$key", "bg");

....

styles.scss (main style)

@import "./variables";
@import "../../../../../node_modules/bootstrap/scss/bootstrap.scss";
...

at the devs, its changes like this that might actually drive people away tho. would suggest you consider “ability and ease of extending bootstrap” as a core just like getting the code working right. i know people might disagree with this, but this change for instance has some what had me questioning if bootstrap and me remain in a loving relationship or not). 12k lines of css 😦 last i looked it was around 8 or so

Sorry we’ve been slow to investigate and identify a path forward. We’ll need a little more time to experiment and validate the issues identified here. Definitely not in our interest to be causing headaches for folks 😃.

I consider this either a regression or a lack in documentation. Thanks @iatek for the above! Unfortunately it didn’t work for me. What finally worked for me was moving mixins after the merge-map and map-loop, like this:

// CUSTOM COLOURS
@import './variables';

// Configuration
@import "node_modules/bootstrap/scss/functions";
@import "node_modules/bootstrap/scss/variables";

$theme-colors: map-merge($theme-colors, $custom-colours);
$theme-colors-rgb: map-loop($theme-colors, to-rgb, "$value");
$utilities-colors: map-merge($utilities-colors, $theme-colors-rgb);
$utilities-text-colors: map-loop($utilities-colors, rgba-css-var, "$key", "text");
$utilities-bg-colors: map-loop($utilities-colors, rgba-css-var, "$key", "bg");

@import "node_modules/bootstrap/scss/mixins";
@import "node_modules/bootstrap/scss/utilities";
// ... and the rest of boostrap

Should this issue not be fixed in a 5.1.2?

The whole bg-, text- update in 5.1.0 has seemingly complicated the entire process of adding a new theme-color. The only way I could find to get the bg- and text- classes regenerated for the new “custom” theme color is…

@import "functions";
@import "variables";
@import "mixins";

$custom: #df711b;

$custom-theme-colors: (
  "custom": $custom
);

$theme-colors: map-merge($theme-colors, $custom-theme-colors);
$theme-colors-rgb: map-loop($theme-colors, to-rgb, "$value");
$utilities-colors: map-merge($utilities-colors, $theme-colors-rgb);
$utilities-text-colors: map-loop($utilities-colors, rgba-css-var, "$key", "text");
$utilities-bg-colors: map-loop($utilities-colors, rgba-css-var, "$key", "bg");

@import "bootstrap";

I discovered this on an SO question and here’s the working code demo

Whereas in 5.0.2 one could simply follow the example in the docs…

@import "functions";
@import "variables";
@import "mixins";

$custom-colors: (
  "custom-color": #df711b
);

$theme-colors: map-merge($theme-colors, $custom-colors);

This doesn’t work entirely for $utilities-text-colors, you will be missing .text-white etc.

These map-merges inside _utilities.scss and _variables.scss really makes for a mess.

@mdo I think lots of people are missing the whole point of introducing RGBa with opacity CSS var. If i understand correctly, this is needed for new text and background opacity logic. But the same can be achieved with regular opacity-* utilities. If that’s correct, this means we have a bunch of RGB values defined in :root just for setting the opacity. But this doesn’t help to extend color palette, because the suggested method still generates HEX values with opacity CSS var. Why don’t we use HSL and HSLa instead, where we can simply change lightness to generate additional tints/shades of *-500 colors and change alpha to control opacity? A few examples here.

@tomsommer Yes, the same does apply there. I misunderstood your earlier point I think and was only looking to see if spacers are updated if you change the $spacer value. That update does happen, but yes, the reassigned maps do not. I’m checking out the viability of moving those maps to _maps.scss as well.

Yeah, this was definitely a shortcoming of Sass we didn’t fully explore at the time. It’s something we’ll 100% have to revisit in v6, but until then, I want to make sure we consider the best options and ship something that’s functional and as easy to document/explain as possible.

What do folks think of that PR I opened to separate out Sass maps? I might need to include more maps there like $spacers it sounds like, but I’m hoping the principle of it helps. We might also need to smooth out the utilities map merges if the latest comments here are right.

I know @tomsommer, I had to spend a few hours to solve that issue in v5.1.1 and here is what I come up with and it works perfectly.

@import "functions";

// Overwrite your variables
$custom-color1: red !default;
$custom-color2: blue !default;

$min-contrast-ratio: 3;
$link-decoration: none;

// Import the bootstrap variables
@import "variables";

$extra-theme-colors: (
	"gray-dark":   $gray-800,
	"custom-color1": $custom-color1
);

$extra-general-colors: (
	"custom-color2": $custom-color2
);

// Run map-merge() to mer our custom maps with the default Bootstrap maps
$colors: map-remove( $colors, "gray-dark" );
$colors: map-merge( $colors, $extra-general-colors );

$theme-colors: map-merge($theme-colors, $extra-theme-colors );

// ---------- MOST IMPORTANT ---------------
// Extra stuffs we need to do for generating the proper theme color classes (.bg-*, .text-*)
$theme-colors-rgb: map-loop($theme-colors, to-rgb, "$value");

$utilities-text: map-merge($theme-colors, $utilities-text);
$utilities-text-colors: map-loop($utilities-text, rgba-css-var, "$key", "text");

$utilities-bg: map-merge($theme-colors, $utilities-bg);
$utilities-bg-colors: map-loop($utilities-bg, rgba-css-var, "$key", "bg");

// And then continue importing the rest
@import "mixins";
@import "utilities";
// and so on...

This will work. Try and enjoy. 😃 Honestly, I really wish I can go back to the Boostrat v5.0 days without all these complexities around adding own custom colors.

Fun fact: I faced the same text-white issue and then figured this out. 😦

Hehe thanks mdo. I think the 5.1 update took a few people by surprise. Some “breaking” things like this but on the face of it it looks like 5.0 but it’s still a big update.