]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Breadcrumbs (#41956)
authorMark Otto <markd.otto@gmail.com>
Mon, 22 Dec 2025 04:57:32 +0000 (20:57 -0800)
committerMark Otto <markdotto@gmail.com>
Fri, 9 Jan 2026 04:14:08 +0000 (20:14 -0800)
* Redo breadcrumb

* Cleanup

scss/_breadcrumb.scss
site/src/content/docs/components/breadcrumb.mdx

index 8808c46f7b32ae4502f689a69b94094cddb40205..1755132cf03039cd740d4ea7fce44dc1e08aa85b 100644 (file)
@@ -3,19 +3,24 @@
 @use "variables" as *;
 @use "functions" as *;
 @use "mixins/border-radius" as *;
+@use "mixins/transition" as *;
 
 // scss-docs-start breadcrumb-variables
 $breadcrumb-font-size:              null !default;
 $breadcrumb-padding-y:              0 !default;
 $breadcrumb-padding-x:              0 !default;
-$breadcrumb-item-padding-x:         .5rem !default;
 $breadcrumb-margin-bottom:          1rem !default;
 $breadcrumb-bg:                     null !default;
-$breadcrumb-divider-color:          var(--secondary-color) !default;
-$breadcrumb-active-color:           var(--secondary-color) !default;
-$breadcrumb-divider:                string.quote("/") !default;
-$breadcrumb-divider-flipped:        $breadcrumb-divider !default;
-$breadcrumb-border-radius:          null !default;
+$breadcrumb-divider-color:          var(--fg-4) !default;
+$breadcrumb-border-radius:          var(--border-radius) !default;
+
+$breadcrumb-link-padding-x:         .75rem !default;
+$breadcrumb-link-padding-y:         .25rem !default;
+$breadcrumb-link-color:             var(--fg-3) !default;
+$breadcrumb-link-hover-color:       var(--fg-2) !default;
+$breadcrumb-link-hover-bg:          var(--bg-1) !default;
+$breadcrumb-link-active-color:      var(--fg-1) !default;
+$breadcrumb-link-border-radius:     var(--border-radius-lg) !default;
 // scss-docs-end breadcrumb-variables
 
 @layer components {
@@ -28,14 +33,19 @@ $breadcrumb-border-radius:          null !default;
     --breadcrumb-bg: #{$breadcrumb-bg};
     --breadcrumb-border-radius: #{$breadcrumb-border-radius};
     --breadcrumb-divider-color: #{$breadcrumb-divider-color};
-    --breadcrumb-item-padding-x: #{$breadcrumb-item-padding-x};
-    --breadcrumb-item-active-color: #{$breadcrumb-active-color};
+    --breadcrumb-link-padding-x: #{$breadcrumb-link-padding-x};
+    --breadcrumb-link-padding-y: #{$breadcrumb-link-padding-y};
+    --breadcrumb-link-color: #{$breadcrumb-link-color};
+    --breadcrumb-link-hover-color: #{$breadcrumb-link-hover-color};
+    --breadcrumb-link-hover-bg: #{$breadcrumb-link-hover-bg};
+    --breadcrumb-link-active-color: #{$breadcrumb-link-active-color};
+    --breadcrumb-link-border-radius: #{$breadcrumb-link-border-radius};
     // scss-docs-end breadcrumb-css-vars
 
     display: flex;
     flex-wrap: wrap;
+    align-items: center;
     padding: var(--breadcrumb-padding-y) var(--breadcrumb-padding-x);
-    margin-bottom: var(--breadcrumb-margin-bottom);
     font-size: var(--breadcrumb-font-size);
     list-style: none;
     background-color: var(--breadcrumb-bg);
@@ -43,24 +53,34 @@ $breadcrumb-border-radius:          null !default;
   }
 
   .breadcrumb-item {
-    // The separator between breadcrumbs (by default, a forward-slash: "/")
-    + .breadcrumb-item {
-      padding-inline-start: var(--breadcrumb-item-padding-x);
+    display: flex;
+  }
 
-      &::before {
-        float: inline-start; // Suppress inline spacings and underlining of the separator
-        padding-inline-end: var(--breadcrumb-item-padding-x);
-        color: var(--breadcrumb-divider-color);
-        content: var(--breadcrumb-divider, escape-svg($breadcrumb-divider));
-      }
-    }
+  .breadcrumb-divider {
+    margin-inline: calc(var(--breadcrumb-link-padding-x) / 4);
+    color: var(--breadcrumb-divider-color);
+  }
+
+  .breadcrumb-link {
+    position: relative;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    min-height: 2.25rem;
+    padding: var(--breadcrumb-link-padding-y) var(--breadcrumb-link-padding-x);
+    color: var(--breadcrumb-link-color);
+    text-decoration: none;
+    @include border-radius(var(--breadcrumb-link-border-radius));
+    @include transition(.1s text-decoration-color ease-in-out);
 
-    [dir="rtl"] &:not(:first-child)::before {
-      content: var(--breadcrumb-divider, escape-svg($breadcrumb-divider-flipped));
+    &:hover {
+      z-index: 2;
+      color: var(--breadcrumb-link-hover-color);
+      background-color: var(--breadcrumb-link-hover-bg);
     }
 
     &.active {
-      color: var(--breadcrumb-item-active-color);
+      color: var(--breadcrumb-link-active-color);
     }
   }
 }
index 4513a5006ffdd28d4a4597793a57bbd935067239..894c610d85b470bf680294ade77e063874f665d7 100644 (file)
 ---
 title: Breadcrumb
-description: Indicate the current page’s location within a navigational hierarchy that automatically adds separators via CSS.
+description: Indicate the current page's location within a navigational hierarchy using explicit divider elements.
 toc: true
 ---
 
 ## Example
 
-Use an ordered or unordered list with linked list items to create a minimally styled breadcrumb. Use our utilities to add additional styles as desired.
+Use an ordered list with `.breadcrumb-item` for each page and `.breadcrumb-divider` elements containing your separator icon. Add `.active` to the `.breadcrumb-link` of the current page.
 
 <Example code={`<nav aria-label="breadcrumb">
     <ol class="breadcrumb">
-      <li class="breadcrumb-item active" aria-current="page">Home</li>
+      <li class="breadcrumb-item">
+        <a class="breadcrumb-link" href="#">Home</a>
+      </li>
+      <li class="breadcrumb-divider">
+        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 16" width="6" height="12"><path d="M2 2l4 6-4 6" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
+      </li>
+      <li class="breadcrumb-item">
+        <a class="breadcrumb-link" href="#">Library</a>
+      </li>
+      <li class="breadcrumb-divider">
+        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 16" width="6" height="12"><path d="M2 2l4 6-4 6" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
+      </li>
+      <li class="breadcrumb-item" aria-current="page">
+        <a class="breadcrumb-link active" href="#">Data</a>
+      </li>
     </ol>
   </nav>
 
   <nav aria-label="breadcrumb">
     <ol class="breadcrumb">
-      <li class="breadcrumb-item"><a href="#">Home</a></li>
-      <li class="breadcrumb-item active" aria-current="page">Library</li>
-    </ol>
-  </nav>
-
-  <nav aria-label="breadcrumb">
-    <ol class="breadcrumb">
-      <li class="breadcrumb-item"><a href="#">Home</a></li>
-      <li class="breadcrumb-item"><a href="#">Library</a></li>
-      <li class="breadcrumb-item active" aria-current="page">Data</li>
+      <li class="breadcrumb-item">
+        <a class="breadcrumb-link" href="#">Home</a>
+      </li>
+      <li class="breadcrumb-divider">
+        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 16" width="6" height="12"><path d="M2 2l4 6-4 6" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
+      </li>
+      <li class="breadcrumb-item">
+        <a class="breadcrumb-link" href="#">
+          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentcolor"><circle cx="2" cy="8" r="2"/><circle cx="8" cy="8" r="2"/><circle cx="14" cy="8" r="2"/></svg>
+        </a>
+      </li>
+      <li class="breadcrumb-divider">
+        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 16" width="6" height="12"><path d="M2 2l4 6-4 6" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
+      </li>
+      <li class="breadcrumb-item">
+        <a class="breadcrumb-link" href="#">Documents</a>
+      </li>
+      <li class="breadcrumb-divider">
+        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 16" width="6" height="12"><path d="M2 2l4 6-4 6" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
+      </li>
+      <li class="breadcrumb-item" aria-current="page">
+        <a class="breadcrumb-link active" href="#">2025</a>
+      </li>
     </ol>
   </nav>`} />
 
 ## Dividers
 
-Dividers are automatically added in CSS through [`::before`](https://developer.mozilla.org/en-US/docs/Web/CSS/::before) and [`content`](https://developer.mozilla.org/en-US/docs/Web/CSS/content). They can be changed by modifying a local CSS custom property `--bs-breadcrumb-divider`, or through the `$breadcrumb-divider` Sass variable — and `$breadcrumb-divider-flipped` for its RTL counterpart, if needed. We default to our Sass variable, which is set as a fallback to the custom property. This way, you get a global divider that you can override without recompiling CSS at any time.
+Dividers are added explicitly using `.breadcrumb-divider` elements. This gives you full control over the separator—use any SVG icon, text character, or custom content.
+
+### SVG dividers
+
+Use inline SVG for crisp, scalable dividers that inherit `currentColor` for easy theming.
 
-<Example code={`<nav style="--bs-breadcrumb-divider: '>';" aria-label="breadcrumb">
+<Example code={`<nav aria-label="breadcrumb">
     <ol class="breadcrumb">
-      <li class="breadcrumb-item"><a href="#">Home</a></li>
-      <li class="breadcrumb-item active" aria-current="page">Library</li>
+      <li class="breadcrumb-item">
+        <a class="breadcrumb-link" href="#">Home</a>
+      </li>
+      <li class="breadcrumb-divider">
+        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 16" width="6" height="12"><path d="M2 2l4 6-4 6" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
+      </li>
+      <li class="breadcrumb-item" aria-current="page">
+        <a class="breadcrumb-link active" href="#">Library</a>
+      </li>
     </ol>
   </nav>`} />
 
-When modifying via Sass, the [quote](https://sass-lang.com/documentation/modules/string/#quote) function is required to generate the quotes around a string. For example, using `>` as the divider, you can use this:
-
-```scss
-$breadcrumb-divider: quote(">");
-```
+### Text dividers
 
-It’s also possible to use an **embedded SVG icon**. Apply it via our CSS custom property, or use the Sass variable.
+For simple text-based dividers, just add the character directly.
 
-<Callout>
-**Inlined SVG requires properly escaped characters.** Some reserved characters, such as `<`, `>` and `#`, must be URL-encoded or escaped. We do this with the `$breadcrumb-divider` variable using our [`escape-svg()` Sass function]([[docsref:/customize/sass#escape-svg]]). When customizing the CSS variable, you must handle this yourself. Read [Kevin Weber’s explanations on CodePen](https://codepen.io/kevinweber/pen/dXWoRw ) for more info.
-</Callout>
-
-<Example code={`<nav style="--bs-breadcrumb-divider: url(&#34;data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='%236c757d'/%3E%3C/svg%3E&#34;);" aria-label="breadcrumb">
+<Example code={`<nav aria-label="breadcrumb">
     <ol class="breadcrumb">
-      <li class="breadcrumb-item"><a href="#">Home</a></li>
-      <li class="breadcrumb-item active" aria-current="page">Library</li>
+      <li class="breadcrumb-item">
+        <a class="breadcrumb-link" href="#">Home</a>
+      </li>
+      <li class="breadcrumb-divider">/</li>
+      <li class="breadcrumb-item">
+        <a class="breadcrumb-link" href="#">Library</a>
+      </li>
+      <li class="breadcrumb-divider">/</li>
+      <li class="breadcrumb-item" aria-current="page">
+        <a class="breadcrumb-link active" href="#">Data</a>
+      </li>
     </ol>
   </nav>`} />
 
-```scss
-$breadcrumb-divider: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='8'><path d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='#{$breadcrumb-divider-color}'/></svg>");
-```
+### Custom dividers
 
-You can also remove the divider setting `--bs-breadcrumb-divider: '';` (empty strings in CSS custom properties counts as a value), or setting the Sass variable to `$breadcrumb-divider: none;`.
+Use any content you like—different icons, decorative elements, or themed separators.
 
-<Example code={`<nav style="--bs-breadcrumb-divider: '';" aria-label="breadcrumb">
+<Example code={`<nav aria-label="breadcrumb">
     <ol class="breadcrumb">
-      <li class="breadcrumb-item"><a href="#">Home</a></li>
-      <li class="breadcrumb-item active" aria-current="page">Library</li>
+      <li class="breadcrumb-item">
+        <a class="breadcrumb-link" href="#">Home</a>
+      </li>
+      <li class="breadcrumb-divider">›</li>
+      <li class="breadcrumb-item">
+        <a class="breadcrumb-link" href="#">Library</a>
+      </li>
+      <li class="breadcrumb-divider">›</li>
+      <li class="breadcrumb-item" aria-current="page">
+        <a class="breadcrumb-link active" href="#">Data</a>
+      </li>
     </ol>
   </nav>`} />
 
-```scss
-$breadcrumb-divider: none;
-```
-
 ## Accessibility
 
-Since breadcrumbs provide a navigation, it’s a good idea to add a meaningful label such as `aria-label="breadcrumb"` to describe the type of navigation provided in the `<nav>` element, as well as applying an `aria-current="page"` to the last item of the set to indicate that it represents the current page.
+Since breadcrumbs provide navigation, it's important to follow these practices:
+
+- Add `aria-label="breadcrumb"` to the `<nav>` element to describe the navigation type
+- Add `aria-current="page"` to the `.breadcrumb-item` containing the current page
+- Divider elements are automatically hidden from assistive technology via CSS
 
 For more information, see the [ARIA Authoring Practices Guide breadcrumb pattern](https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/).