Navbar Card is a custom Lovelace card designed to simplify navigation within your Home Assistant dashboard, heavily inspired by the great work of Adaptive Mushroom. It provides a sleek, responsive navigation bar that displays as a full-width bar at the bottom on mobile devices. On desktop, it adapts into a flexible container that can be positioned on any side of the screen (top, bottom, left, or right) adjusting its orientation to fit seamlessly.
- Go to HACS in Home Assistant.
- On the top right, click "Custom repositories".
- Enter the repository URL: https://github.com/joseluis9595/lovelace-navbar-card.git
- Search for "Navbar Card".
- Click Install!
- Download navbar-card.js from the latest release.
- Move this file to home assistant's
<config>/www
folder. - In home assistant, go to
Settings > Dashboards
. - On the top right corner, click
Resources
. - Add a new resource with the following:
- URL:
/local/navbar-card.js
- Resource type: JavaScript module
- URL:
- Go to your dashboard, refresh your page and add your new navbar-card!
Name | Type | Default | Description |
---|---|---|---|
routes |
Routes | Required |
Defines the array of routes to be shown in the navbar |
desktop |
Desktop | - | Options specific to desktop mode |
mobile |
Mobile | - | Options specific to mobile mode |
template |
Template | - | Template name |
styles |
Styles | - | Custom CSS styles for the card |
Routes represents an array of clickable icons that redirects to a given path. Each item in the array should contain the following configuration:
Name | Type | Default | Description |
---|---|---|---|
url |
string | Required* |
The path to a Lovelace view. Ignored if tap_action is defined. |
icon |
string | - | Material icon to display as this entry icon. Either icon or image is required. |
icon_selected |
string | - | Icon to be displayed when url matches the current browser URL |
image |
string | - | URL of an image to display as this entry icon. Either icon or image is required. |
image_selected |
string | - | Image to be displayed when url matches the current browser URL |
badge |
Badge | - | Badge configuration |
label |
string | JSTemplate | - | Label to be displayed under the given route if show_labels is true |
tap_action |
tap_action | - | Custom tap action configuration. |
hold_action |
hold_action | - | Custom hold action configuration. |
double_tap_action |
double_tap_action | - | Custom double_tap action configuration. |
popup |
Popup items | - | List of routes to display in a popup menu |
hidden |
boolean | JSTemplate | - | Controls whether to render this route or not |
selected |
boolean | JSTemplate | - | Controls whether to display this route as selected or not. If not defined, the selected status will be computed as route.url == window.location.pathname |
Note:
url
is required unlesstap_action
,hold_action
,double_tap_action
orpopup
is present.
Note: If
tap_action
is defined,url
is ignored.
Tip: Some suggestions when using the
image
property:
- Place your custom images in the
<ha-config-folder>/www
directory- Use images with a transparent background for best results
- Keep image dimensions squared for best results
Apart from the standard Home Assistant actions (navigate, call-service, etc.), navbar-card
supports some additional custom actions:
Action | Description | Required Parameters |
---|---|---|
open-popup |
Opens the popup menu defined in the route | None |
toggle-menu |
Opens the native HA side menu | None |
navigate-back |
Navigates back to the previous page in the browser history | None |
Example:
type: custom:navbar-card
...
routes:
...
- url: /lovelace/lights
icon: mdi:lightbulb-outline
tap_action:
action: open-popup # Will open the popup menu defined for this route
hold_action:
action: toggle-menu # Will open the native HA side menu
Configuration to display a small badge on any of the navbar items.
Name | Type | Default | Description |
---|---|---|---|
show |
boolean | JSTemplate | false | Boolean template indicating whether to display the badge or not |
color |
string | red | Background color of the badge |
For each route, a popup menu can be configured, to display a popup when clicked. This is activated using the open-popup
action in either tap_action
or hold_action
.
Name | Type | Default | Description |
---|---|---|---|
url |
string | Required* |
The path to a Lovelace view. Ignored if tap_action is defined. |
icon |
string | Required |
Material icon to display as this entry icon |
badge |
Badge | - | Badge configuration |
label |
string | JSTemplate | - | Label to be displayed under the given route if show_labels is true |
tap_action |
tap_action | - | Custom tap action configuration, including 'open-popup' to display a popup menu. |
hold_action |
hold_action | - | Custom hold action configuration, including 'open-popup' to display a popup menu. |
Note:
url
is required unlesstap_action
is present. Iftap_action
is defined,url
is ignored.
You can easily customize some properties of the navbar-card by writing your own JavaScript rules. To do this, you simply wrap the value of the field that supports JSTemplates in [[[
and ]]]
, then write the JavaScript code that determines the property's value.
Apart from using plain javascript, you can access some predefined variables:
states
-> Contains the global state of all entities in HomeAssistant. To get the state of a specific entity, use:states['entity_type.your_entity'].state
.user
-> Information about the current logged user.
Tip: You can use
console.log
in your JSTemplate to help debug your HomeAssistant states.
Below is an example using JSTemplates for displaying a route only for one user, and a label indicating the number of lights currently on:
type: custom:navbar-card
desktop:
position: bottom
show_labels: true
routes:
- url: /lovelace/lights
label: |
[[[
const lightsOn = Object.entries(states)
.filter(([entityId, value]) => {
return entityId.startsWith('light.') && value.state == 'on';
})
.length;
return `Lights (${lightsOn})`
]]]
icon: mdi:lightbulb-outline
icon_selected: mdi:lightbulb
- url: /lovelace/devices
label: Devices
icon: mdi:devices
hidden: |
[[[ return user.name != "jose"; ]]]
Specific configuration for desktop mode.
Name | Type | Default | Description |
---|---|---|---|
show_labels |
boolean | popup_only | routes_only |
false |
Whether or not to display labels under each route |
min_width |
number | 768 |
Screen size from which the navbar will be displayed as its desktop variant |
position |
top | bottom | left | right |
bottom |
Position of the navbar on desktop devices |
hidden |
boolean | JSTemplate | false |
Set to true to hide the navbar on desktop devices |
Specific configuration for mobile mode.
Name | Type | Default | Description |
---|---|---|---|
show_labels |
boolean | popup_only | routes_only |
false |
Whether or not to display labels under each route |
hidden |
boolean | JSTemplate | false |
Set to true to hide the navbar on mobile devices |
Templates allow you to predefine a custom configuration for navbar-card
and reuse it across multiple dashboards. This approach saves time and simplifies maintenance โ any change to the template will automatically apply to all cards using it.
To define custom templates, add them under navbar-templates
in your main Lovelace YAML configuration like this:
navbar-templates:
your_template_name:
# Your navbar config
routes:
- label: Home
icon: mdi:home
url: /lovelace/home
...
# Your normal lovelace configuration
views:
...
You can reference a template from your navbar-card
using the template property:
type: custom:navbar-card
template: your_template_name
Card properties defined directly in the card will take priority over those inherited from the template.
For example, if you want to use a template called your_template_name
but have one specific dashboard with a different primary color, your configurations might look like this:
- Default Navbar for Most Views:
type: custom:navbar-card
template: your_template_name
- Customized Navbar for a Specific View:
type: custom:navbar-card
template: your_template_name
styles: |
.navbar {
--navbar-primary-color: red;
}
Custom CSS styles can be applied to the Navbar Card to personalize its appearance and adapt it to your dashboard's design. Simply provide a CSS string targeting the relevant classes to style the navbar to your liking.
You can check out some examples here for inspiration.
Here is a breakdown of the CSS classes available for customization:
-
.navbar
: Base component for the navbar..navbar.desktop
: Styling for the desktop version..navbar.desktop.[top | bottom | left | right]
: Specific styles for different positions of the navbar..navbar.mobile
: Styling for the mobile version.
-
.route
: Represents each route (or item) within the navbar. -
.button
: Background element for each icon..button.active
: Applies when a route is selected.
-
.icon
: Refers to the ha-icon component used for displaying icons..icon.active
: Applies when a route is selected.
-
.image
: Refers to the img component used for displaying route images..image.active
: Applies when a route is selected.
-
.label
: Text label displayed under the icons (if labels are enabled)..label.active
: Applies when a route is selected.
-
.badge
: Small indicator or badge that appears over the icon (if configured)..badge.active
: Applies when a route is selected.
-
.navbar-popup
: Main container for the popup. -
.navbar-popup-backdrop
: Backdrop styles for the popup. -
.popup-item
: Styles applied to the container of each popup-item. This object contains both the "button" with the icon, and the label..popup-item.label-[top | bottom | left | right]
: Specific styles for different positions of the label..popup-item .label
: Styles applied to the label of each popup item..popup-item .button
: Button for each popup item, containing just the icon.
If you're using the Navbar Card, you might notice it could collide with other cards on your dashboard. A simple way to fix this is by adding some padding to your Home Assistant views. The easiest way to do that is by using card-mod with a custom theme.
Here's an example of how you can tweak your theme to adjust the layout for both desktop and mobile:
your_theme:
card-mod-theme: your_theme
card-mod-root-yaml: |
.: |
/* Add padding to the left (or other sides, depending on your navbar position) for desktop screens */
@media (min-width: 768px) {
hui-sections-view {
padding-left: 100px !important;
}
}
/* Add bottom padding for mobile screens to prevent cards from overlapping with the navbar */
@media (max-width: 767px) {
hui-sections-view:after {
content: "";
display: block;
height: 80px;
width: 100%;
background-color: transparent;
}
}
Another useful styling detail, is removing the native ha-tabs element on the top of the screen. We want to hide the ha-tabs element, but keep the edit, search and assist buttons visible. To do so, once again, using card-mod and custom themes is quite easy:
your_theme:
app-header-background-color: transparent
app-header-text-color: var(--primary-text-color)
card-mod-theme: your_theme
card-mod-root-yaml: |
.: |
ha-tabs {
pointer-events: none;
opacity: 0;
}
your_theme:
app-header-background-color: transparent
app-header-text-color: var(--primary-text-color)
card-mod-theme: your_theme
card-mod-root-yaml: |
.: |
.toolbar > sl-tab-group {
pointer-events: none;
opacity: 0;
}
Basic example
type: custom:navbar-card
desktop:
position: left
min_width: 768
show_labels: true
mobile:
show_labels: false
routes:
- icon: mdi:home-outline
icon_selected: mdi:home-assistant
url: /lovelace/home
label: Home
- icon: mdi:devices
url: /lovelace/devices
label: Devices
hold_action:
action: navigate
navigation_path: /config/devices/dashboard
- icon: mdi:thermometer
url: /lovelace/weather
label: Weather
- icon: mdi:creation-outline
icon_selected: mdi:creation
url: /lovelace/control
label: Control
- icon: mdi:dots-horizontal
label: More
tap_action:
action: open-popup
popup:
- icon: mdi:cog
url: /config/dashboard
- icon: mdi:hammer
url: /developer-tools/yaml
- icon: mdi:power
tap_action:
action: call-service
service: homeassistant.restart
service_data: {}
confirmation:
text: Are you sure you want to restart Home Assistant?
badge:
show: >
[[[ states['binary_sensor.docker_hub_update_available'].state === 'on' ]]]
color: var(--primary-color)
Custom primary color
type: custom:navbar-card
routes:
- url: /lovelace/home
label: Home
icon: mdi:home-outline
icon_selected: mdi:home-assistant
- url: /lovelace/devices
label: Devices
icon: mdi:devices
styles: |
.navbar {
--navbar-primary-color: red;
}
Custom background color
type: custom:navbar-card
routes:
- url: /lovelace/home
label: Home
icon: mdi:home-outline
icon_selected: mdi:home-assistant
- url: /lovelace/devices
label: Devices
icon: mdi:devices
styles: |
.navbar {
background: #000000;
}
No rounded corners only in desktop mode
type: custom:navbar-card
routes:
- url: /lovelace/home
label: Home
icon: mdi:home-outline
icon_selected: mdi:home-assistant
- url: /lovelace/devices
label: Devices
icon: mdi:devices
styles: |
.navbar.desktop{
border-radius: 0px;
}
More spacing on desktop mode and "bottom" position
type: custom:navbar-card
desktop:
position: bottom
routes:
- url: /lovelace/home
label: Home
icon: mdi:home-outline
icon_selected: mdi:home-assistant
- url: /lovelace/devices
label: Devices
icon: mdi:devices
styles: |
.navbar.desktop.bottom {
bottom: 100px;
}
Display route only for a given user
type: custom:navbar-card
desktop:
position: bottom
routes:
- url: /lovelace/home
label: Home
icon: mdi:home-outline
icon_selected: mdi:home-assistant
- url: /lovelace/devices
label: Devices
icon: mdi:devices
- url: /lovelace/settings
label: Settings
icon: mdi:cog
# This route will only be displayed for user "jose"
show: |
[[[ return user.name == "jose"]]]
Force one route to always be selected
type: custom:navbar-card
desktop:
position: bottom
routes:
- url: /lovelace/home
label: Home
selected: true # force `selected` field to true
icon: mdi:home-outline
icon_selected: mdi:home-assistant
- url: /lovelace/devices
label: Devices
icon: mdi:devices
- url: /lovelace/settings
label: Settings
icon: mdi:cog