Skip to content

Commit e72916e

Browse files
committed
Update color and background-color utilities
- Adds new functions to generate additional Sass maps - Adds new root variables for rgb() versions of our theme colors, plus a few extras - Adds ability to change the alpha transparency of text color and background color utilities with new utilities, inline styles, or local CSS var - Updates documentation for color and background-color utilities pages - Deprecates .text-black-50 and .text-white-50 since those (and additional transparency levels) can be generated on the fly Change approach slightly to prevent cascade
1 parent a2f92d1 commit e72916e

File tree

7 files changed

+222
-14
lines changed

7 files changed

+222
-14
lines changed

scss/_functions.scss

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,41 @@
3232
}
3333
}
3434

35+
// Colors
36+
@function to-rgb($value) {
37+
@return red($value), green($value), blue($value);
38+
}
39+
40+
@function rgba-css-var($identifier, $target) {
41+
@return rgba(var(--#{$variable-prefix}#{$identifier}-rgb), var(--#{$variable-prefix}#{$target}-opacity));
42+
}
43+
44+
// stylelint-disable scss/dollar-variable-pattern
45+
@function map-loop($map, $func, $args...) {
46+
$_map: ();
47+
48+
@each $key, $value in $map {
49+
// allow to pass the $key and $value of the map as an function argument
50+
$_args: ();
51+
@each $arg in $args {
52+
$_args: append($_args, if($arg == "$key", $key, if($arg == "$value", $value, $arg)));
53+
}
54+
55+
$_map: map-merge($_map, ($key: call(get-function($func), $_args...)));
56+
}
57+
58+
@return $_map;
59+
}
60+
// stylelint-enable scss/dollar-variable-pattern
61+
62+
@function varify($list) {
63+
$result: null;
64+
@each $entry in $list {
65+
$result: append($result, var(--#{$variable-prefix}#{$entry}), space);
66+
}
67+
@return $result;
68+
}
69+
3570
// Internal Bootstrap function to turn maps into its negative variant.
3671
// It prefixes the keys with `n` and makes the value negative.
3772
@function negativify-map($map) {

scss/_root.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88
--#{$variable-prefix}#{$color}: #{$value};
99
}
1010

11+
@each $color, $value in $theme-colors-rgb {
12+
--#{$variable-prefix}#{$color}-rgb: #{$value};
13+
}
14+
15+
--#{$variable-prefix}white-rgb: #{to-rgb($white)};
16+
--#{$variable-prefix}black-rgb: #{to-rgb($black)};
17+
--#{$variable-prefix}body-rgb: #{to-rgb($body-color)};
18+
1119
// Use `inspect` for lists so that quoted items keep the quotes.
1220
// See https://github.com/sass/sass/issues/2383#issuecomment-336349172
1321
--#{$variable-prefix}font-sans-serif: #{inspect($font-family-sans-serif)};

scss/_utilities.scss

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -514,32 +514,55 @@ $utilities: map-merge(
514514
"color": (
515515
property: color,
516516
class: text,
517+
local-vars: (
518+
"text-opacity": 1
519+
),
517520
values: map-merge(
518-
$theme-colors,
521+
$utilities-text-colors,
519522
(
520-
"white": $white,
521-
"body": $body-color,
522523
"muted": $text-muted,
523-
"black-50": rgba($black, .5),
524-
"white-50": rgba($white, .5),
524+
"black-50": rgba($black, .5), // deprecated
525+
"white-50": rgba($white, .5), // deprecated
525526
"reset": inherit,
526527
)
527528
)
528529
),
530+
"text-opacity": (
531+
css-var: true,
532+
class: text-opacity,
533+
values: (
534+
25: .25,
535+
50: .5,
536+
75: .75,
537+
100: 1
538+
)
539+
),
529540
// scss-docs-end utils-color
530541
// scss-docs-start utils-bg-color
531542
"background-color": (
532543
property: background-color,
533544
class: bg,
545+
local-vars: (
546+
"bg-opacity": 1
547+
),
534548
values: map-merge(
535-
$theme-colors,
549+
$utilities-bg-colors,
536550
(
537-
"body": $body-bg,
538-
"white": $white,
539551
"transparent": transparent
540552
)
541553
)
542554
),
555+
"bg-opacity": (
556+
css-var: true,
557+
class: bg-opacity,
558+
values: (
559+
10: .1,
560+
25: .25,
561+
50: .5,
562+
75: .75,
563+
100: 1
564+
)
565+
),
543566
// scss-docs-end utils-bg-color
544567
"gradient": (
545568
property: background-image,

scss/_variables.scss

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ $theme-colors: (
9090
) !default;
9191
// scss-docs-end theme-colors-map
9292

93+
// scss-docs-start theme-colors-rgb
94+
$theme-colors-rgb: map-loop($theme-colors, to-rgb, "$value") !default;
95+
// scss-docs-end theme-colors-rgb
96+
9397
// The contrast ratio to reach against white, to determine if color changes from "light" to "dark". Acceptable values for WCAG 2.0 are 3, 4.5 and 7.
9498
// See https://www.w3.org/TR/WCAG20/#visual-audio-contrast-contrast
9599
$min-contrast-ratio: 4.5 !default;
@@ -401,6 +405,28 @@ $body-bg: $white !default;
401405
$body-color: $gray-900 !default;
402406
$body-text-align: null !default;
403407

408+
// Utilities maps
409+
//
410+
// Extends the default `$theme-colors` maps to help create our utilities.
411+
412+
// scss-docs-start utilities-colors
413+
$utilities-colors: map-merge(
414+
$theme-colors-rgb,
415+
(
416+
"black": to-rgb($black),
417+
"white": to-rgb($white),
418+
"body": to-rgb($body-color)
419+
)
420+
) !default;
421+
// scss-docs-end utilities-colors
422+
423+
// scss-docs-start utilities-text-colors
424+
$utilities-text-colors: map-loop($utilities-colors, rgba-css-var, "$key", "text") !default;
425+
// scss-docs-end utilities-text-colors
426+
427+
// scss-docs-start utilities-bg-colors
428+
$utilities-bg-colors: map-loop($utilities-colors, rgba-css-var, "$key", "bg") !default;
429+
// scss-docs-end utilities-bg-colors
404430

405431
// Links
406432
//

scss/mixins/_utilities.scss

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,25 +41,46 @@
4141
}
4242
}
4343

44+
$is-css-var: map-get($utility, css-var);
45+
$is-local-vars: map-get($utility, local-vars);
4446
$is-rtl: map-get($utility, rtl);
4547

4648
@if $value != null {
4749
@if $is-rtl == false {
4850
/* rtl:begin:remove */
4951
}
50-
.#{$property-class + $infix + $property-class-modifier} {
51-
@each $property in $properties {
52-
#{$property}: $value if($enable-important-utilities, !important, null);
52+
53+
@if $is-css-var {
54+
.#{$property-class + $infix + $property-class-modifier} {
55+
--#{$variable-prefix}#{$property-class}: #{$value};
5356
}
54-
}
5557

56-
@each $pseudo in $state {
57-
.#{$property-class + $infix + $property-class-modifier}-#{$pseudo}:#{$pseudo} {
58+
@each $pseudo in $state {
59+
.#{$property-class + $infix + $property-class-modifier}-#{$pseudo}:#{$pseudo} {
60+
--#{$variable-prefix}#{$property-class}: #{$value};
61+
}
62+
}
63+
} @else {
64+
.#{$property-class + $infix + $property-class-modifier} {
5865
@each $property in $properties {
66+
@if $is-local-vars {
67+
@each $local-var, $value in $is-local-vars {
68+
--#{$variable-prefix}#{$local-var}: #{$value};
69+
}
70+
}
5971
#{$property}: $value if($enable-important-utilities, !important, null);
6072
}
6173
}
74+
75+
@each $pseudo in $state {
76+
.#{$property-class + $infix + $property-class-modifier}-#{$pseudo}:#{$pseudo} {
77+
@each $property in $properties {
78+
#{$property}: $value if($enable-important-utilities, !important, null);
79+
}
80+
}
81+
}
6282
}
83+
6384
@if $is-rtl == false {
6485
/* rtl:end:remove */
6586
}

site/content/docs/5.0/utilities/background.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,44 @@ Do you need a gradient in your custom CSS? Just add `background-image: var(--bs-
3535
{{< /colors.inline >}}
3636
{{< /markdown >}}
3737

38+
## Opacity
39+
40+
<small class="d-inline-flex px-2 py-1 font-monospace text-muted border rounded-3">Added in v5.1.0</small>
41+
42+
As of v5.1.0, `background-color` utilities are generated with Sass using CSS variables. This allows for real-time color changes without compilation and dynamic alpha transparency changes.
43+
44+
### How it works
45+
46+
Consider our default `.bg-success` utility.
47+
48+
```css
49+
.bg-success {
50+
--bs-bg-opacity: 1;
51+
background-color: rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important;
52+
}
53+
```
54+
55+
We use an RGB version of our `--bs-succes` (with the value of `25, 135, 84`) CSS variable and attached a second CSS variable, `--bs-bg-opacity`, for the alpha transparency (with no default value, but a fallback of `1`). That means anytime you use `.bg-success` now, your computed `color` value is `rgba(25, 135, 84, 1)`.
56+
57+
### Example
58+
59+
To change that opacity, override `--bs-bg-opacity` via custom styles or inline styles.
60+
61+
{{< example >}}
62+
<div class="bg-success p-2 text-white">This is default success background</div>
63+
<div class="bg-success p-2" style="--bs-bg-opacity: .5;">This is 50% opacity success background</div>
64+
{{< /example >}}
65+
66+
Or, choose from any of the `.bg-opacity` utilities:
67+
68+
{{< example >}}
69+
<div class="bg-success p-2 text-white">This is default success background</div>
70+
<div class="bg-success p-2 text-white bg-opacity-75">This is 75% opacity success background</div>
71+
<div class="bg-success p-2 text-dark bg-opacity-50">This is 50% opacity success background</div>
72+
<div class="bg-success p-2 text-dark bg-opacity-25">This is 25% opacity success background</div>
73+
<div class="bg-success p-2 text-dark bg-opacity-10">This is 10% opacity success background</div>
74+
{{< /example >}}
75+
3876
## Sass
3977

4078
In addition to the following Sass functionality, consider reading about our included [CSS custom properties]({{< docsref "/customize/css-variables" >}}) (aka CSS variables) for colors and more.
@@ -63,6 +101,14 @@ Grayscale colors are also available as a Sass map. **This map is not used to gen
63101

64102
{{< scss-docs name="gray-colors-map" file="scss/_variables.scss" >}}
65103

104+
RGB colors are generated from a separate Sass map:
105+
106+
{{< scss-docs name="theme-colors-rgb" file="scss/_variables.scss" >}}
107+
108+
And background color opacities build on that with their own map that's consumed by the utilities API:
109+
110+
{{< scss-docs name="utilities-bg-colors" file="scss/_variables.scss" >}}
111+
66112
### Mixins
67113

68114
**No mixins are used to generate our background utilities**, but we do have some additional mixins for other situations where you'd like to create your own gradients.

site/content/docs/5.0/utilities/colors.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,51 @@ Colorize text with color utilities. If you want to colorize links, you can use t
2323
<p class="text-white-50 bg-dark">.text-white-50</p>
2424
{{< /example >}}
2525

26+
{{< callout warning >}}
27+
**Deprecation:** With the addition of `.text-opacity-*` utilities and CSS variables for text utilities, `.text-black-50` and `.text-white-50` are deprecated as of v5.1.0. They'll be removed in v6.0.0.
28+
{{< /callout >}}
29+
2630
{{< callout info >}}
2731
{{< partial "callout-warning-color-assistive-technologies.md" >}}
2832
{{< /callout >}}
2933

34+
## Opacity
35+
36+
<small class="d-inline-flex px-2 py-1 font-monospace text-muted border rounded-3">Added in v5.1.0</small>
37+
38+
As of v5.1.0, text color utilities are generated with Sass using CSS variables. This allows for real-time color changes without compilation and dynamic alpha transparency changes.
39+
40+
### How it works
41+
42+
Consider our default `.text-primary` utility.
43+
44+
```css
45+
.text-primary {
46+
--bs-text-opacity: 1;
47+
color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important;
48+
}
49+
```
50+
51+
We use an RGB version of our `--bs-primary` (with the value of `13, 110, 253`) CSS variable and attached a second CSS variable, `--bs-text-opacity`, for the alpha transparency (with no default value, but a fallback of `1`). That means anytime you use `.text-primary` now, your computed `color` value is `rgba(13, 110, 253, 1)`.
52+
53+
### Example
54+
55+
To change that opacity, override `--bs-text-opacity` via custom styles or inline styles.
56+
57+
{{< example >}}
58+
<div class="text-primary">This is default primary text</div>
59+
<div class="text-primary" style="--bs-text-opacity: .5;">This is 50% opacity primary text</div>
60+
{{< /example >}}
61+
62+
Or, choose from any of the `.text-opacity` utilities:
63+
64+
{{< example >}}
65+
<div class="text-primary">This is default primary text</div>
66+
<div class="text-primary text-opacity-75">This is 75% opacity primary text</div>
67+
<div class="text-primary text-opacity-50">This is 50% opacity primary text</div>
68+
<div class="text-primary text-opacity-25">This is 25% opacity primary text</div>
69+
{{< /example >}}
70+
3071
## Specificity
3172

3273
Sometimes contextual classes cannot be applied due to the specificity of another selector. In some cases, a sufficient workaround is to wrap your element's content in a `<div>` or more semantic element with the desired class.
@@ -57,6 +98,14 @@ Grayscale colors are also available as a Sass map. **This map is not used to gen
5798

5899
{{< scss-docs name="gray-colors-map" file="scss/_variables.scss" >}}
59100

101+
RGB colors are generated from a separate Sass map:
102+
103+
{{< scss-docs name="theme-colors-rgb" file="scss/_variables.scss" >}}
104+
105+
And color opacities build on that with their own map that's consumed by the utilities API:
106+
107+
{{< scss-docs name="utilities-text-colors" file="scss/_variables.scss" >}}
108+
60109
### Utilities API
61110

62111
Color utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]({{< docsref "/utilities/api#using-the-api" >}})

0 commit comments

Comments
 (0)