diff --git a/.bundlewatch.config.json b/.bundlewatch.config.json index 94396f15c7..cc16c47b78 100644 --- a/.bundlewatch.config.json +++ b/.bundlewatch.config.json @@ -18,19 +18,19 @@ }, { "path": "./dist/css/bootstrap-utilities.css", - "maxSize": "10.75 kB" + "maxSize": "11.5 kB" }, { "path": "./dist/css/bootstrap-utilities.min.css", - "maxSize": "10.0 kB" + "maxSize": "10.75 kB" }, { "path": "./dist/css/bootstrap.css", - "maxSize": "31.5 kB" + "maxSize": "32.0 kB" }, { "path": "./dist/css/bootstrap.min.css", - "maxSize": "29.5 kB" + "maxSize": "30.0 kB" }, { "path": "./dist/js/bootstrap.bundle.js", diff --git a/scss/_helpers.scss b/scss/_helpers.scss index 6126781cde..13f2752c9b 100644 --- a/scss/_helpers.scss +++ b/scss/_helpers.scss @@ -2,6 +2,7 @@ @import "helpers/color-bg"; @import "helpers/colored-links"; @import "helpers/focus-ring"; +@import "helpers/icon-link"; @import "helpers/ratio"; @import "helpers/position"; @import "helpers/stacks"; diff --git a/scss/_maps.scss b/scss/_maps.scss index 6418a3f6c0..9a5cc96b6a 100644 --- a/scss/_maps.scss +++ b/scss/_maps.scss @@ -116,6 +116,8 @@ $utilities-border-subtle: ( ) !default; // scss-docs-end utilities-border-colors +$utilities-links-underline: map-loop($utilities-colors, rgba-css-var, "$key", "link-underline") !default; + $negative-spacers: if($enable-negative-margins, negativify-map($spacers), null) !default; $gutters: $spacers !default; diff --git a/scss/_utilities.scss b/scss/_utilities.scss index 5134688e90..d017d117f1 100644 --- a/scss/_utilities.scss +++ b/scss/_utilities.scss @@ -609,6 +609,56 @@ $utilities: map-merge( values: $utilities-text-emphasis-colors ), // scss-docs-end utils-color + // scss-docs-start utils-links + "link-opacity": ( + css-var: true, + class: link-opacity, + state: hover, + values: ( + 10: .1, + 25: .25, + 50: .5, + 75: .75, + 100: 1 + ) + ), + "link-offset": ( + property: text-underline-offset, + class: link-offset, + state: hover, + values: ( + 1: .125em, + 2: .25em, + 3: .375em, + ) + ), + "link-underline": ( + // css-var: true, + property: text-decoration-color, + class: link-underline, + local-vars: ( + "link-underline-opacity": 1 + ), + values: map-merge( + $utilities-links-underline, + ( + null: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-underline-opacity, 1)), + ) + ) + ), + "link-underline-opacity": ( + css-var: true, + class: link-underline-opacity, + state: hover, + values: ( + 10: .1, + 25: .25, + 50: .5, + 75: .75, + 100: 1 + ), + ), + // scss-docs-end utils-links // scss-docs-start utils-bg-color "background-color": ( property: background-color, diff --git a/scss/helpers/_colored-links.scss b/scss/helpers/_colored-links.scss index 0e03039bbf..06c8ce4120 100644 --- a/scss/helpers/_colored-links.scss +++ b/scss/helpers/_colored-links.scss @@ -1,11 +1,17 @@ +// stylelint-disable function-name-case + +// All-caps `RGBA()` function used because of this Sass bug: https://github.com/sass/node-sass/issues/2251 @each $color, $value in $theme-colors { .link-#{$color} { - color: $value if($enable-important-utilities, !important, null); + --#{$prefix}link-color-rgb: #{to-rgb($value)}; + text-decoration-color: RGBA(to-rgb($value), var(--#{$prefix}link-underline-opacity, 1)); @if $link-shade-percentage != 0 { &:hover, &:focus { - color: if(color-contrast($value) == $color-contrast-light, shade-color($value, $link-shade-percentage), tint-color($value, $link-shade-percentage)) if($enable-important-utilities, !important, null); + $hover-color: if(color-contrast($value) == $color-contrast-light, shade-color($value, $link-shade-percentage), tint-color($value, $link-shade-percentage)); + --#{$prefix}link-color-rgb: #{to-rgb($hover-color)}; + text-decoration-color: RGBA(to-rgb($hover-color), var(--#{$prefix}link-underline-opacity, 1)); } } } diff --git a/scss/helpers/_icon-link.scss b/scss/helpers/_icon-link.scss new file mode 100644 index 0000000000..712dd02c72 --- /dev/null +++ b/scss/helpers/_icon-link.scss @@ -0,0 +1,24 @@ +.icon-link { + display: inline-flex; + gap: .375rem; + align-items: center; + text-decoration-color: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-opacity, .5)); + text-underline-offset: .5rem; + backface-visibility: hidden; + + > .bi { + flex-shrink: 0; + width: 1em; + height: 1em; + @include transition(.2s ease-in-out transform); + } +} + +.icon-link-hover { + &:hover, + &:focus-visible { + > .bi { + transform: var(--#{$prefix}icon-link-transform, translate3d(.25em, 0, 0)); + } + } +} diff --git a/site/assets/scss/_content.scss b/site/assets/scss/_content.scss index 14b8b93fe1..126ec9f882 100644 --- a/site/assets/scss/_content.scss +++ b/site/assets/scss/_content.scss @@ -124,26 +124,6 @@ fill: currentcolor; } -.icon-link { - display: flex; - align-items: center; - text-decoration-color: rgba($primary, .5); - text-underline-offset: .5rem; - backface-visibility: hidden; - - .bi { - width: 1.5em; - height: 1.5em; - transition: .2s ease-in-out transform; // stylelint-disable-line property-disallowed-list - } - - &:hover { - .bi { - transform: translate3d(5px, 0, 0); - } - } -} - .border-lg-start { @include media-breakpoint-up(lg) { border-left: var(--bs-border-width) solid var(--bs-border-color); diff --git a/site/content/docs/5.3/examples/features/features.css b/site/content/docs/5.3/examples/features/features.css index b5d658f6b4..debc263647 100644 --- a/site/content/docs/5.3/examples/features/features.css +++ b/site/content/docs/5.3/examples/features/features.css @@ -4,16 +4,6 @@ border-radius: .75rem; } -.icon-link > .bi { - margin-top: .125rem; - margin-left: .125rem; - fill: currentcolor; - transition: transform .25s ease-in-out; -} -.icon-link:hover > .bi { - transform: translate(.25rem); -} - .icon-square { width: 3rem; height: 3rem; diff --git a/site/content/docs/5.3/examples/features/index.html b/site/content/docs/5.3/examples/features/index.html index 35a4ef5da0..a60a98b33b 100644 --- a/site/content/docs/5.3/examples/features/index.html +++ b/site/content/docs/5.3/examples/features/index.html @@ -76,9 +76,9 @@ body_class: ""

Featured title

Paragraph of text beneath the heading to explain the heading. We'll add onto it with another sentence and probably just keep going until we run out of words.

- + Call to action - +
@@ -87,9 +87,9 @@ body_class: ""

Featured title

Paragraph of text beneath the heading to explain the heading. We'll add onto it with another sentence and probably just keep going until we run out of words.

- + Call to action - +
@@ -98,9 +98,9 @@ body_class: ""

Featured title

Paragraph of text beneath the heading to explain the heading. We'll add onto it with another sentence and probably just keep going until we run out of words.

- + Call to action - + diff --git a/site/content/docs/5.3/helpers/colored-links.md b/site/content/docs/5.3/helpers/colored-links.md index e940196ff8..9cdd0fad0f 100644 --- a/site/content/docs/5.3/helpers/colored-links.md +++ b/site/content/docs/5.3/helpers/colored-links.md @@ -3,19 +3,35 @@ layout: docs title: Colored links description: Colored links with hover states group: helpers -toc: false +toc: true --- -You can use the `.link-*` classes to colorize links. Unlike the [`.text-*` classes]({{< docsref "/utilities/colors" >}}), these classes have a `:hover` and `:focus` state. +## Link colors + +You can use the `.link-*` classes to colorize links. Unlike the [`.text-*` classes]({{< docsref "/utilities/colors" >}}), these classes have a `:hover` and `:focus` state. Some of the link styles use a relatively light foreground color, and should only be used on a dark background in order to have sufficient contrast. {{< example >}} {{< colored-links.inline >}} {{- range (index $.Site.Data "theme-colors") }} -{{ .name | title }} link +

{{ .name | title }} link

{{- end -}} {{< /colored-links.inline >}} {{< /example >}} {{< callout info >}} -Some of the link styles use a relatively light foreground color, and should only be used on a dark background in order to have sufficient contrast. +{{< partial "callouts/warning-color-assistive-technologies.md" >}} {{< /callout >}} + +## Link utilities + +{{< added-in "5.3.0" >}} + +Colored links can also be modified by our [link utilities]({{< docsref "/utilities/link/" >}}). + +{{< example >}} +{{< colored-links.inline >}} +{{- range (index $.Site.Data "theme-colors") }} +

{{ .name | title }} link

+{{- end -}} +{{< /colored-links.inline >}} +{{< /example >}} diff --git a/site/content/docs/5.3/helpers/icon-link.md b/site/content/docs/5.3/helpers/icon-link.md new file mode 100644 index 0000000000..66b2036bbf --- /dev/null +++ b/site/content/docs/5.3/helpers/icon-link.md @@ -0,0 +1,66 @@ +--- +layout: docs +title: Icon link +description: Quickly create stylized hyperlinks with Bootstrap Icons or other icons. +group: helpers +aliases: "/docs/5.3/icon-link/" +toc: true +added: 5.3 +--- + +The icon link helper component modifies our default link styles to enhance their appearance and quickly align any pairing of icon and text. Alignment is set via inline flexbox styling and a default `gap` value. We stylize the underline with a custom offset and color. Icons are automatically sized to `1em` to best match their associated text's `font-size`. + +Icon links assume [Bootstrap Icons](https://icons.getbootstrap.com) are being used, but you can use any icon or image you like. + +{{< callout >}} +Icons used here are likely to be purely decorative, which means they should be hidden from assistive technologies using `aria-hidden="true"`, as we've done in our examples. For icons that are more than decorative, provide an appropriate text alternative via `alt` for `` elements `role="img"` and `aria-label` for SVGs. +{{< /callout >}} + +## Example + +Take a regular `` element, add `.icon-link`, and insert an icon on either the left or right of your link text. The icon is automatically sized, placed, and colored. + +{{< example >}} + + + Icon link + +{{< /example >}} + +{{< example >}} + + Icon link + + +{{< /example >}} + +## Style on hover + +Add `.icon-link-hover` to move the icon to the right on hover. + +{{< example >}} + + Icon link + + +{{< /example >}} + +Customize the hover `transform` by overriding the `--bs-icon-link-transform` CSS variable: + +{{< example >}} + + + Icon link + +{{< /example >}} + +## Pairs with link utilities + +Modify icon links with any of [our link utilities]({{< docsref "/utilities/link/" >}}) for modifying underline color and offset. + +{{< example >}} + + Icon link + + +{{< /example >}} diff --git a/site/content/docs/5.3/utilities/link.md b/site/content/docs/5.3/utilities/link.md new file mode 100644 index 0000000000..3b98daa869 --- /dev/null +++ b/site/content/docs/5.3/utilities/link.md @@ -0,0 +1,103 @@ +--- +layout: docs +title: Link +description: Link utilities are used to stylize your anchors to adjust their color, opacity, underline offset, underline color, and more. +group: utilities +toc: true +added: 5.3 +--- + +## Link opacity + +Change the alpha opacity of the link `rgba()` color value with utilities. Please be aware that changes to a color's opacity can lead to links with [*insufficient* contrast]({{< docsref "getting-started/accessibility#color-contrast" >}}). + +{{< example >}} +

Link opacity 10

+

Link opacity 25

+

Link opacity 50

+

Link opacity 75

+

Link opacity 100

+{{< /example >}} + +You can even change the opacity level on hover. + +{{< example >}} +

Link hover opacity 10

+

Link hover opacity 25

+

Link hover opacity 50

+

Link hover opacity 75

+

Link hover opacity 100

+{{< /example >}} + +## Link underlines + +### Underline color + +Change the underline's color independent of the link text color. + +{{< example >}} +{{< link-underline-colors.inline >}} +{{- range (index $.Site.Data "theme-colors") }} +

{{ .name | title }} underline

+{{- end -}} +{{< /link-underline-colors.inline >}} +{{< /example >}} + +### Underline offset + +Change the underline's distance from your text. Offset is set in `em` units to automatically scale with the element's current `font-size`. + +{{< example >}} +

Default link

+

Offset 1 link

+

Offset 2 link

+

Offset 3 link

+{{< /example >}} + +### Underline opacity + +Change the underline's opacity. Requires adding `.link-underline` to first set an `rgba()` color we use to then modify the alpha opacity. + +{{< example >}} +

Underline opacity 10

+

Underline opacity 25

+

Underline opacity 50

+

Underline opacity 75

+

Underline opacity 100

+{{< /example >}} + +### Hover variants + +Just like the `.link-opacity-*-hover` utilities, `.link-offset` and `.link-underline-opacity` utilities include `:hover` variants by default. Mix and match to create unique link styles. + +{{< example >}} + + Underline opacity 10 + +{{< /example >}} + +## Colored links + +[Colored link helpers]({{< docsref "/helpers/colored-links/" >}}) have been updated to pair with our link utilities. Use the new utilities to modify the link opacity, underline opacity, and underline offset. + +{{< example >}} +{{< colored-links.inline >}} +{{- range (index $.Site.Data "theme-colors") }} +

{{ .name | title }} link

+{{- end -}} +{{< /colored-links.inline >}} +{{< /example >}} + +{{< callout info >}} +{{< partial "callouts/warning-color-assistive-technologies.md" >}} +{{< /callout >}} + +## Sass + +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. + +### Utilities API + +Link utilities are declared in our utilities API in `scss/_utilities.scss`. [Learn how to use the utilities API.]({{< docsref "/utilities/api#using-the-api" >}}) + +{{< scss-docs name="utils-links" file="scss/_utilities.scss" >}} diff --git a/site/data/sidebar.yml b/site/data/sidebar.yml index b1d567e990..dea26b401a 100644 --- a/site/data/sidebar.yml +++ b/site/data/sidebar.yml @@ -105,6 +105,7 @@ - title: Color & background - title: Colored links - title: Focus ring + - title: Icon link - title: Position - title: Ratio - title: Stacks @@ -125,6 +126,7 @@ - title: Flex - title: Float - title: Interactions + - title: Link - title: Object fit - title: Opacity - title: Overflow diff --git a/site/layouts/partials/home/components-utilities.html b/site/layouts/partials/home/components-utilities.html index 6806a24b7b..e4c253d334 100644 --- a/site/layouts/partials/home/components-utilities.html +++ b/site/layouts/partials/home/components-utilities.html @@ -53,9 +53,9 @@ `) "html" "" }}

- + Explore customized components - +

@@ -78,9 +78,9 @@ $utilities: map-merge( `) "scss" "" }}

- + Explore the utility API - +

diff --git a/site/layouts/partials/home/css-variables.html b/site/layouts/partials/home/css-variables.html index 3006947496..96a48287b7 100644 --- a/site/layouts/partials/home/css-variables.html +++ b/site/layouts/partials/home/css-variables.html @@ -8,9 +8,9 @@ Bootstrap 5 is evolving with each release to better utilize CSS variables for global theme styles, individual components, and even utilities. We provide dozens of variables for colors, font styles, and more at a :root level for use anywhere. On components and utilities, CSS variables are scoped to the relevant class and can easily be modified.

- + Learn more about CSS variables - +

diff --git a/site/layouts/partials/home/customize.html b/site/layouts/partials/home/customize.html index 365b524c44..c38243dc25 100644 --- a/site/layouts/partials/home/customize.html +++ b/site/layouts/partials/home/customize.html @@ -7,9 +7,9 @@ Bootstrap utilizes Sass for a modular and customizable architecture. Import only the components you need, enable global options like gradients and shadows, and write your own CSS with our variables, maps, functions, and mixins.

- + Learn more about customizing - +

diff --git a/site/layouts/partials/home/get-started.html b/site/layouts/partials/home/get-started.html index 2c3270450f..58ddb99961 100644 --- a/site/layouts/partials/home/get-started.html +++ b/site/layouts/partials/home/get-started.html @@ -7,9 +7,9 @@ Jump right into building with Bootstrap—use the CDN, install it via package manager, or download the source code.

- + Read installation docs - +

diff --git a/site/layouts/partials/home/icons.html b/site/layouts/partials/home/icons.html index c6219b072e..5cc7f14173 100644 --- a/site/layouts/partials/home/icons.html +++ b/site/layouts/partials/home/icons.html @@ -8,9 +8,9 @@ Bootstrap Icons is an open source SVG icon library featuring over 1,800 glyphs, with more added every release. They're designed to work in any project, whether you use Bootstrap itself or not. Use them as SVGs or icon fonts—both options give you vector scaling and easy customization via CSS.

- + Get Bootstrap Icons - +

diff --git a/site/layouts/partials/home/plugins.html b/site/layouts/partials/home/plugins.html index b76fe65399..a2634b18c1 100644 --- a/site/layouts/partials/home/plugins.html +++ b/site/layouts/partials/home/plugins.html @@ -8,9 +8,9 @@ Add toggleable hidden elements, modals and offcanvas menus, popovers and tooltips, and so much more—all without jQuery. Bootstrap's JavaScript is HTML-first, meaning most plugins are added with data attributes in your HTML. Need more control? Include individual plugins programmatically.

- + Learn more about Bootstrap JavaScript - +

diff --git a/site/layouts/partials/home/themes.html b/site/layouts/partials/home/themes.html index e832f2c637..3e286f2671 100644 --- a/site/layouts/partials/home/themes.html +++ b/site/layouts/partials/home/themes.html @@ -8,9 +8,9 @@ Take Bootstrap to the next level with premium themes from the official Bootstrap Themes marketplace. Themes are built on Bootstrap as their own extended frameworks, rich with new components and plugins, documentation, and powerful build tools.

- + Browse Bootstrap Themes - +

diff --git a/site/layouts/partials/icons.html b/site/layouts/partials/icons.html index 9d078f9e71..ddf7f1d516 100644 --- a/site/layouts/partials/icons.html +++ b/site/layouts/partials/icons.html @@ -1,4 +1,7 @@ + + +