Skip to main content

Testing

Help us to improve the ONS Design System. Take part in a short study

Breadcrumbs

A breadcrumb trail consists of a list of links to the parent pages of the current page in hierarchical order. It helps users find their place within a website or web application.

<nav class="breadcrumb" aria-label="Breadcrumb">
  <ol class="breadcrumb__items u-fs-s">
    <li class="breadcrumb__item" id="breadcrumb-1">
      <a class="breadcrumb__link" href="/">Home</a>
      <svg class="svg-icon" viewBox="0 0 8 13" xmlns="http://www.w3.org/2000/svg" focusable="false">
        <path d="M5.74,14.28l-.57-.56a.5.5,0,0,1,0-.71h0l5-5-5-5a.5.5,0,0,1,0-.71h0l.57-.56a.5.5,0,0,1,.71,0h0l5.93,5.93a.5.5,0,0,1,0,.7L6.45,14.28a.5.5,0,0,1-.71,0Z" transform="translate(-5.02 -1.59)" />
      </svg>
    </li>
    <li class="breadcrumb__item" id="breadcrumb-2">
      <a class="breadcrumb__link" href="/components">Components</a>
      <svg class="svg-icon" viewBox="0 0 8 13" xmlns="http://www.w3.org/2000/svg" focusable="false">
        <path d="M5.74,14.28l-.57-.56a.5.5,0,0,1,0-.71h0l5-5-5-5a.5.5,0,0,1,0-.71h0l.57-.56a.5.5,0,0,1,.71,0h0l5.93,5.93a.5.5,0,0,1,0,.7L6.45,14.28a.5.5,0,0,1-.71,0Z" transform="translate(-5.02 -1.59)" />
      </svg>
    </li>
  </ol>
</nav>
Nunjucks macro options
Name Type Required Description
classes string false Custom classes to add to the breadcrumb
ariaLabel string false The label added to the nav element. Defaults to Breadcrumbs
id string false The ID added to the nav element
itemsList Array true An array of items to show in the breadcrumb list
Name Type Required Description
itemClasses string false Custom classes to add to the breadcrumb list item
linkClasses string false Custom classes to add to the breadcrumb link
url string true The url for the link
text string true The name of the page
attributes object false HTML attributes (for example data attributes) to add to the breadcrumb element
id string false The ID added to the breadcrumb
{% from "components/breadcrumb/_macro.njk" import onsBreadcrumb %}
{{
    onsBreadcrumb({
        "ariaLabel": 'Breadcrumb',
        "itemsList": [
            {
                "url": '/',
                "text": 'Home'
            },
            {
                "url": '/components',
                "text": 'Components'
            }
        ]
    })
}}

