]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Remove `!important` from utilities, make it opt-in per utility (#41755)
authorMark Otto <markd.otto@gmail.com>
Mon, 22 Sep 2025 05:12:17 +0000 (22:12 -0700)
committerMark Otto <markdotto@gmail.com>
Fri, 10 Oct 2025 17:03:32 +0000 (10:03 -0700)
* Remove !important from utilities, make it opt-in per utility

* package-lock

* Fix test

package-lock.json
scss/_config.scss
scss/_utilities.scss
scss/_variables.scss
scss/helpers/_color-bg.scss
scss/mixins/_utilities.scss
scss/tests/mixins/_utilities.test.scss
scss/tests/utilities/_api.test.scss
site/src/content/docs/customize/options.mdx
site/src/content/docs/utilities/api.mdx

index 36aadf8239487e029f79e7cde1f347fa2de63a27..ac593702644c7b5928efe9d40d37f7404dea370f 100644 (file)
         "npm": "1.2.8000 || >= 1.4.16"
       }
     },
+    "node_modules/detect-libc": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.0.tgz",
+      "integrity": "sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==",
+      "dev": true,
+      "optional": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/deterministic-object-hash": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz",
index 34c1abb54cb0835353e9f276f8657ade3f6ca7f8..64f07db28e6aa63d576e6a59cf16881097edac0a 100644 (file)
@@ -19,7 +19,6 @@ $enable-rfs:                  true !default;
 $enable-validation-icons:     true !default;
 $enable-negative-margins:     false !default;
 $enable-deprecation-messages: true !default;
-$enable-important-utilities:  false !default;
 
 $enable-dark-mode:            true !default;
 $color-mode-type:             data !default; // `data` or `media-query`
index 607c1da901cb36f7d291cc2076e45e640e226b29..1baeeb77c0137577cfc22e08bd7c7a71fd462cd9 100644 (file)
@@ -95,6 +95,7 @@ $utilities: map.merge(
       print: true,
       property: display,
       class: d,
+      important: true,
       values: inline inline-block block grid inline-grid table table-row table-cell flex inline-flex flow-root none
     ),
     // scss-docs-end utils-display
@@ -121,6 +122,7 @@ $utilities: map.merge(
     // scss-docs-start utils-position
     "position": (
       property: position,
+      important: true,
       values: static relative absolute fixed sticky
     ),
     "top": (
@@ -859,6 +861,7 @@ $utilities: map.merge(
     "visibility": (
       property: visibility,
       class: null,
+      important: true,
       values: (
         visible: visible,
         invisible: hidden,
index a56412b50db641b5d4390755fd7d10f2b411f25d..a0ed0d40a27a0610f3b4faba91fd19a166b3bd30 100644 (file)
@@ -94,7 +94,6 @@ $escaped-characters: (
 // $enable-validation-icons:     true !default;
 // $enable-negative-margins:     false !default;
 // $enable-deprecation-messages: true !default;
-// $enable-important-utilities:  true !default;
 
 // $enable-dark-mode:            true !default;
 // $color-mode-type:             data !default; // `data` or `media-query`
index 8d70151ee18567d0d4f928d8078506814b7308af..d9b1c56e89623a06b323f82bd4cf3ed9fc3efb5c 100644 (file)
@@ -6,8 +6,8 @@
   // All-caps `RGBA()` function used because of this Sass bug: https://github.com/sass/node-sass/issues/2251
   @each $color, $value in $theme-colors {
     .text-bg-#{$color} {
-      color: color-contrast($value) if($enable-important-utilities, !important, null);
-      background-color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}bg-opacity, 1)) if($enable-important-utilities, !important, null);
+      color: color-contrast($value);
+      background-color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}bg-opacity, 1));
     }
   }
 }
index 7202a82312928fa54b89466996fd71a49818c8f7..39d85bc436342ecab527bada5076ada3bdfe5e2f 100644 (file)
@@ -58,6 +58,7 @@
     $is-css-var: map.get($utility, css-var);
     $is-local-vars: map.get($utility, local-vars);
     $is-rtl: map.get($utility, rtl);
