Navigation components that most developers treat as afterthoughts — breadcrumbs and pagination — have an outsized impact on how users move through a site and how confident they feel doing it. Get them wrong and users lose their place, bounce from deep pages, or struggle to scan large datasets. Get them right and you reduce cognitive load, improve SEO signal, and give your interface a polished, production-quality feel. This guide covers Bootstrap 5 breadcrumbs and Bootstrap pagination in depth: the markup patterns, the accessibility requirements, the UX principles, and the customisation techniques that separate amateur implementations from professional ones.
Key Takeaways
- Bootstrap 5 breadcrumbs use a
<nav>landmark witharia-label="breadcrumb"and a CSS-driven separator via the--bs-breadcrumb-dividercustom property. - The active breadcrumb item should carry
aria-current="page"and never be a link — it represents the current location. - Bootstrap pagination is a flex-based
<ul>list; every interactive element must be an<a>or<button>to satisfy keyboard navigation requirements. - Truncating pagination with an ellipsis item improves usability on large datasets without hiding the first and last page anchors.
- Both components integrate cleanly with Bootstrap 5 CSS custom properties, allowing theme-level colour changes with a single variable override.
- Combining breadcrumbs and pagination correctly on content-heavy pages — such as blog archives — reinforces hierarchical context at every scroll position.
Why Breadcrumbs and Pagination Matter for Navigation UX
Users arriving on a deep page from a search engine or a shared link have no ambient awareness of where they are in your site hierarchy. Breadcrumbs solve that immediately. Pagination solves a different but equally important problem: how to divide a large content set into digestible chunks while keeping every chunk reachable in a predictable number of clicks.
From a search engine perspective, both components carry structural meaning. Breadcrumbs reinforce topical hierarchy — Google reads BreadcrumbList structured data and uses it to generate rich results. Pagination signals content relationships, which affects how crawlers allocate crawl budget across archive pages. This is one reason navigation UX in Bootstrap projects is worth treating as a first-class concern, not a styling task left until the end of a project. If you are thinking seriously about SEO for a static HTML site, the post on HTML Template SEO: What You Can and Can’t Fix Without a CMS is a useful companion read.

Bootstrap 5 Breadcrumbs: Correct Markup and Accessibility
The Bootstrap 5 breadcrumb component wraps an <ol> inside a <nav> element. The <ol> is semantically appropriate because breadcrumb items have a defined order. Each item is a <li class="breadcrumb-item">, and the current page item receives both the active class and the aria-current="page" attribute.
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">Home</a></li>
<li class="breadcrumb-item"><a href="/blog/">Blog</a></li>
<li class="breadcrumb-item active" aria-current="page">Bootstrap 5 Tips</li>
</ol>
</nav>Two mistakes appear constantly in production code. First, wrapping the active item in an anchor — this implies the page links to itself, which confuses both screen readers and search engine crawlers. Second, omitting aria-label="breadcrumb" from the <nav> landmark, which means a screen reader announces it as an unnamed navigation region and provides no distinguishing context when multiple <nav> elements exist on the same page. For a broader look at accessible component patterns in Bootstrap, the guide on making a Bootstrap 5 website accessible to WCAG 2.1 AA covers the full checklist.
Customising Breadcrumb Separators With CSS Custom Properties
Bootstrap 5 uses a CSS custom property to control the separator character, which means you can change it with a single line of CSS rather than rebuilding the component. The default is a forward slash, but any string or SVG fragment works.
<!-- Override separator to a chevron character -->
<nav aria-label="breadcrumb" style="--bs-breadcrumb-divider: '›';">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">Home</a></li>
<li class="breadcrumb-item"><a href="/products/">Products</a></li>
<li class="breadcrumb-item active" aria-current="page">Canvas Template</li>
</ol>
</nav>For a global theme override, set the variable in your own stylesheet rather than using an inline style:
<style>
:root {
--bs-breadcrumb-divider: '/';
--bs-breadcrumb-item-active-color: var(--cnvs-themecolor);
}
</style>The --cnvs-themecolor reference here is specific to the Canvas HTML Template, which exposes a top-level theme colour token that cascades through all themed components. Plugging breadcrumb active colour into that variable keeps your design system internally consistent without touching a single Sass file.

