1
0
mirror of https://github.com/twbs/bootstrap.git synced 2025-09-25 12:59:05 +02:00

Remove !important from utilities, make it opt-in per utility (#41755)

* Remove !important from utilities, make it opt-in per utility

* package-lock

* Fix test
This commit is contained in:
Mark Otto
2025-09-21 22:12:17 -07:00
committed by GitHub
parent 21491d1f2f
commit e5a1ee3d3a
10 changed files with 105 additions and 33 deletions

21
package-lock.json generated
View File

@@ -7174,6 +7174,16 @@
"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",
@@ -17109,17 +17119,6 @@
"@img/sharp-win32-x64": "0.34.4"
}
},
"node_modules/sharp/node_modules/detect-libc": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
"dev": true,
"license": "Apache-2.0",
"optional": true,
"engines": {
"node": ">=8"
}
},
"node_modules/sharp/node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",

View 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`

View 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,

View 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`

View 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));
}
}
}

View 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);
}
}
}

View 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;
}
}

View 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;
}
}
}
}
}

View 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>

View 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 youre familiar with how the utilities API works, learn how to add your own custom classes and modify our default utilities.