+    $is-important: map.get($utility, important);
 
     @if $value != null {
       @if $is-rtl == false {
@@ -82,7 +83,7 @@
                 --#{$prefix}#{$local-var}: #{$variable};
               }
             }
-            #{$property}: $value if($enable-important-utilities, !important, null);
+            #{$property}: $value if($is-important, !important, null);
           }
         }
 
@@ -94,7 +95,7 @@
                   --#{$prefix}#{$local-var}: #{$variable};
                 }
               }
-              #{$property}: $value if($enable-important-utilities, !important, null);
+              #{$property}: $value if($is-important, !important, null);
             }
           }
         }
index 00ce389582de4b0888bf33de177d4186d58774c5..da42501b1d067106c2502b5d755ee6852a88081b 100644 (file)
@@ -6,7 +6,6 @@
 
 $true-terminal-output: false;
 $prefix: bs-;
-$enable-important-utilities: false;
 
 // Important: Do not import rfs to check that the mixin just calls the appropriate functions from it
 // @import "../../mixins/utilities";
@@ -41,13 +40,12 @@ $enable-important-utilities: false;
     }
   }
 
-  @include describe("global $enable-important-utilities: true") {
+  @include describe("per-utility important: true") {
     @include it("sets !important") {
-      $enable-important-utilities: true !global;
-
       @include test-generate-utility(
         (
           property: "padding",
+          important: true,
           values: (small: .5rem, large: 2rem)
         )
       ) {
@@ -59,8 +57,6 @@ $enable-important-utilities: false;
           padding: 2rem !important;
         }
       }
-
-      $enable-important-utilities: false !global;
     }
   }
 
index 304d8d1c942051dcbf3f60f415b7d5d2055e97f1..2b38bb9964cf4b7ba3cce1eb59a5f39593cd6827 100644 (file)
@@ -1,8 +1,7 @@
-@import "../../functions";
-@import "../../variables";
-@import "../../variables-dark";
-@import "../../maps";
-@import "../../mixins";
+@use "../../functions";
+@use "../../variables";
+@use "../../maps";
+@use "../../mixins";
 
 $utilities: ();
 
@@ -11,16 +10,19 @@ $utilities: ();
     $utilities: (
       margin: (
         property: margin,
+        important: true,
         values: auto
       ),
       padding: (
         property: padding,
         responsive: true,
+        important: true,
         values: 1rem
       ),
       font-size: (
         property: font-size,
         values: (large: 1.25rem),
+        important: true,
         print: true
       )
     ) !global;
@@ -33,7 +35,7 @@ $utilities: ();
 
     @include assert() {
       @include output() {
-        @import "../../utilities/api";
+        @use "../../utilities/api";
       }
 
       @include expect() {
@@ -72,4 +74,53 @@ $utilities: ();
 
     }
   }
+
+  @include it("generates utilities without !important when important: false or not set") {
+    $utilities: (
+      opacity: (
+        property: opacity,
+        values: (
+          0: 0,
+          50: .5,
+          100: 1
+        )
+      ),
+      text-align: (
+        property: text-align,
+        important: false,
+        values: (
+          start: left,
+          center: center
+        )
+      )
+    ) !global;
+
+    @include assert() {
+      @include output() {
+        @import "../../utilities/api";
+      }
+
+      @include expect() {
+        .opacity-0 {
+          opacity: 0;
+        }
+
+        .opacity-50 {
+          opacity: .5;
+        }
+
+        .opacity-100 {
+          opacity: 1;
+        }
+
+        .text-align-start {
+          text-align: left;
+        }
+
+        .text-align-center {
+          text-align: center;
+        }
+      }
+    }
+  }
 }