Bootstrap Pagination: Markup, Sizing, and UX Patterns
The Bootstrap pagination component is a flex list of <li class="page-item"> elements, each containing an <a class="page-link">. The outer <ul> sits inside a <nav> with a descriptive aria-label.
<nav aria-label="Blog post pagination">
<ul class="pagination">
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1" aria-disabled="true">Previous</a>
</li>
<li class="page-item active" aria-current="page">
<a class="page-link" href="/blog/page/1/">1</a>
</li>
<li class="page-item"><a class="page-link" href="/blog/page/2/">2</a></li>
<li class="page-item"><a class="page-link" href="/blog/page/3/">3</a></li>
<li class="page-item">
<a class="page-link" href="/blog/page/2/">Next</a>
</li>
</ul>
</nav>Several UX decisions are encoded in that markup. The disabled Previous item uses tabindex="-1" to remove it from keyboard focus order and aria-disabled="true" to signal its state to assistive technology — these two attributes do different jobs and both are needed. The active item carries aria-current="page" for the same reason as the breadcrumb active item. When building a blog archive — a common use case described in the post on adding a blog section to any HTML template — this pattern provides both screen reader users and search engines with unambiguous page state.
Handling Large Datasets: Ellipsis Pagination
When a paginated set runs to dozens of pages, showing every page number creates visual noise and makes the component unusable. The standard UX pattern is to show the first page, the last page, the current page, and one or two neighbours — replacing the gaps with an ellipsis item marked as disabled.
<nav aria-label="Search results pagination">
<ul class="pagination pagination-lg justify-content-center">
<li class="page-item">
<a class="page-link" href="/results/page/6/">Previous</a>
</li>
<li class="page-item"><a class="page-link" href="/results/page/1/">1</a></li>
<li class="page-item disabled" aria-hidden="true">
<span class="page-link">…</span>
</li>
<li class="page-item"><a class="page-link" href="/results/page/6/">6</a></li>
<li class="page-item active" aria-current="page">
<a class="page-link" href="/results/page/7/">7</a>
</li>
<li class="page-item"><a class="page-link" href="/results/page/8/">8</a></li>
<li class="page-item disabled" aria-hidden="true">
<span class="page-link">…</span>
</li>
<li class="page-item"><a class="page-link" href="/results/page/24/">24</a></li>
<li class="page-item">
<a class="page-link" href="/results/page/8/">Next</a>
</li>
</ul>
</nav>Note that ellipsis items use aria-hidden="true" rather than aria-disabled, because they are not interactive controls — they are decorative gap indicators. Using a <span> instead of an <a> inside the ellipsis item reinforces this semantically. The pagination-lg and pagination-sm modifier classes control size without requiring any custom CSS, and justify-content-center or justify-content-end from Bootstrap’s flexbox utilities handle alignment.
Responsive Breadcrumbs and Pagination
On small viewports, both components can overflow their containers. A few practical strategies prevent this.
For breadcrumbs, truncating intermediate items on mobile is the standard pattern. This is typically done by hiding middle items with a responsive utility class or by collapsing them to a single “…” expander. A simpler approach that works for shallow hierarchies — three levels or fewer — is to truncate the text of intermediate labels with CSS overflow ellipsis:
<style>
.breadcrumb-item a {
max-width: 120px;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: bottom;
}
</style>For pagination, the most practical responsive technique is to reduce the number of visible page numbers on small screens. Bootstrap’s display utilities let you hide specific items below a breakpoint:
<li class="page-item d-none d-md-block">
<a class="page-link" href="/page/5/">5</a>
</li>On very small screens, some design systems replace standard pagination entirely with a “Page X of Y” text indicator plus Previous and Next buttons — a pattern that is more thumb-friendly and less prone to overflow. Whichever approach you take, ensure the minimum touch target size for each page link meets the 44×44 CSS pixel recommendation from WCAG 2.5.5. Padding the .page-link element is usually enough to satisfy this without affecting the visual design.
Combining Breadcrumbs and Pagination in a Real Page Layout
On a paginated blog archive or category page, both components should be present — and their placement relative to the content affects how clearly users understand their position. The breadcrumb belongs at the top of the content area, before the page heading, so users arriving from search immediately see their location. The pagination belongs after the last content item, immediately before the footer.
<div class="container">
<!-- Breadcrumb at top of content area -->
<nav aria-label="breadcrumb" class="mt-4">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Blog</li>
</ol>
</nav>
<h2 class="mb-4">Blog — Page 2</h2>
<!-- Article cards would go here -->
<!-- Pagination at bottom of content area -->
<nav aria-label="Blog archive pagination" class="mt-5 mb-4">
<ul class="pagination justify-content-center">
<li class="page-item">
<a class="page-link" href="/blog/page/1/">Previous</a>
</li>
<li class="page-item">
<a class="page-link" href="/blog/page/1/">1</a>
</li>
<li class="page-item active" aria-current="page">
<a class="page-link" href="/blog/page/2/">2</a>
</li>
<li class="page-item">
<a class="page-link" href="/blog/page/3/">3</a>
</li>
<li class="page-item">
<a class="page-link" href="/blog/page/3/">Next</a>
</li>
</ul>
</nav>
</div>Spacing the components with Bootstrap’s margin utilities — mt-4, mt-5, mb-4 — keeps visual rhythm consistent without a single line of custom CSS. If your project uses a grid with specific gutter widths, the post on Bootstrap 5 columns and gutters is worth reviewing to ensure your breadcrumb and pagination containers align with the rest of the layout grid.
FAQ
No. The active breadcrumb item represents the page the user is already on, so making it a link that points to the current URL is redundant and can confuse assistive technologies. Use plain text inside the <li> and add aria-current="page" to the <li> element. Bootstrap’s .active class handles the visual styling.
Add the .disabled class to the <li> element, set tabindex="-1" on the inner <a> to remove it from keyboard focus order, and add aria-disabled="true" to signal the disabled state to screen readers. Both attributes are required — the class alone only applies visual styling, while tabindex="-1" and aria-disabled provide the functional and semantic signals that assistive technologies rely on.
Bootstrap 5 exposes the --bs-breadcrumb-divider CSS custom property. Set it on :root in your stylesheet for a global change, or apply it inline on the <nav> element for a one-off override. The value is a quoted string, such as '›' or '/'. To use an SVG as the separator, use the url() CSS function with a base64-encoded or inline SVG fragment — the Bootstrap documentation includes an example of this pattern.
The Bootstrap pagination component itself is purely CSS — there is no bundled JavaScript. For client-side rendered applications, you manage page state yourself and re-render the pagination list on each state change. Ensure you update aria-current="page" on the active item and manage focus appropriately when new content loads, so keyboard and screen reader users understand that the page content has changed.
A common rule of thumb is to show all pages if there are seven or fewer, and to introduce ellipsis truncation once the total exceeds that count. In the truncated view, always show the first page, the last page, the current page, and one immediate neighbour on each side — five visible items plus two ellipsis placeholders. This gives users enough context to understand their position and reach the beginning or end of the set in one click.
Looking for a production-ready Bootstrap 5 HTML template? Browse Canvas Template demos and find the perfect starting point for your next project.
If you’re working with the Canvas HTML Template and want to generate production-ready layouts faster, try Canvas Builder free and see how much time you save on every project.
Skip the setup — build it free
Spin up a complete Bootstrap 5 site, blog included, with Canvas Builder. No coding, no cost.
Canvas Team
Tutorials and tips for building beautiful Bootstrap 5 websites with the Canvas HTML Template and Canvas Builder.
More from the Canvas Blog