SecretoCho
menu

component 03 / 28WORKINGfeatured

SC Breadcrumb

type
Code Component
platform
Framer
last update
read time
5–6 min
license
SecretoCho Design
needs JavaScript

demo · runs with JavaScript

fig 00 · live demo, ported from SC_Breadcrumb.tsx

Builds an accessible breadcrumb trail from URL segments with configurable separators/alignment and emits JSON-LD (BreadcrumbList/optional BlogPosting) for SEO.

SC Breadcrumb builds a clean, responsive breadcrumb trail from the current URL, with configurable separator, max items (auto-ellipsis), alignment, and typography. It can also output schema.org JSON-LD for SEO (BreadcrumbList + optional BlogPosting), with empty-field cleanup for tidy markup.

  • Navigation
  • SEO

Main

Overview

Built With
React, CSS, Framer Code Component API
Layout Support
Fully Responsive (any width/height)
Orientation
Inline nav trail
Ideal Use Case
Page trails, article nav, SEO-friendly navigation

Tags

  • breadcrumb
  • navigation
  • seo
  • schema.org
  • json-ld
  • accessibility

Code comment

/** * SC Breadcrumb * Dynamic breadcrumb trail + optional schema.org JSON-LD. * © SecretoCho Design – Aug 2025 * @framerDisableUnlink * @framerSupportedLayoutWidth any * @framerSupportedLayoutHeight any */

Dependencies

Technologies
None (pure React + DOM)
Notes
No runtime libraries required; works with Framer’s standard runtime.

Complexity

Logic Level
Low–Medium (path parsing + schema build)
Runtime Cost
Very Low (simple text/links)
Component Size
~2–3 KB (raw TSX)
Notes
JSON-LD injection is static; no reflow cost after render.

Guide

Instructions

  1. Drop SCBreadcrumb into your page header area.
  2. Set Separator (e.g., /, ›, →).
  3. Choose Max Items (older items collapse to …).
  4. Pick Alignment (Left/Center/Right).
  5. (Optional) Style with the Font, Color, Hover controls.
  6. (Optional) Enable SEO: fill Breadcrumb Name/Slug/Root and/or Blog fields to emit JSON-LD.

Examples / Presets

  • Classic

    separator
    "/"
    maxItems
    3
    color
    #555
    hover
    #0A7
  • Chevrons

    separator="›" · maxItems=4 · center

  • Minimal

    separator="•" · maxItems=2 · right

Mechanics

How it Works

  • Path parsing: window.location.pathname → /a/b/c → ['a','b','c'].
  • Formatting: formatTitle() decodes URI, swaps -/_ with spaces, Title-Cases words.
  • Overflow: If segments.length > maxItems, prepend … and keep the last maxItems segments.
  • Link building: Each non-last crumb links to its cumulative absolute URL (origin + /a/...).
  • Schema:
    • BreadcrumbList uses Root → Name/Slug → (optional) Headline.
    • BlogPosting uses blog fields (author/publisher/logo/image/dates).
    • cleanObject() removes empty strings/arrays/objects before JSON-LD injection.

Performance & Tuning

  • Text-only render; virtually zero layout cost.
  • Avoid extremely long labels; rely on maxItems to keep trails short.
  • Hover color changes are GPU-friendly; transition is limited to color.

Compatibility & Limits

  • Requires window.location (client render). For SSR, outputs a safe fallback (/) until hydrated.
  • JSON-LD is appended via <script type="application/ld+json">; safe in all evergreen browsers.
  • Ellipsis crumb … is non-interactive by design.

Quality

Accessibility

  • Use inside a <nav aria-label="Breadcrumb"> region when possible.
  • Last item should not be a link; mark it as the current page (aria-current="page" if wrapped in an anchor).
  • Separators are decorative—render as text with aria-hidden="true" or CSS ::before.

Security & Privacy

  • No network calls or storage.
  • JSON-LD strings are serialized, not executed; still ensure values come from trusted sources (avoid piping untrusted user input directly).
  • Uses window.location only; no cookies or tracking.
  • Small surface area; no global listeners.

Reference

Props