{% from "components/icons/_macro.njk" import onsIcon %}
{% macro onsBreadcrumb(params) %}
    <nav class="breadcrumb{{ ' ' + params.classes if params.classes else '' }}" aria-label="{{ params.ariaLabel | default("Breadcrumbs") }}" {% if params.id is defined and params.id %} id="{{ params.id }}"{% endif %}>
        <ol class="breadcrumb__items u-fs-s">
            {% for item in (params.itemsList if params.itemsList is iterable else params.itemsList.items()) %}
                <li class="breadcrumb__item{{ ' ' + item.itemClasses if item.itemClasses else '' }}" id="breadcrumb-{{ loop.index }}">
                    <a class="breadcrumb__link{{ ' ' + item.linkClasses if item.linkClasses else '' }}" href="{{ item.url }}"{% if item.id is defined and item.id %} id="{{ item.id }}"{% endif %}
                    {% if item.attributes is defined and item.attributes %}{% for attribute, value in (item.attributes.items() if item.attributes is mapping and item.attributes.items else item.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}
                    >{{ item.text }}</a>
                    {{
                        onsIcon({
                            "icon": "chevron"
                        })
                    }}
                </li>
            {% endfor %}
        </ol>
    </nav>
{% endmacro %}

$breadcrumb-chevron-height: 0.65rem;
.breadcrumb {
  align-items: center;
  display: flex;
  padding: 1rem 0;
  &__items {
    margin: 0;
    padding: 0;
  }
  &__item {
    display: inline-block;
    margin: 0;
    white-space: nowrap; // Stop items from wrapping, break on chevron only
    &:not(:nth-last-child(1)) {
      //small screen not last child
      display: none;
    }
    .svg-icon {
      height: $breadcrumb-chevron-height;
      margin: 0 0.2rem;
      vertical-align: middle;
      width: $breadcrumb-chevron-height;
    }
    &:nth-last-child(1) {
      // small screen last child
      direction: rtl;
      .svg-icon {
        margin-left: -0.13rem;
        transform: rotate(180deg);
      }
    }
    @include mq(s) {
      //big screen
      &:not(:nth-last-child(1)) {
        //not last child
        display: inline-block;
      }
      &:nth-last-child(1) {
        // last child
        direction: ltr;
        .svg-icon {
          display: none;
        }
      }
      &:first-child:nth-last-child(1) {
        //first and last child
        direction: rtl;
        .svg-icon {
          display: inline-block;
          vertical-align: middle;
        }
      }
      &:not(:last-child).svg-icon {
        //not last child
        margin: 0;
        /* stylelint-disable */
        // We have to override the icon settings so it renders correctly in ie11
        background-position: center center;
        vertical-align: middle;
        /* stylelint-enable */
      }
    }
  }
  &__link {
    color: $color-text;
    text-decoration: underline;
    &:hover {
      color: $color-text;
    }
  }
}

When to use this component

Use the breadcrumbs component when you need to help users understand and move between the multiple levels of a website.

When not to use this component

Don’t use the breadcrumbs component on websites with a flat structure, or to show progress through a linear journey or transaction.

If you’re using other navigational elements on the page, such as a sidebar, consider whether your users need the additional support of breadcrumbs.

How to use this component

Always place breadcrumbs before a page’s <main> content element. This makes sure the Skip to content link allows the user to skip all navigation, including the breadcrumbs. Where possible this should be set in the page template in pageConfig to make sure it’s placed correctly.

How it works

  • The set of links is structured using an ordered list to provide semantic structure
  • A nav element labeled Breadcrumb identifies the structure as a breadcrumb trail and makes it a navigation landmark so that it is easy to locate
  • To prevent screen reader announcing the visual separators between links, they are added via CSS
  • The separators are part of the visual presentation that signifies the breadcrumb trail. This is already semantically represented by the nav element with its aria-label of Breadcrumb. Therefore using a display technique that is not used by screen readers prevents redundant and potentially distracting verbosity

Variants

Single breadcrumb

When the component only has a single breadcrumb it will display like this.

<nav class="breadcrumb" aria-label="Breadcrumb">
  <ol class="breadcrumb__items u-fs-s">
    <li class="breadcrumb__item" id="breadcrumb-1">
      <a class="breadcrumb__link" href="/">Home</a>
      <svg class="svg-icon" viewBox="0 0 8 13" xmlns="http://www.w3.org/2000/svg" focusable="false">
        <path d="M5.74,14.28l-.57-.56a.5.5,0,0,1,0-.71h0l5-5-5-5a.5.5,0,0,1,0-.71h0l.57-.56a.5.5,0,0,1,.71,0h0l5.93,5.93a.5.5,0,0,1,0,.7L6.45,14.28a.5.5,0,0,1-.71,0Z" transform="translate(-5.02 -1.59)" />
      </svg>
    </li>
  </ol>
</nav>
Nunjucks macro options
Name Type Required Description
classes string false Custom classes to add to the breadcrumb
ariaLabel string false The label added to the nav element. Defaults to Breadcrumbs
id string false The ID added to the nav element
itemsList Array true An array of items to show in the breadcrumb list
Name Type Required Description
itemClasses string false Custom classes to add to the breadcrumb list item
linkClasses string false Custom classes to add to the breadcrumb link
url string true The url for the link
text string true The name of the page
attributes object false HTML attributes (for example data attributes) to add to the breadcrumb element
id string false The ID added to the breadcrumb
{% from "components/breadcrumb/_macro.njk" import onsBreadcrumb %}
{{
    onsBreadcrumb({
        "ariaLabel": 'Breadcrumb',
        "itemsList": [
            {
                "url": '/',
                "text": 'Home'
            }
        ]
    })
}}

{% from "components/icons/_macro.njk" import onsIcon %}
{% macro onsBreadcrumb(params) %}
    <nav class="breadcrumb{{ ' ' + params.classes if params.classes else '' }}" aria-label="{{ params.ariaLabel | default("Breadcrumbs") }}" {% if params.id is defined and params.id %} id="{{ params.id }}"{% endif %}>
        <ol class="breadcrumb__items u-fs-s">
            {% for item in (params.itemsList if params.itemsList is iterable else params.itemsList.items()) %}
                <li class="breadcrumb__item{{ ' ' + item.itemClasses if item.itemClasses else '' }}" id="breadcrumb-{{ loop.index }}">
                    <a class="breadcrumb__link{{ ' ' + item.linkClasses if item.linkClasses else '' }}" href="{{ item.url }}"{% if item.id is defined and item.id %} id="{{ item.id }}"{% endif %}
                    {% if item.attributes is defined and item.attributes %}{% for attribute, value in (item.attributes.items() if item.attributes is mapping and item.attributes.items else item.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}
                    >{{ item.text }}</a>
                    {{
                        onsIcon({
                            "icon": "chevron"
                        })
                    }}
                </li>
            {% endfor %}
        </ol>
    </nav>
{% endmacro %}

$breadcrumb-chevron-height: 0.65rem;
.breadcrumb {
  align-items: center;
  display: flex;
  padding: 1rem 0;
  &__items {
    margin: 0;
    padding: 0;
  }
  &__item {
    display: inline-block;
    margin: 0;
    white-space: nowrap; // Stop items from wrapping, break on chevron only
    &:not(:nth-last-child(1)) {
      //small screen not last child
      display: none;
    }
    .svg-icon {
      height: $breadcrumb-chevron-height;
      margin: 0 0.2rem;
      vertical-align: middle;
      width: $breadcrumb-chevron-height;
    }
    &:nth-last-child(1) {
      // small screen last child
      direction: rtl;
      .svg-icon {
        margin-left: -0.13rem;
        transform: rotate(180deg);
      }
    }
    @include mq(s) {
      //big screen
      &:not(:nth-last-child(1)) {
        //not last child
        display: inline-block;
      }
      &:nth-last-child(1) {
        // last child
        direction: ltr;
        .svg-icon {
          display: none;
        }
      }
      &:first-child:nth-last-child(1) {
        //first and last child
        direction: rtl;
        .svg-icon {
          display: inline-block;
          vertical-align: middle;
        }
      }
      &:not(:last-child).svg-icon {
        //not last child
        margin: 0;
        /* stylelint-disable */
        // We have to override the icon settings so it renders correctly in ie11
        background-position: center center;
        vertical-align: middle;
        /* stylelint-enable */
      }
    }
  }
  &__link {
    color: $color-text;
    text-decoration: underline;
    &:hover {
      color: $color-text;
    }
  }
}

Research on this component

Based upon W3 principles 

Help improve this component

Let us know how we could improve this component or share your user research findings.

Discuss the ‘Breadcrumbs’ component on GitHub