39 CSS Breadcrumbs13 / 39

Pure CSSMIT licensed

Seamless Arrow-Cutout CSS3 Breadcrumb Trail

The interlocking-chevron breadcrumb built the classic CSS3 way — with ::before/::after triangles made from transparent-border tricks rather than clip-path. Each crumb's arrow is two rotated border-triangles that seamlessly notch into the next, the technique taught in every 'CSS arrow' tutorial, modernised.

Published

Live Demo
Try it

The code

<nav class="bc-13" aria-label="Breadcrumb">
  <ol class="bc-13__list">
    <li class="bc-13__item"><a class="bc-13__link" href="#">Home</a></li>
    <li class="bc-13__item"><a class="bc-13__link" href="#">Catalog</a></li>
    <li class="bc-13__item"><a class="bc-13__link" href="#">Tools</a></li>
    <li class="bc-13__item"><a class="bc-13__link" aria-current="page" href="#">Power Drills</a></li>
  </ol>
</nav>
.bc-13 {
  width: 100%;
  min-height: 100vh;
  --h: 44px;
  --depth: 14px;
  --page: oklch(0.96 0.01 90);
  font-family: system-ui,'Segoe UI',sans-serif;
  padding: 30px;
  background: var(--page);
  display: flex;
  align-items: center;
  justify-content: center;
}

.bc-13 * {
  box-sizing: border-box;
}

.bc-13__list {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}

.bc-13__item {
  display: flex;
  position: relative;
}

.bc-13__item + .bc-13__item {
  margin-inline-start: calc(var(--depth) * -1);
}

.bc-13__link {
  position: relative;
  display: flex;
  align-items: center;
  height: var(--h);
  padding: 0 calc(var(--depth) + 12px) 0 calc(var(--depth) + 12px);
  font: 600 13px/1 system-ui,sans-serif;
  color: #fff;
  text-decoration: none;
  background: oklch(0.58 0.03 90);
  clip-path: polygon(0 0,calc(100% - var(--depth)) 0,100% 50%,calc(100% - var(--depth)) 100%,0 100%,var(--depth) 50%);
  transition: filter .18s ease;
}

.bc-13__item:first-child .bc-13__link {
  clip-path: polygon(0 0,calc(100% - var(--depth)) 0,100% 50%,calc(100% - var(--depth)) 100%,0 100%);
  padding-left: 16px;
}

.bc-13__item:last-child .bc-13__link {
  clip-path: polygon(0 0,100% 0,100% 100%,0 100%,var(--depth) 50%);
  padding-right: 16px;
  background: oklch(0.6 0.18 25);
}

.bc-13__item:first-child:last-child .bc-13__link {
  clip-path: none;
}

.bc-13__item:nth-child(2) .bc-13__link {
  background: oklch(0.52 0.05 60);
}

.bc-13__item:nth-child(3) .bc-13__link {
  background: oklch(0.5 0.07 40);
}

.bc-13__link:hover {
  filter: brightness(1.12);
}

.bc-13__link:focus-visible {
  outline: 3px solid oklch(0.3 0.05 40);
  outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
  .bc-13__link {
    transition: none;
  }
}
/* No JavaScript — arrows are transparent-border triangles (::after in the crumb colour, ::before in the page colour) that notch together seamlessly; the widest-support arrow technique. */
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Breadcrumb from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Seamless Arrow-Cutout CSS3 Breadcrumb Trail
Source: https://codefronts.com/navigation/css-breadcrumbs/seamless-arrow-cutout-css3-breadcrumb-trail/

