A <nav aria-label="Breadcrumb"> wraps an ordered list (<ol>) — order matters here, it’s a path, so <ol> is the more correct choice than <ul>.
Every step is a link except the last one, which is the current page: plain text, marked aria-current="page".
Style
Separators (/, ›, …) are generated in CSS (::before on every item except the first) rather than typed into the HTML, so a screen reader doesn’t read “slash” or “chevron” between every step.
Long trails need to collapse on narrow screens — hiding the middle steps behind an ellipsis is the common pattern.
Features
None needed for the base version.
Collapsing the middle steps on a narrow container can be done with a CSS container query alone — no JS needed there either.
A regular @media query only responds to the browser window’s size — not useful here, since the same breadcrumb might sit in a wide header on one page and a narrow sidebar on another. A @container query responds to the size of a containing element instead: mark an ancestor with container-type: inline-size, and @container (max-width: ...) inside it reacts to that element’s width. Below, the exact same markup is dropped into a 500px and a 220px container to show both states side by side, without needing to actually resize anything.
The ellipsis is its own <li>, hidden by default — simpler than trying to style a ::before/::after on an element that’s itself display: none, since a hidden element’s pseudo-elements never render.