Bottom Nav
The mobile tab bar: three to five destinations along the bottom of the screen, each an icon over a short label with a count or dot badge.
c2-bottom-nav
The mobile tab bar: three to five c2-bottom-nav-item destinations along the bottom of the screen, each an icon
over a short label with an optional count or dot badge. It is a navigation landmark (named "Main" unless the host
has an aria-label) of plain links or buttons, the current one announced with aria-current="page"; not a tab
list, so every item is a normal tab stop.
Set value to the value of the item being shown, or mark that item current. Activating another item fires a
cancelable item-select (cancelling it also stops the link, for an unsaved-changes guard), then updates value
and fires change. Activating the current item again fires reselect, the place to scroll back to the top.
The host is position: sticky to the bottom by default, so as the last element of the page it stays on screen
without covering the end of the content, and the bar is padded by env(safe-area-inset-bottom) for the home
indicator. With hide-on-scroll it slides away while the page scrolls down and returns on scroll up, at the top
or when focus moves into it. Every look (Material indicator, translucent glass, floating dock, top line) is a set
of CSS variables.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
value | string | — | Value of the current item. Left empty, the item marked current when the bar first renders provides it, and so does
an item that gets the current attribute later. Set it to '' for a page that is none of the items. |
label-visibility | BottomNavLabelVisibility | labeled | Which labels show: all (labeled), all up to three items and the current one from four (auto), the current one (selected) or none (unlabeled). |
hide-on-scroll | boolean | false | Slides the bar away while the page scrolls down and brings it back on scroll up, at the top or on focus. |
scroll-target | string | — | Id of the element whose scrolling hide-on-scroll follows, looked up in the bar's document or shadow root when the
attribute is set or the bar connects, so that element must exist by then. Empty: the window. |
Slots
| Name | Description |
|---|---|
default | The c2-bottom-nav-item elements, three to five of them. |
Events
| Name | Type | Description |
|---|---|---|
item-select | CustomEvent<BottomNavItemSelectEventDetail> | An item other than the current one was activated. Cancelable: cancelling keeps value and stops a link from navigating. |
change | Event | value changed because an item was activated. |
reselect | CustomEvent<BottomNavReselectEventDetail> | The current item was activated again. |
CSS parts
Shadow DOM styling hooks used with ::part(name). Prefer CSS custom properties when they cover the change.
| Name | Description |
|---|---|
bar | The visible bar: background, border, radius, safe-area padding. It slides away with hide-on-scroll. |
CSS custom properties
Grouped by semantic target and state from --c2-<component>__<target>__<state>--<property>. Click a group to collapse it; click a name to copy it.
| Name | Type | Default | Description |
|---|---|---|---|
--c2-bottom-nav--position | position | sticky | fixed pins it to the viewport wherever it sits in the page. |
--c2-bottom-nav--z-index | number | 10 | |
--c2-bottom-nav--background | background | #ffffff | A translucent colour with backdrop-filter gives the glass look. |
--c2-bottom-nav--border-top | border | 1px solid #e4e4e7 | |
--c2-bottom-nav--border-radius | border-radius | 0px | |
--c2-bottom-nav--box-shadow | box-shadow | none | |
--c2-bottom-nav--backdrop-filter | backdrop-filter | none | Such as blur(18px) saturate(1.6) over a translucent background. |
--c2-bottom-nav--margin | margin | 0px | Lifts the bar off the screen edges for a floating dock. |
--c2-bottom-nav--max-width | pixel | none | |
--c2-bottom-nav--min-height | pixel | 64px | |
--c2-bottom-nav--padding-top | padding | 0px | |
--c2-bottom-nav--padding-right | padding | 0px | |
--c2-bottom-nav--padding-bottom | padding | env(safe-area-inset-bottom, 0px) | Keeps the items clear of the home indicator. |
--c2-bottom-nav--padding-left | padding | 0px | |
--c2-bottom-nav--gap | pixel | 0px | Space between items. |
--c2-bottom-nav__away--transform | transform | translateY(calc(100% + 32px)) | Where hide-on-scroll moves the bar. |
--c2-bottom-nav__away--transition-duration | time | 0.2s | Length of that slide; reduced motion drops it. |
Text and languages
The text the component shows, in English. It shows another language when the app adds one with addTranslations, under bottom-nav, and the nearest lang asks for it; any message not translated stays in English. {0}, {1}… stand for the values a message carries. Languages guide.
| Key | English | Values |
|---|---|---|
navigationLabel | Main | — |
newCount | {0} new | {0} count |
newActivity | new activity | — |
c2-bottom-nav-item
One destination of a c2-bottom-nav: an icon over a short label, with an optional count or dot badge. With an
href it renders a link, otherwise a button. Mark the item of the page being shown current (or set the bar's
value) to announce aria-current="page", show the indicator behind the icon and swap in the current-icon.
The badge is drawn with c2-badge and read as part of the item's name ("Inbox, 3 new", "Chat, new activity"),
so a screen reader hears what a sighted user sees. A label hidden by the bar's label-visibility stays the name.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
value | string | — | Identifies the item for the bar's value. Falls back to href, then the label. |
href | string | undefined | — | Makes the item a link. |
target | string | undefined | — | Browsing context used when href is set, such as _blank. |
label | string | undefined | — | Label used when the default slot is empty. |
current | boolean | false | The item of the page being shown: announced as aria-current="page". Set by the bar from its value. |
count | number | undefined | undefined | Number shown in a badge on the icon. 0 hides the badge. |
max | number | 99 | Upper bound for count; larger values show as <max>+. |
dot | boolean | false | Shows a dot badge on the icon, read as "new activity". Ignored while count is shown. |
Slots
| Name | Description |
|---|---|
default | The label. Falls back to label. |
icon | The icon, sized by --c2-bottom-nav-item__icon--size. |
current-icon | Optional icon shown instead of icon while the item is current, such as a filled variant. |
CSS parts
Shadow DOM styling hooks used with ::part(name). Prefer CSS custom properties when they cover the change.
| Name | Description |
|---|---|
item | The link or button: the whole touch target. |
indicator | The shape behind the icon that marks the current item, and the hover and pressed feedback. |
label | The label text. |
badge | The c2-badge drawn for count or dot. |
CSS custom properties
Grouped by semantic target and state from --c2-<component>__<target>__<state>--<property>. Click a group to collapse it; click a name to copy it.
| Name | Type | Default | Description |
|---|---|---|---|
--c2-bottom-nav-item--flex-direction | flex-direction | column | row puts the icon before the label, as on tablets. |
--c2-bottom-nav-item--gap | pixel | 4px | Space between the icon and the label. |
--c2-bottom-nav-item--min-height | pixel | 48px | Minimum height of the touch target. |
--c2-bottom-nav-item--padding-top | padding | 8px | |
--c2-bottom-nav-item--padding-right | padding | 2px | |
--c2-bottom-nav-item--padding-bottom | padding | 6px | |
--c2-bottom-nav-item--padding-left | padding | 2px | |
--c2-bottom-nav-item--color | color | #71717a | Icon and label colour of an item that is not current. |
--c2-bottom-nav-item--font-family | font-family | inherit | |
--c2-bottom-nav-item--font-size | font-size | 12px | |
--c2-bottom-nav-item--font-weight | font-weight | 500 | |
--c2-bottom-nav-item--line-height | line-height | 16px | |
--c2-bottom-nav-item--letter-spacing | pixel | — | |
--c2-bottom-nav-item__current--color | color | rgb(2, 101, 220) | Icon and label colour of the current item. |
--c2-bottom-nav-item__current--font-weight | font-weight | 600 | Label weight of the current item. |
--c2-bottom-nav-item__indicator--width | pixel | 56px | |
--c2-bottom-nav-item__indicator--height | pixel | 32px | |
--c2-bottom-nav-item__indicator--border-radius | border-radius | 999px | |
--c2-bottom-nav-item__indicator--background | background | transparent | Indicator of an item that is not current. |
--c2-bottom-nav-item__indicator--transition-duration | time | 0.2s | |
--c2-bottom-nav-item__indicator__hover--background | background | #f4f4f5 | Indicator under a hovering pointer. |
--c2-bottom-nav-item__indicator__active--background | background | #e4e4e7 | Indicator while pressed. |
--c2-bottom-nav-item__indicator__current--background | background | #edf1fe | Indicator of the current item. transparent for a tint-only look. |
--c2-bottom-nav-item__icon--size | pixel | 24px | Also handed to slotted Feather and Phosphor icons. |
--c2-bottom-nav-item__line--height | pixel | 0px | Height of a line on the top edge of the current item; 3px for the top-line look. |
--c2-bottom-nav-item__line--width | pixel | 50% | Width of that line. |
--c2-bottom-nav-item__line--border-radius | border-radius | 0 0 3px 3px | |
--c2-bottom-nav-item__line__current--background | background | rgb(2, 101, 220) | |
--c2-bottom-nav-item__badge--top | pixel | 0px | Offset of a count badge from the top of the indicator. |
--c2-bottom-nav-item__badge--inset-inline-start | pixel | calc(50% + 4px) | Offset of a count badge from the start of the indicator. |
--c2-bottom-nav-item__badge--box-shadow | box-shadow | 0 0 0 2px #ffffff | Ring around the badge, in the bar's background colour. |
--c2-bottom-nav-item__dot--top | pixel | 3px | Offset of a dot badge from the top of the indicator. |
--c2-bottom-nav-item__dot--inset-inline-start | pixel | calc(50% + 7px) | Offset of a dot badge from the start of the indicator. |
--c2-bottom-nav-item__focus--outline | outline | 2px solid rgba(2, 101, 220, 0.4) | Keyboard focus ring, drawn around the indicator. |
--c2-bottom-nav-item__focus--outline-offset | pixel | 2px | |