nametypedefaultdescription
fontFont{"Inter",400,"1rem"}Typography for items
colorstring#555Link/label color
hoverColorstring#009658Hover color
separatorstring/Character between crumbs (e.g., / › →)
maxItemsnumber3Max visible segments (older collapse to …)
gapnumber8Space between crumbs (px)
alignmentenumflex-startFlex alignment (flex-start|center|flex-end)
sectionIdstringbreadcrumb-sectionWrapper id attribute
schemaNamestring""Breadcrumb display name (e.g., “Blog”)
schemaSlugstring""Breadcrumb slug (e.g., "blog")
schemaRootstringHomeRoot label for position 1
blogHeadlinestring""Article headline
blogDescriptionstring""Short description
blogImageimage""Primary image URL
blogImageHeightnumber800Image height (px)
blogImageWidthnumber1200Image width (px)
blogAuthorNamestring""Author full name
blogAuthorURLstring""Author profile/home URL
blogPublisherNamestring""Publisher name
blogPublisherLogoimage""Publisher logo URL
blogPublisherLogoHeightnumber60Logo height (px)
blogPublisherLogoWidthnumber600Logo width (px)
blogPublishDatestring""ISO date published (YYYY-MM-DD)
blogModifiedDatestring""ISO date modified (YYYY-MM-DD)

Notes & Tips

  • Overflow UX: The … represents skipped ancestors; keep maxItems 2–4 for clarity.
  • Chevrons: For a chevron look, set separator="›" and tighten gap=6.
  • Centering: For centered trails within fluid layouts, ensure the parent has display:block with adequate width.
  • Framer control quirk: Alignment value should be flex-start/center/flex-end (the UI shows “Left/Center/Right”).

Troubleshooting / FAQ

My alignment doesn’t change.

Use flex-start|center|flex-end; if imported presets use "left", switch to flex-start.

Labels look odd (“My%20Post”).

The component decodes URI; if still wrong, confirm your route slugs.

Home links to a relative path.

Origin comes from window.location.origin; verify your domain/protocol in previews.

JSON-LD not visible.

It won’t render UI—check page source (client) or DevTools Elements for <script type="application/ld+json">.

Source

Header comment

SC_Breadcrumb.tsx · lines 15–22 · header comment
/** * SC Dynamic Breadcrumb * --------------------- * - URL-based breadcrumb with overflow handling * - SPA navigation (single boolean control) * - BreadcrumbList + BlogPosting JSON-LD (optional) * - Canvas-safe preview path */

props [REF]

Key excerpt

The trail from the URL: segments past the limit fold into “…”, each crumb links to its own path prefix, and a BreadcrumbList is built for JSON-LD.

SC_Breadcrumb.tsx · lines 187–238 · tsx
    // -------- Build items --------    const segments = pathForBuild.split("/").filter(Boolean)    const effectiveMax = Math.max(1, Math.min(layoutMax, 50))    const hasOverflow = segments.length > effectiveMax    const visibleSegs = hasOverflow ? segments.slice(-effectiveMax) : segments    const all = ["home", ...(hasOverflow ? ["..."] : []), ...visibleSegs]    const buildHref = (idx: number): string | null => {        const isLast = idx === all.length - 1        const seg = all[idx]        if (seg === "..." || isLast) return null        if (seg === "home") return origin        const ahead = all.length - idx - 1        const segCount = segments.length - ahead        return `${origin}/${segments.slice(0, segCount).join("/")}`    }    const items = all.map((seg, i) => ({        key: i,        segment: seg,        label:            seg === "home" ? "Home" : seg === "..." ? "…" : formatSegment(seg),        href: buildHref(i),        isLast: i === all.length - 1,    }))    // -------- Schema --------    const breadcrumbSchema = breadcrumbEnabled        ? cleanObject({              "@context": "https://schema.org",              "@type": "BreadcrumbList",              itemListElement: [                  {                      "@type": "ListItem",                      position: 1,                      name: breadcrumbRootName,                      item: origin,                  },                  breadcrumbCategoryName && {                      "@type": "ListItem",                      position: 2,                      name: breadcrumbCategoryName,                      item: `${origin}/${breadcrumbCategorySlug}`,                  },                  blogHeadline && {                      "@type": "ListItem",                      position: 3,                      name: blogHeadline,                  },              ].filter(Boolean),          })        : null

Credits

Credits

Designed and implemented by SecretoCho Design. Pattern-safe URL formatting and schema cleanup helpers included.

license
SecretoCho Design

SecretoCho Design 2025

Disclaimer

Proves

Hiring a design engineer?

I’m open to senior design engineer roles: remote from Belgrade, or relocation with visa sponsorship. Write to me, or read the CV first. Client work stays selective, one project at a time.

sc@secretocho.design

read the CV · LinkedIn