The interlocking-chevron breadcrumb built the classic CSS3 way — with ::before/::after triangles made from transparent-border tricks rather than clip-path. Each crumb's arrow is two rotated border-triangles that seamlessly notch into the next, the technique taught in every 'CSS arrow' tutorial, modernised.
## HTML
```html
<nav class="bc-13" aria-label="Breadcrumb">
  <ol class="bc-13__list">
    <li class="bc-13__item"><a class="bc-13__link" href="#">Home</a></li>
    <li class="bc-13__item"><a class="bc-13__link" href="#">Catalog</a></li>
    <li class="bc-13__item"><a class="bc-13__link" href="#">Tools</a></li>
    <li class="bc-13__item"><a class="bc-13__link" aria-current="page" href="#">Power Drills</a></li>
  </ol>
</nav>
```
## CSS
```css
.bc-13 {
  width: 100%;
  min-height: 100vh;
  --h: 44px;
  --depth: 14px;
  --page: oklch(0.96 0.01 90);
  font-family: system-ui,'Segoe UI',sans-serif;
  padding: 30px;
  background: var(--page);
  display: flex;
  align-items: center;
  justify-content: center;
}

.bc-13 * {
  box-sizing: border-box;
}

.bc-13__list {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}

.bc-13__item {
  display: flex;
  position: relative;
}

.bc-13__item + .bc-13__item {
  margin-inline-start: calc(var(--depth) * -1);
}

.bc-13__link {
  position: relative;
  display: flex;
  align-items: center;
  height: var(--h);
  padding: 0 calc(var(--depth) + 12px) 0 calc(var(--depth) + 12px);
  font: 600 13px/1 system-ui,sans-serif;
  color: #fff;
  text-decoration: none;
  background: oklch(0.58 0.03 90);
  clip-path: polygon(0 0,calc(100% - var(--depth)) 0,100% 50%,calc(100% - var(--depth)) 100%,0 100%,var(--depth) 50%);
  transition: filter .18s ease;
}

.bc-13__item:first-child .bc-13__link {
  clip-path: polygon(0 0,calc(100% - var(--depth)) 0,100% 50%,calc(100% - var(--depth)) 100%,0 100%);
  padding-left: 16px;
}

.bc-13__item:last-child .bc-13__link {
  clip-path: polygon(0 0,100% 0,100% 100%,0 100%,var(--depth) 50%);
  padding-right: 16px;
  background: oklch(0.6 0.18 25);
}

.bc-13__item:first-child:last-child .bc-13__link {
  clip-path: none;
}

.bc-13__item:nth-child(2) .bc-13__link {
  background: oklch(0.52 0.05 60);
}

.bc-13__item:nth-child(3) .bc-13__link {
  background: oklch(0.5 0.07 40);
}

.bc-13__link:hover {
  filter: brightness(1.12);
}

.bc-13__link:focus-visible {
  outline: 3px solid oklch(0.3 0.05 40);
  outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
  .bc-13__link {
    transition: none;
  }
}
```

## JavaScript
```js
/* No JavaScript — arrows are transparent-border triangles (::after in the crumb colour, ::before in the page colour) that notch together seamlessly; the widest-support arrow technique. */
```

How this works

This is the border-triangle heritage technique, still worth knowing. Each crumb is a rectangle; its right-pointing arrow is an ::after triangle formed by the old transparent-border trick — a zero-size box with a thick border-left in the crumb's colour and transparent top/bottom borders, which renders as a solid triangle pointing right. A matching ::before triangle in the PAGE background colour notches into the crumb's left edge, so consecutive crumbs interlock seamlessly without overlap math.

Because the arrow colour is a real border, the trail's tonal palette flows through the triangles automatically as long as each crumb sets its ::after border-left-color to match its own background. It's more verbose than clip-path (demo 01) but has the widest possible support and no clipping of focus outlines — the ring renders normally around the rectangle. The current crumb takes the accent (and its arrow), and the first crumb's incoming notch is simply omitted for a clean start.

Make it yours

  • Arrow size = the triangle's border widths; keep the vertical borders half the crumb height for a clean 45°-ish point.
  • Palette: set each crumb's background AND its ::after border-left-color together (one variable per crumb) so the arrow always matches.
  • Add a 1px gap-line between crumbs by insetting the notch triangle slightly.
  • Swap to a chevron (outline) look by using two thin rotated bars instead of a filled triangle.

Gotchas — read before shipping

  • The arrow's border-left-color MUST equal the crumb's background, and the incoming notch MUST equal the PAGE background — mismatch and the seam shows.
  • Triangle borders don't scale with content — set the vertical border widths to exactly half the crumb height or the point looks off-centre.
  • This predates clip-path; if you don't need legacy support, demo 01's clip-path is simpler to maintain — pick per your browser floor.
  • Keep the triangles pointer-events:none so the pointed tip doesn't steal clicks from the neighbouring crumb.

Browser support

ChromeSafariFirefoxEdge
111+15.4+113+111+

Floor set by oklch() as this demo is written. The core technique itself goes back further — Chrome all.

The transparent-border triangle trick works in every browser ever shipped — this is the maximum-compatibility arrow breadcrumb. oklch() palette is the only 2023 touch.

Techniques used in this demo

Search CodeFronts

Loading…