Skip to content

Commit 2e75ec3

Browse files
committed
Convert popovers to CSS variables
1 parent 9131248 commit 2e75ec3

File tree

5 files changed

+147
-65
lines changed

5 files changed

+147
-65
lines changed

scss/_popover.scss

Lines changed: 82 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,50 @@
1+
// stylelint-disable custom-property-empty-line-before
2+
13
.popover {
4+
// scss-docs-start popover-css-vars
5+
--#{$variable-prefix}popover-zindex: #{$zindex-popover};
6+
--#{$variable-prefix}popover-max-width: #{$popover-max-width};
7+
@include rfs($popover-font-size, --#{$variable-prefix}popover-font-size);
8+
--#{$variable-prefix}popover-bg: #{$popover-bg};
9+
--#{$variable-prefix}popover-border-width: #{$popover-border-width};
10+
--#{$variable-prefix}popover-border-color: #{$popover-border-color};
11+
--#{$variable-prefix}popover-border-radius: #{$popover-border-radius};
12+
--#{$variable-prefix}popover-box-shadow: #{$popover-box-shadow};
13+
--#{$variable-prefix}popover-header-padding-x: #{$popover-header-padding-x};
14+
--#{$variable-prefix}popover-header-padding-y: #{$popover-header-padding-y};
15+
--#{$variable-prefix}popover-header-color: #{$popover-header-color};
16+
--#{$variable-prefix}popover-header-bg: #{$popover-header-bg};
17+
--#{$variable-prefix}popover-body-padding-x: #{$popover-body-padding-x};
18+
--#{$variable-prefix}popover-body-padding-y: #{$popover-body-padding-y};
19+
--#{$variable-prefix}popover-body-color: #{$popover-body-color};
20+
--#{$variable-prefix}popover-arrow-width: #{$popover-arrow-width};
21+
--#{$variable-prefix}popover-arrow-height: #{$popover-arrow-height};
22+
--#{$variable-prefix}popover-arrow-border: var(--#{$variable-prefix}popover-border-color);
23+
// scss-docs-end popover-css-vars
24+
225
position: absolute;
326
top: 0;
427
left: 0 #{"/* rtl:ignore */"};
5-
z-index: $zindex-popover;
28+
z-index: var(--#{$variable-prefix}popover-zindex);
629
display: block;
7-
max-width: $popover-max-width;
30+
max-width: var(--#{$variable-prefix}popover-max-width);
831
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
932
// So reset our font and text properties to avoid inheriting weird values.
1033
@include reset-text();
11-
@include font-size($popover-font-size);
34+
font-size: var(--#{$variable-prefix}popover-font-size);
1235
// Allow breaking very long words so they don't overflow the popover's bounds
1336
word-wrap: break-word;
14-
background-color: $popover-bg;
37+
background-color: var(--#{$variable-prefix}popover-bg);
1538
background-clip: padding-box;
16-
border: $popover-border-width solid $popover-border-color;
17-
@include border-radius($popover-border-radius);
18-
@include box-shadow($popover-box-shadow);
39+
border: var(--#{$variable-prefix}popover-border-width) solid var(--#{$variable-prefix}popover-border-color);
40+
@include border-radius(var(--#{$variable-prefix}popover-border-radius));
41+
@include box-shadow(var(--#{$variable-prefix}popover-box-shadow));
1942

2043
.popover-arrow {
2144
position: absolute;
2245
display: block;
23-
width: $popover-arrow-width;
24-
height: $popover-arrow-height;
46+
width: var(--#{$variable-prefix}popover-arrow-width);
47+
height: var(--#{$variable-prefix}popover-arrow-height);
2548

2649
&::before,
2750
&::after {
@@ -30,45 +53,52 @@
3053
content: "";
3154
border-color: transparent;
3255
border-style: solid;
56+
border-width: 0;
3357
}
3458
}
3559
}
3660

3761
.bs-popover-top {
3862
> .popover-arrow {
39-
bottom: subtract(-$popover-arrow-height, $popover-border-width);
63+
bottom: calc((var(--#{$variable-prefix}popover-arrow-height)) * -1); // stylelint-disable-line function-disallowed-list
64+
65+
&::before,
66+
&::after {
67+
border-width: var(--#{$variable-prefix}popover-arrow-height) calc(var(--#{$variable-prefix}popover-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
68+
}
4069

4170
&::before {
4271
bottom: 0;
43-
border-width: $popover-arrow-height ($popover-arrow-width * .5) 0;
44-
border-top-color: $popover-arrow-outer-color;
72+
border-top-color: var(--#{$variable-prefix}popover-arrow-border);
4573
}
4674

4775
&::after {
48-
bottom: $popover-border-width;
49-
border-width: $popover-arrow-height ($popover-arrow-width * .5) 0;
50-
border-top-color: $popover-arrow-color;
76+
bottom: var(--#{$variable-prefix}popover-border-width);
77+
border-top-color: var(--#{$variable-prefix}popover-bg);
5178
}
5279
}
5380
}
5481

5582
/* rtl:begin:ignore */
5683
.bs-popover-end {
5784
> .popover-arrow {
58-
left: subtract(-$popover-arrow-height, $popover-border-width);
59-
width: $popover-arrow-height;
60-
height: $popover-arrow-width;
85+
left: calc((var(--#{$variable-prefix}popover-arrow-height)) * -1); // stylelint-disable-line function-disallowed-list
86+
width: var(--#{$variable-prefix}popover-arrow-height);
87+
height: var(--#{$variable-prefix}popover-arrow-width);
88+
89+
&::before,
90+
&::after {
91+
border-width: calc(var(--#{$variable-prefix}popover-arrow-width) * .5) var(--#{$variable-prefix}popover-arrow-height) calc(var(--#{$variable-prefix}popover-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
92+
}
6193

6294
&::before {
6395
left: 0;
64-
border-width: ($popover-arrow-width * .5) $popover-arrow-height ($popover-arrow-width * .5) 0;
65-
border-right-color: $popover-arrow-outer-color;
96+
border-right-color: var(--#{$variable-prefix}popover-arrow-border);
6697
}
6798

6899
&::after {
69-
left: $popover-border-width;
70-
border-width: ($popover-arrow-width * .5) $popover-arrow-height ($popover-arrow-width * .5) 0;
71-
border-right-color: $popover-arrow-color;
100+
left: var(--#{$variable-prefix}popover-border-width);
101+
border-right-color: var(--#{$variable-prefix}popover-bg);
72102
}
73103
}
74104
}
@@ -77,18 +107,21 @@
77107

78108
.bs-popover-bottom {
79109
> .popover-arrow {
80-
top: subtract(-$popover-arrow-height, $popover-border-width);
110+
top: calc((var(--#{$variable-prefix}popover-arrow-height)) * -1); // stylelint-disable-line function-disallowed-list
111+
112+
&::before,
113+
&::after {
114+
border-width: 0 calc(var(--#{$variable-prefix}popover-arrow-width) * .5) var(--#{$variable-prefix}popover-arrow-height); // stylelint-disable-line function-disallowed-list
115+
}
81116

82117
&::before {
83118
top: 0;
84-
border-width: 0 ($popover-arrow-width * .5) $popover-arrow-height ($popover-arrow-width * .5);
85-
border-bottom-color: $popover-arrow-outer-color;
119+
border-bottom-color: var(--#{$variable-prefix}popover-arrow-border);
86120
}
87121

88122
&::after {
89-
top: $popover-border-width;
90-
border-width: 0 ($popover-arrow-width * .5) $popover-arrow-height ($popover-arrow-width * .5);
91-
border-bottom-color: $popover-arrow-color;
123+
top: var(--#{$variable-prefix}popover-border-width);
124+
border-bottom-color: var(--#{$variable-prefix}popover-bg);
92125
}
93126
}
94127

@@ -98,30 +131,33 @@
98131
top: 0;
99132
left: 50%;
100133
display: block;
101-
width: $popover-arrow-width;
102-
margin-left: -$popover-arrow-width * .5;
134+
width: var(--#{$variable-prefix}popover-arrow-width);
135+
margin-left: calc(var(--#{$variable-prefix}popover-arrow-width) * -.5); // stylelint-disable-line function-disallowed-list
103136
content: "";
104-
border-bottom: $popover-border-width solid $popover-header-bg;
137+
border-bottom: var(--#{$variable-prefix}popover-border-width) solid var(--#{$variable-prefix}popover-header-bg);
105138
}
106139
}
107140

108141
/* rtl:begin:ignore */
109142
.bs-popover-start {
110143
> .popover-arrow {
111-
right: subtract(-$popover-arrow-height, $popover-border-width);
112-
width: $popover-arrow-height;
113-
height: $popover-arrow-width;
144+
right: calc((var(--#{$variable-prefix}popover-arrow-height)) * -1); // stylelint-disable-line function-disallowed-list
145+
width: var(--#{$variable-prefix}popover-arrow-height);
146+
height: var(--#{$variable-prefix}popover-arrow-width);
147+
148+
&::before,
149+
&::after {
150+
border-width: calc(var(--#{$variable-prefix}popover-arrow-width) * .5) 0 calc(var(--#{$variable-prefix}popover-arrow-width) * .5) var(--#{$variable-prefix}popover-arrow-height); // stylelint-disable-line function-disallowed-list
151+
}
114152

115153
&::before {
116154
right: 0;
117-
border-width: ($popover-arrow-width * .5) 0 ($popover-arrow-width * .5) $popover-arrow-height;
118-
border-left-color: $popover-arrow-outer-color;
155+
border-left-color: var(--#{$variable-prefix}popover-arrow-border);
119156
}
120157

121158
&::after {
122-
right: $popover-border-width;
123-
border-width: ($popover-arrow-width * .5) 0 ($popover-arrow-width * .5) $popover-arrow-height;
124-
border-left-color: $popover-arrow-color;
159+
right: var(--#{$variable-prefix}popover-border-width);
160+
border-left-color: var(--#{$variable-prefix}popover-bg);
125161
}
126162
}
127163
}
@@ -145,12 +181,12 @@
145181

146182
// Offset the popover to account for the popover arrow
147183
.popover-header {
148-
padding: $popover-header-padding-y $popover-header-padding-x;
184+
padding: var(--#{$variable-prefix}popover-header-padding-y) var(--#{$variable-prefix}popover-header-padding-x);
149185
margin-bottom: 0; // Reset the default from Reboot
150186
@include font-size($font-size-base);
151-
color: $popover-header-color;
152-
background-color: $popover-header-bg;
153-
border-bottom: $popover-border-width solid $popover-border-color;
187+
color: var(--#{$variable-prefix}popover-header-color);
188+
background-color: var(--#{$variable-prefix}popover-header-bg);
189+
border-bottom: var(--#{$variable-prefix}popover-border-width) solid var(--#{$variable-prefix}popover-border-color);
154190
@include border-top-radius($popover-inner-border-radius);
155191

156192
&:empty {
@@ -159,6 +195,6 @@
159195
}
160196

161197
.popover-body {
162-
padding: $popover-body-padding-y $popover-body-padding-x;
163-
color: $popover-body-color;
198+
padding: var(--#{$variable-prefix}popover-body-padding-y) var(--#{$variable-prefix}popover-body-padding-x);
199+
color: var(--#{$variable-prefix}popover-body-color);
164200
}

scss/_tooltip.scss

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// stylelint-disable custom-property-empty-line-before
2+
13
// Base class
24
.tooltip {
35
// scss-docs-start tooltip-css-vars
@@ -6,7 +8,7 @@
68
--#{$variable-prefix}tooltip-padding-x: #{$tooltip-padding-x};
79
--#{$variable-prefix}tooltip-padding-y: #{$tooltip-padding-y};
810
--#{$variable-prefix}tooltip-margin: #{$tooltip-margin};
9-
--#{$variable-prefix}tooltip-font-size: #{$tooltip-font-size};
11+
@include rfs($tooltip-font-size, --#{$variable-prefix}tooltip-font-size);
1012
--#{$variable-prefix}tooltip-color: #{$tooltip-color};
1113
--#{$variable-prefix}tooltip-bg: #{$tooltip-bg};
1214
--#{$variable-prefix}tooltip-border-radius: #{$tooltip-border-radius};

scss/_variables.scss

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,7 +1295,7 @@ $tooltip-margin: 0 !default;
12951295
$tooltip-arrow-width: .8rem !default;
12961296
$tooltip-arrow-height: .4rem !default;
12971297
// fusv-disable
1298-
$tooltip-arrow-color: null !default; // Deprecated in v5.2.0 for CSS variables
1298+
$tooltip-arrow-color: null !default; // Deprecated in Bootstrap 5.2.0 for CSS variables
12991299
// fusv-enable
13001300
// scss-docs-end tooltip-variables
13011301

@@ -1333,10 +1333,13 @@ $popover-body-padding-x: $spacer !default;
13331333

13341334
$popover-arrow-width: 1rem !default;
13351335
$popover-arrow-height: .5rem !default;
1336-
$popover-arrow-color: $popover-bg !default;
1336+
// scss-docs-end popover-variables
13371337

1338+
// fusv-disable
1339+
// Deprecated in Bootstrap 5.2.0 for CSS variables
1340+
$popover-arrow-color: $popover-bg !default;
13381341
$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;
1339-
// scss-docs-end popover-variables
1342+
// fusv-enable
13401343

13411344

13421345
// Toasts

site/assets/scss/_component-examples.scss

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,17 @@
243243
--bs-tooltip-bg: var(--bs-primary);
244244
}
245245

246+
// scss-docs-start custom-popovers
247+
.custom-popover {
248+
--bs-popover-max-width: 200px;
249+
--bs-popover-border-color: var(--bs-primary);
250+
--bs-popover-header-bg: var(--bs-primary);
251+
--bs-popover-header-color: var(--bs-white);
252+
--bs-popover-body-padding-x: 1rem;
253+
--bs-popover-body-padding-y: .5rem;
254+
}
255+
// scss-docs-end custom-popovers
256+
246257
// Scrollspy demo on fixed height div
247258
.scrollspy-example {
248259
position: relative;

site/content/docs/5.1/components/popovers.md

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ toc: true
1010

1111
Things to know when using the popover plugin:
1212

13-
- Popovers rely on the 3rd party library [Popper](https://popper.js.org/) for positioning. You must include [popper.min.js]({{< param "cdn.popper" >}}) before bootstrap.js or use `bootstrap.bundle.min.js` / `bootstrap.bundle.js` which contains Popper in order for popovers to work!
13+
- Popovers rely on the third party library [Popper](https://popper.js.org/) for positioning. You must include [popper.min.js]({{< param "cdn.popper" >}}) before `bootstrap.js`, or use one `bootstrap.bundle.min.js` which contains Popper.
1414
- Popovers require the [tooltip plugin]({{< docsref "/components/tooltips" >}}) as a dependency.
1515
- Popovers are opt-in for performance reasons, so **you must initialize them yourself**.
1616
- Zero-length `title` and `content` values will never show a popover.
@@ -31,9 +31,11 @@ Things to know when using the popover plugin:
3131

3232
Keep reading to see how popovers work with some examples.
3333

34-
## Example: Enable popovers everywhere
34+
## Examples
3535

36-
One way to initialize all popovers on a page would be to select them by their `data-bs-toggle` attribute:
36+
### Enable popovers
37+
38+
As mentioned above, you must initialize popovers before they can be used. One way to initialize all popovers on a page would be to select them by their `data-bs-toggle` attribute, like so:
3739

3840
```js
3941
var popoverTriggerList = Array.prototype.slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
@@ -42,25 +44,17 @@ var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
4244
})
4345
```
4446

45-
## Example: Using the `container` option
46-
47-
When you have some styles on a parent element that interfere with a popover, you'll want to specify a custom `container` so that the popover's HTML appears within that element instead.
48-
49-
```js
50-
var popover = new bootstrap.Popover(document.querySelector('.example-popover'), {
51-
container: 'body'
52-
})
53-
```
47+
### Live demo
5448

55-
## Example
49+
We use JavaScript similar to the snippet above to render the following live popover. Titles are set via `title` attribute and body content is set via `data-bs-content`.
5650

5751
{{< example >}}
5852
<button type="button" class="btn btn-lg btn-danger" data-bs-toggle="popover" title="Popover title" data-bs-content="And here's some amazing content. It's very engaging. Right?">Click to toggle popover</button>
5953
{{< /example >}}
6054

6155
### Four directions
6256

63-
Four options are available: top, right, bottom, and left aligned. Directions are mirrored when using Bootstrap in RTL.
57+
Four options are available: top, right, bottom, and left. Directions are mirrored when using Bootstrap in RTL. Set `data-bs-placement` to change the direction.
6458

6559
{{< example >}}
6660
<button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" data-bs-content="Top popover">
@@ -77,6 +71,34 @@ Four options are available: top, right, bottom, and left aligned. Directions are
7771
</button>
7872
{{< /example >}}
7973

74+
### Custom `container`
75+
76+
When you have some styles on a parent element that interfere with a popover, you'll want to specify a custom `container` so that the popover's HTML appears within that element instead. This is common in responsive tables, input groups, and the like.
77+
78+
```js
79+
var popover = new bootstrap.Popover(document.querySelector('.example-popover'), {
80+
container: 'body'
81+
})
82+
```
83+
84+
### Custom popovers
85+
86+
<small class="d-inline-flex px-2 py-1 font-monospace text-muted border rounded-3">Added in v5.2.0</small>
87+
88+
You can customize the appearance of popovers using [CSS variables](#variables). We set a custom class with `data-bs-custom-class="custom-popover"` to scope our custom appearance and use it to override some of the local CSS variables.
89+
90+
{{< scss-docs name="custom-popovers" file="site/assets/scss/_component-examples.scss" >}}
91+
92+
{{< example class="custom-popover-demo" >}}
93+
<button type="button" class="btn btn-secondary"
94+
data-bs-toggle="popover" data-bs-placement="right"
95+
data-bs-custom-class="custom-popover"
96+
title="Custom popover"
97+
data-bs-content="This popover is themed via CSS variables.">
98+
Custom popover
99+
</button>
100+
{{< /example >}}
101+
80102
### Dismiss on next click
81103

82104
Use the `focus` trigger to dismiss popovers on the user's next click of a different element than the toggle element.
@@ -109,10 +131,18 @@ For disabled popover triggers, you may also prefer `data-bs-trigger="hover focus
109131
</span>
110132
{{< /example >}}
111133

112-
## Sass
134+
## CSS
113135

114136
### Variables
115137

138+
<small class="d-inline-flex px-2 py-1 font-monospace text-muted border rounded-3">Added in v5.2.0</small>
139+
140+
As part of Bootstrap’s evolving CSS variables approach, popovers now use local CSS variables on `.popover` for enhanced real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too.
141+
142+
{{< scss-docs name="popover-css-vars" file="scss/_popover.scss" >}}
143+
144+
### Sass variables
145+
116146
{{< scss-docs name="popover-variables" file="scss/_variables.scss" >}}
117147

118148
## Usage

0 commit comments

Comments
 (0)