index 926ae03122d92af2b6ef550999552e332a42c1a6..16120e3fda6f3b0bfcfb4c434e6aea3d3416bf04 100644 (file)
@@ -26,6 +26,5 @@ You can find and customize these variables for key global options in Bootstrap
 | `$enable-validation-icons`     | `true` (default) or `false`        | Enables `background-image` icons within textual inputs and some custom forms for validation states. |
 | `$enable-negative-margins`     | `true` or `false` (default)        | Enables the generation of [negative margin utilities]([[docsref:/utilities/spacing#negative-margin]]). |
 | `$enable-deprecation-messages` | `true` (default) or `false`        | Set to `false` to hide warnings when using any of the deprecated mixins and functions that are planned to be removed in `v6`. |
-| `$enable-important-utilities`  | `true` (default) or `false`        | Enables the `!important` suffix in utility classes. |
 | `$enable-smooth-scroll`        | `true` (default) or `false`        | Applies `scroll-behavior: smooth` globally, except for users asking for reduced motion through [`prefers-reduced-motion` media query]([[docsref:/getting-started/accessibility#reduced-motion]]) |
 </BsTable>
index a3a36311700e20897177112a33daa2401b0a84e5..daea7d5bc49d72417d6e940064577fdd11436744 100644 (file)
@@ -13,13 +13,14 @@ The `$utilities` map contains all our utilities and is later merged with your cu
 | Option | Type | Default&nbsp;value | Description |
 | --- | --- | --- | --- |
 | [`property`](#property) | **Required** | – | Name of the property, this can be a string or an array of strings (e.g., horizontal paddings or margins). |
-| [`values`](#values) | **Required** | – | List of values, or a map if you dont want the class name to be the same as the value. If `null` is used as map key, `class` is not prepended to the class name. |
+| [`values`](#values) | **Required** | – | List of values, or a map if you don't want the class name to be the same as the value. If `null` is used as map key, `class` is not prepended to the class name. |
 | [`class`](#class) | Optional | null | Name of the generated class. If not provided and `property` is an array of strings, `class` will default to the first element of the `property` array. If not provided and `property` is a string, the `values` keys are used for the `class` names. |
 | [`css-var`](#css-variable-utilities) | Optional | `false` | Boolean to generate CSS variables instead of CSS rules. |
 | [`css-variable-name`](#css-variable-utilities) | Optional | null | Custom un-prefixed name for the CSS variable inside the ruleset. |
 | [`local-vars`](#local-css-variables) | Optional | null | Map of local CSS variables to generate in addition to the CSS rules. |
 | [`state`](#states) | Optional | null | List of pseudo-class variants (e.g., `:hover` or `:focus`) to generate. |
 | [`responsive`](#responsive) | Optional | `false` | Boolean indicating if responsive classes should be generated. |
+| [`important`](#importance) | Optional | `false` | Boolean indicating if `!important` should be added to the utility's CSS rules. |
 | `rfs` | Optional | `false` | Boolean to enable [fluid rescaling with RFS]([[docsref:/getting-started/rfs]]). |
 | [`print`](#print) | Optional | `false` | Boolean indicating if print classes need to be generated. |
 | `rtl` | Optional | `true` | Boolean indicating if utility should be kept in RTL. |
@@ -360,12 +361,36 @@ Output:
 
 ## Importance
 
-Utilities generated by the API no longer include `!important` by default in v6. This is because we now use CSS layers to ensure utilities override components and modifier classes as intended. You can toggle this setting globally with the `$enable-important-utilities` variable (defaults to `false`).
+Utilities generated by the API no longer include `!important` by default in v6. This is because we now use CSS layers to ensure utilities override components and modifier classes as intended. You can enable `!important` on a per-utility basis by setting the `important` option to `true`.
 
 ```scss
-$enable-important-utilities: true;
+$utilities: (
+  "opacity": (
+    property: opacity,
+    important: true,
+    values: (
+      0: 0,
+      25: .25,
+      50: .5,
+      75: .75,
+      100: 1,
+    )
+  )
+);
+```
+
+This will generate utilities with `!important`:
+
+```css
+.opacity-0 { opacity: 0 !important; }
+.opacity-25 { opacity: .25 !important; }
+.opacity-50 { opacity: .5 !important; }
+.opacity-75 { opacity: .75 !important; }
+.opacity-100 { opacity: 1 !important; }
 ```
 
+Some utilities like `display`, `position`, and `visibility` have `important: true` set by default as they commonly need to override component styles.
+
 ## Using the API
 
 Now that you’re familiar with how the utilities API works, learn how to add your own custom classes and modify our default utilities.