Bubble Card
Bubble Card is a minimalist and customizable card collection for Home Assistant with a nice pop-up touch.
Table of contents
Installation
Configuration
Pop-up
Horizontal buttons stack
Button
Media player
Cover
Select
Separator
Empty column
Sub-buttons
Card layouts
Actions
Styling
Templates
Conflicts
Help
Donate
Installation
Home Assistant lowest supported version: 2023.9.0
Without HACS
1. Download these files: [bubble-card.js](https://raw.githubusercontent.com/Clooos/Bubble-Card/main/dist/bubble-card.js) and [bubble-pop-up-fix.js](https://raw.githubusercontent.com/Clooos/Bubble-Card/main/dist/bubble-pop-up-fix.js)
2. Add these files to your `/www` folder
3. On your dashboard click on the icon at the right top corner then on `Edit dashboard`
4. Click again on that icon and then click on `Manage resources`
5. Click on `Add resource`
6. Copy and paste this: `/local/bubble-card.js?v=1`
7. Click on `JavaScript Module` then `Create`
8. Go back and refresh your page
9. You can now click on `Add card` in the bottom right corner and search for `Bubble Card`
10. After any update of the file you will have to edit `/local/bubble-card.js?v=1` and change the version to any higher number
If it's not working, just try to clear your browser cache.`
With HACS (Recommended)
This method allows you to get updates directly on the HACS main page
1. If HACS is not installed yet, download it following the instructions on [https://hacs.xyz/docs/setup/download/](https://hacs.xyz/docs/use/download/download/)
2. Proceed to the HACS initial configuration following the instructions on [https://hacs.xyz/docs/configuration/basic](https://hacs.xyz/docs/configuration/basic)
3. On your sidebar go to `HACS` > `Frontend`
4. Click on the `+` button at the bottom right corner
5. Now search for `Bubble Card` and then click on the button at the bottom right corner to download it
6. Go back on your dashboard and click on the icon at the right top corner then on `Edit dashboard`
7. You can now click on `Add card` in the bottom right corner and search for `Bubble Card`
If it's not working, try to clear your browser cache.
#### Videos
You can also take a look at my YouTube channel for step by step videos.
[![YouTube](https://img.shields.io/badge/YouTube-My%20channel-red?logo=youtube)](https://www.youtube.com/@cloooos)
Configuration
All options can be configured in the Home Assistant editor. But you can find more details and the YAML in the documentation below.
**Main options (YAML + description)
**
| Name | Type | Requirement | Supported options | Description |
| --- | --- | --- | --- | --- |
| `type` | string | **Required** | `custom:bubble-card` | Type of the card |
| `card_type` | string | **Required** | `button`, `cover`, `empty-column`, `horizontal-buttons-stack`, `media-player`, `pop-up`, `select` or `separator` | Type of the Bubble Card, see below |
| `styles` | object list | Optional | Any CSS stylesheets | Allows you to customize your Bubble Card CSS, see [styling](#styling) |
Check out this video to learn about Bubble Card and its capabilities. My YouTube channel is quite new and focuses on tutorials about Home Assistant and Bubble Card. Don’t hesitate to subscribe to help increase my channel’s visibility. Thank you in advance!
Pop-up
This card allows you to convert any vertical stack into a pop-up. Each pop-up is hidden by default and can be opened by targeting its link (e.g. '#pop-up-name'
), with any card that supports the navigate
action, or with the horizontal buttons stack that is included.
[!IMPORTANT]
This card must be placed within a vertical stack card at the topmost position to function properly. To avoid misalignment with your view, place vertical stacks/pop-ups after all other dashboard cards. It should be called from the same view to work.
How to create a pop-up in the editor
1. To add a pop-up you first need to add a `Vertical stack` card to your dashboard.
2. This `Vertical stack` must be after all your other cards in your view order and before your horizontal buttons stack if you have one. In a section view type it can be placed anywhere.
3. Now add a `Bubble Card` with the `Pop-up` type.
4. Just fill in the `Hash` input and the ones you need.
**You can also watch [this step by step video](https://www.youtube.com/watch?v=7mOV7BfWoFc).**
[!TIP]
Pop-up trigger
This feature allows you to open a pop-up based on the state of any entity, for example, you can open a "Security" pop-up with a camera when a person is in front of your house. You can also create a toggle helper (input_boolean) and trigger its opening/closing in an automation.
Opening a pop-up when a binary_sensor
is on
```yaml
type: custom:bubble-card
card_type: pop-up
hash: '#kitchen'
name: Security
icon: mdi:video
trigger_entity: binary_sensor.front_door_motion
trigger_state: 'on'
trigger_close: true
```
Different ways to close a pop-up
They are many ways to close a pop-up. For instance, you can swipe from the pop-up header to the bottom, by doing a long swipe inside the pop-up to the bottom, by pressing Escape on desktop, by removing the hash in the URL or by simply pressing the close button.
Pop-up initialization fix
If you notice that pop-up content appears upon page load, consider installing this fix as an additional module.
Installation
You can do this by adding `bubble-pop-up-fix.js` to your `configuration.yaml` like so:
```yaml
frontend:
extra_module_url:
- /hacsfiles/Bubble-Card/bubble-pop-up-fix.js
```
If you didn't install it with HACS, change the path accordingly. Then, clear your browser cache.
For Android Home Assistant Companion App users, you can close the app, then clear the app cache. If it's still not working, you can close and restart the app again.
For iOS Home Assistant Companion App users, you can go to your Home Assistant settings, then navigate to Companion App > Debug > Clear Frontend Cache (or something similar), then refresh the page or restart the app.
For previous users of the **Optimized mode**, you will need to replace your `type: custom:bubble-pop-up` with this in YAML mode:
```yaml
type: vertical-stack
cards:
- type: custom:bubble-card
card_type: pop-up
```
Pop-up options
**Options (YAML + descriptions)
**
| Name | Type | Requirement | Supported options | Description |
| --- | --- | --- | --- | --- |
| `hash` | string | **Required** | Any unique hash (e.g. `'#kitchen'`) with ' ' | This is how you will open your pop-up |
| `auto_close` | string | Optional | A timeout in milliseconds (e.g. `10000` for 10s) | Auto close the pop-up after a timeout |
| `close_on_click` | boolean | Optional | `true` or `false` (default) | Automatically close the pop-up after any interaction |
| `close_by_clicking_outside` | boolean | Optional | `true` (default) or `false` | Close the pop-up by clicking outside of it |
| `width_desktop` | string | Optional | Any CSS value | Width on desktop (`100%` by default on mobile) |
| `margin` | string | Optional | Any CSS value | Use this **only** if your pop-up is not well centered on mobile (e.g. `13px`) |
| `margin_top_mobile` | string | Optional | Any CSS value | Top margin on mobile (e.g. `-56px` if your header is hidden) |
| `margin_top_desktop` | string | Optional | Any CSS value | Top margin on desktop (e.g. `50vh` for a half-sized pop-up or `calc(100vh - 400px)` for a fixed height of `400px`) |
| `bg_color` | string | Optional | Any hex, rgb or rgba value | The background color of your pop-up (e.g. `#ffffff` for a white background) |
| `bg_opacity` | string | Optional | Any value from `0` to `100` | The background opacity of your pop-up (e.g. `100` for no transparency) |
| `bg_blur` | string | Optional | Any value from `0` to `100` | The background blur effect of your pop-up, **this only work if `bg_opacity` is not set to `100`** (e.g. `0` for no blur)|
| `shadow_opacity` | string | Optional | Any value from `0` to `100` | The shadow opacity of your pop-up (e.g. `0` to hide it) |
| `hide_backdrop` | boolean | Optional | `true` or `false` (default) | Set this to true on the first pop-up of your main dashboard to disable the backdrop on all pop-ups. |
| `background_update` | boolean | Optional | `true` or `false` (default) | Update pop-up content in background (not recommended) |
| `trigger_entity` | string | Optional | Any entity | Open this pop-up based on the state of any entity |
| `trigger_state` | string | Optional (**Required** if `trigger_entity` is defined) | Any entity state | Entity state to open the pop-up |
| `trigger_close` | boolean | Optional | `true` or `false` (default) | Close the pop-up when `trigger_state` is different |
| `open_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Trigger an action when the pop-up is opening |
| `close_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Trigger an action when the pop-up is closing |
| `card_layout` | string | Optional | `normal` (default), `large`, `large-2-rows` | Styling layout of the header, see [card layouts](#card-layouts) |
| `show_header` | boolean | Optional | `true` or `false` (default) | Show/Hide the pop-up header fully |
| You also have access to [all the button settings](#button) for the header of the pop-up. | | Optional | | If undefined no header will be shown |
Examples
A pop-up
```yaml
type: vertical-stack
cards:
- type: custom:bubble-card
card_type: pop-up
hash: '#kitchen'
name: Kitchen
icon: mdi:fridge
entity: light.kitchen
```
A button to open the pop-up
```yaml
type: custom:bubble-card
card_type: button
button_type: name
name: Kitchen
icon: mdi:fridge
button_action:
tap_action:
action: navigate
navigation_path: '#kitchen'
```
A pop-up with a fixed height
Replace `400px` with the size you need.
```yaml
type: vertical-stack
cards:
- type: custom:bubble-card
card_type: pop-up
hash: '#kitchen'
name: Kitchen
icon: mdi:fridge
entity: light.kitchen
margin_top_mobile: calc(100vh - 400px)
margin_top_desktop: calc(100vh - 400px)
```
Horizontal buttons stack
This card is a good companion to the pop-up card, allowing you to open the corresponding pop-ups. It also allows you to open any page of your dashboard. In addition, you can add your motion/occupancy sensors so that the order of the buttons adapts according to the room you just entered. This card is scrollable, remains visible, and acts as a footer.
[!IMPORTANT]
This card has to be the last one in your view (after every card and pop-up). It can't be inside any stack.
Horizontal buttons stack options
**Options (YAML + descriptions)
**
| Name | Type | Requirement | Supported options | Description |
| --- | --- | --- | --- | --- |
| `1_link` | string | **Required** | The pop-up hash (e.g. `'#kitchen'`) with ' ' or any link | A link to open |
| `1_name` | string | Optional | Any string | A name for your button |
| `1_icon` | string | Optional | Any `mdi:` icon | An icon for your button |
| `1_entity` | string | Optional | Any light or light group | Display the color of that light in background |
| `1_pir_sensor` | string | Optional | Any binary sensor | At least one pir sensor or more for `auto_order`, in fact it also works with any entity type, for example you can add light groups and the order will change based on the last changed states. |
| `auto_order` | boolean | Optional | `true` or `false` (default) | Change the order of the buttons according to the `_pir_sensor` last changed time, **it needs to be `false` if you don't have any `_pir_sensor` in your code** |
| `margin` | string | Optional | Any CSS value | Use this **only** if your `horizontal-buttons-stack` is not well centered on mobile (e.g. `13px`) |
| `width_desktop` | string | Optional | Any CSS value | Width on desktop (`100%` by default on mobile) |
| `is_sidebar_hidden` | boolean | Optional | `true` or `false` (default) | Fix the horizontal buttons stack position if the sidebar is hidden on the desktop (only if you have made a modification to hide it yourself) |
| `rise_animation` | boolean | Optional | `true` (default) or `false` | Set this to `false` to disable the animation that activates once the page has loaded |
| `highlight_current_view` | boolean | Optional | `true` or `false` (default) | Highlight current hash / view with a smooth animation |
| `hide_gradient` | boolean | Optional | `true` or `false` (default) | Set this to `false` to hide the gradient |
> [!IMPORTANT]
> The variables starting with a number define your buttons, just change this number to add more buttons (see example below).
Example
An horizontal buttons stack that reorganize itself based on occupancy sensors
```yaml
type: custom:bubble-card
card_type: horizontal-buttons-stack
auto_order: true
1_name: Living room
1_icon: mdi:sofa
1_link: '#living-room'
1_entity: light.living_room
1_pir_sensor: binary_sensor.living_room_motion
2_name: Kitchen
2_icon: mdi:fridge
2_link: '#kitchen'
2_entity: light.kitchen
2_pir_sensor: binary_sensor.kitchen_motion
3_name: Dining room
3_icon: mdi:silverware-fork-knife
3_link: '#dining-room'
3_entity: light.dining_room
3_pir_sensor: binary_sensor.dining_room_motion
```
Button
This card allows you to control your entities and can be customized in many ways. To access color / control of an entity, simply tap on the icon.
[!TIP]
What are the differences between all the button types?
-
The button switch is the default one. By default, it toggles an entity and its background color changes based on the entity’s state or the color of a light.
-
The button slider can control the brightness of a light, the volume of a media player, the position of a cover, and it also supports input numbers. Its background color can change based on the color of a light.
-
The button state is perfect for displaying information from a sensor or any entity. When you press it, it will show the "More info" panel of the entity. Its background color does not change.
-
The button name is the only one that doesn't need an entity and allows you to display a short text, a name or a title. You can also add some actions to it. Its background color does not change.
Button options
**Options (YAML + descriptions)
**
| Name | Type | Requirement | Supported options | Description |
| --- | --- | --- | --- | --- |
| `entity` | string | **Required** | Any entity | An entity to control |
| `button_type` | string | Optional | `switch` (default), `slider`, `state` or `name` | The behavior of your button |
| `name` | string | Optional | Any string | A name for your button, if not defined it will display the entity name |
| `icon` | string | Optional | Any `mdi:` icon | An icon for your button, if not defined it will display the entity icon or the `entity-picture` |
| `force_icon` | boolean | Optional | `true` or `false` (default) | Give the priority to the icon instead of the `entity-picture` |
| `show_state` | boolean | Optional | `true` or `false` (default) | Show or hide the state of your `entity` |
| `show_name` | boolean | Optional | `true` (default) or `false` | Show or hide the name |
| `show_icon` | boolean | Optional | `true` (default) or `false` | Show or hide the icon |
| `show_last_changed` | boolean | Optional | `true` or `false` (default) | Show the last changed time of your `entity` |
| `show_attribute` | boolean | Optional | `true` or `false` (default) | Show an attribute of your `entity` below its `name` |
| `attribute` | string | Optional (required if `show_attribute` is set to `true`) | An attribute from your `entity` | The attribute to show (e.g. `brightness`) |
| `scrolling_effect` | boolean | Optional | `true` (default) or `false` | Allow text to scroll when the content exceeds the size of their container |
| `button_action` | object | Optional | `tap_action`, `double_tap_action` or `hold_action`, see below | Allow to change the default actions on button click. Not available for the `slider` type. |
| `tap_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon click, if undefined, `more-info` will be used. |
| `double_tap_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon double click, if undefined, `toggle` will be used. |
| `hold_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon hold, if undefined, `more-info` will be used. |
| `card_layout` | string | Optional | `normal` (default), `large`, `large-2-rows` | Styling layout of the card, see [card layouts](#card-layouts) |
| `columns` | string | Optional | `1`, `2`, `3` or `4` (default) | Number of columns when placed in a **section view** (e.g. `2` is 2/4) |
| `rows` | string | Optional | `1` (default), `2`, `3` or `4` | Number of rows when placed in a **section view** (e.g. `2` is 2/4) |
| `sub_button` | object | Optional | See [sub-buttons](#sub-buttons) | Add customized buttons fixed to the right |
Examples
A slider button that can control the brightness of a light
```yaml
type: custom:bubble-card
card_type: button
button_type: slider
entity: light.kitchen_led
name: Kitchen LED
icon: mdi:led-strip-variant
```
A button with all the options
```yaml
entity: light.your_light
button_type: switch
show_icon: true
force_icon: true
show_name: true
show_last_changed: true
show_state: true
show_last_updated: true
show_attribute: true
attribute: brightness
scrolling_effect: true
card_layout: large
button_action:
tap_action:
action: toggle
tap_action:
action: more-info
sub_button:
- entity: light.your_light
icon: ''
show_state: false
show_attribute: true
attribute: brightness
show_icon: false
show_background: false
show_name: false
```
Media player
This card allows you to control a media player. You can tap on the icon to get more control.
Media player options
**Options (YAML + descriptions)
**
| Name | Type | Requirement | Supported options | Description |
| --- | --- | --- | --- | --- |
| `entity` | string | **Required** | Any media player | The media player to control |
| `name` | string | Optional | Any string | A name for your media player, if not defined it will display the entity name |
| `icon` | string | Optional | Any `mdi:` icon | An icon for your media player, if not defined it will display the entity icon or the `entity-picture` |
| `force_icon` | boolean | Optional | `true` or `false` (default) | Give the priority to the icon instead of the `entity-picture` |
| `show_state` | boolean | Optional | `true` or `false` (default) | Show or hide the state of your `entity` |
| `show_name` | boolean | Optional | `true` (default) or `false` | Show or hide the name |
| `show_icon` | boolean | Optional | `true` (default) or `false` | Show or hide the icon |
| `show_last_changed` | boolean | Optional | `true` or `false` (default) | Show the last changed time of your `entity` |
| `show_attribute` | boolean | Optional | `true` or `false` (default) | Show an attribute of your `entity` below its `name` |
| `attribute` | string | Optional (required if `show_attribute` is set to `true`) | An attribute from your `entity` | The attribute to show (e.g. `brightness`) |
| `scrolling_effect` | boolean | Optional | `true` (default) or `false` | Allow text to scroll when the content exceeds the size of their container |
| `tap_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon click, if undefined, `more-info` will be used. |
| `double_tap_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon double click, if undefined, `toggle` will be used. |
| `hold_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon hold, if undefined, `more-info` will be used. |
| `card_layout` | string | Optional | `normal` (default), `large`, `large-2-rows` | Styling layout of the card, see [card layouts](#card-layouts) |
| `columns` | string | Optional | `1`, `2`, `3` or `4` (default) | Number of columns when placed in a **section view** (e.g. `2` is 2/4) |
| `rows` | string | Optional | `1` (default), `2`, `3` or `4` | Number of rows when placed in a **section view** |
| `sub_button` | object | Optional | See [sub-buttons](#sub-buttons) | Add customized buttons fixed to the right |
| `hide` | object | Optional | See below | Show or hide buttons |
#### Hide options
| Name | Type | Requirement | Supported options | Description |
| --- | --- | --- | --- | --- |
| `play_pause_button` | boolean | Optional | `true` (default) or `false` | Show or hide the play/pause button |
| `volume_button` | boolean | Optional | `true` (default) or `false` | Show or hide the volume button |
| `previous_button` | boolean | Optional | `true` (default) or `false` | Show or hide the previous button |
| `next_button` | boolean | Optional | `true` (default) or `false` | Show or hide the next button |
| `power_button` | boolean | Optional | `true` (default) or `false` | Show or hide the power button |
Examples
A media player with all the options
```yaml
type: custom:bubble-card
card_type: media-player
name: Media player
entity: media_player.your_media_player
show_state: true
show_last_updated: true
show_attribute: true
attribute: assumed_state
card_layout: large
scrolling_effect: false
show_icon: false
force_icon: true
show_name: false
show_last_changed: true
columns: 2
rows: 1
tap_action:
action: toggle
hide:
play_pause_button: true
volume_button: true
previous_button: true
next_button: true
power_button: true
sub_button:
- entity: media_player.salon_2
icon: mdi:volume-high
name: Volume level
tap_action:
action: more-info
show_name: false
show_state: false
show_last_updated: false
show_attribute: true
show_background: false
attribute: volume_level
```
Cover
This card allows you to control your covers.
Cover options
**Options (YAML + descriptions)
**
| Name | Type | Requirement | Supported options | Description |
| --- | --- | --- | --- | --- |
| `entity` | string | **Required** | Any cover | A cover to control |
| `name` | string | Optional | Any string | A name for your cover, if not defined it will display the entity name |
| `force_icon` | boolean | Optional | `true` or `false` (default) | Give the priority to the icon instead of the `entity-picture` |
| `show_state` | boolean | Optional | `true` or `false` (default) | Show or hide the state of your `entity` |
| `show_name` | boolean | Optional | `true` (default) or `false` | Show or hide the name |
| `show_icon` | boolean | Optional | `true` (default) or `false` | Show or hide the icon |
| `show_last_changed` | boolean | Optional | `true` or `false` (default) | Show the last changed time of your `entity` |
| `show_attribute` | boolean | Optional | `true` or `false` (default) | Show an attribute of your `entity` below its `name` |
| `attribute` | string | Optional (required if `show_attribute` is set to `true`) | An attribute from your `entity` | The attribute to show (e.g. `brightness`) |
| `scrolling_effect` | boolean | Optional | `true` (default) or `false` | Allow text to scroll when the content exceeds the size of their container |
| `icon_open` | string | Optional | Any `mdi:` icon | An icon for your open cover, if not defined it will display the default open cover icon |
| `icon_close` | string | Optional | Any `mdi:` icon | An icon for your closed cover, if not defined it will display the default closed cover icon |
| `icon_up` | string | Optional | Any `mdi:` icon | An icon for your open cover button, if not defined it will display the default open cover icon |
| `icon_down` | string | Optional | Any `mdi:` icon | An icon for your close cover button, if not defined it will display the default close cover icon |
| `open_service` | string | Optional | Any service or script | A service to open your cover, default to `cover.open_cover` |
| `stop_service` | string | Optional | Any service or script | A service to stop your cover, default to `cover.stop_cover` |
| `close_service` | string | Optional | Any service or script | A service to close your cover, default to `cover.close_cover` |
| `tap_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon click, if undefined, `more-info` will be used. |
| `double_tap_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon double click, if undefined, `toggle` will be used. |
| `hold_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon hold, if undefined, `more-info` will be used. |
| `card_layout` | string | Optional | `normal` (default), `large`, `large-2-rows` | Styling layout of the card, see [card layouts](#card-layouts) |
| `columns` | string | Optional | `1`, `2`, `3` or `4` (default) | Number of columns when placed in a **section view** (e.g. `2` is 2/4) |
| `rows` | string | Optional | `1` (default), `2`, `3` or `4` | Number of rows when placed in a **section view** |
| `sub_button` | object | Optional | See [sub-buttons](#sub-buttons) | Add customized buttons fixed to the right |
Example
A card that can control a roller shade
```yaml
type: custom:bubble-card
card_type: cover
entity: cover.kitchen
name: Kitchen
icon_open: mdi:roller-shade
icon_close: mdi:roller-shade-closed
```
Select
This card allows you to add a dropdown menu for your input_select
/ select
entities. This card also supports the sub-buttons and all the common Bubble Card features.
[!TIP]
You can also have select sub-buttons if you want, this feature is available in all the cards that support the sub-buttons.
Select options
**Options (YAML + descriptions)
**
| Name | Type | Requirement | Supported options | Description |
| --- | --- | --- | --- | --- |
| `entity` | string | **Required** | Any entity | An entity to control |
| `name` | string | Optional | Any string | A name for your select, if not defined it will display the entity name |
| `icon` | string | Optional | Any `mdi:` icon | An icon for your select, if not defined it will display the entity icon or the `entity-picture` |
| `force_icon` | boolean | Optional | `true` or `false` (default) | Give the priority to the icon instead of the `entity-picture` |
| `show_state` | boolean | Optional | `true` or `false` (default) | Show or hide the state of your `entity` |
| `show_name` | boolean | Optional | `true` (default) or `false` | Show or hide the name |
| `show_icon` | boolean | Optional | `true` (default) or `false` | Show or hide the icon |
| `show_last_changed` | boolean | Optional | `true` or `false` (default) | Show the last changed time of your `entity` |
| `show_attribute` | boolean | Optional | `true` or `false` (default) | Show an attribute of your `entity` below its `name` |
| `attribute` | string | Optional (required if `show_attribute` is set to `true`) | An attribute from your `entity` | The attribute to show (e.g. `brightness`) |
| `scrolling_effect` | boolean | Optional | `true` (default) or `false` | Allow text to scroll when the content exceeds the size of their container |
| `tap_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon click, if undefined, `more-info` will be used. |
| `double_tap_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon double click, if undefined, `toggle` will be used. |
| `hold_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on icon hold, if undefined, `more-info` will be used. |
| `card_layout` | string | Optional | `normal` (default), `large`, `large-2-rows` | Styling layout of the card, see [card layouts](#card-layouts) |
| `columns` | string | Optional | `1`, `2`, `3` or `4` (default) | Number of columns when placed in a **section view** (e.g. `2` is 2/4) |
| `rows` | string | Optional | `1` (default), `2`, `3` or `4` | Number of rows when placed in a **section view** (e.g. `2` is 2/4) |
| `sub_button` | object | Optional | See [sub-buttons](#sub-buttons) | Add customized buttons fixed to the right |
Examples
A select card with a list of scenes
```yaml
type: custom:bubble-card
card_type: select
name: Scene
entity: input_select.scenes
icon: mdi:brightness-4
show_state: true
```
Separator
This card is a simple separator for dividing your pop-up into categories / sections. e.g. Lights, Devices, Covers, Settings, Automations...
Separator options
**Options (YAML + descriptions)
**
| Name | Type | Requirement | Supported options | Description |
| --- | --- | --- | --- | --- |
| `name` | string | Optional but recommended | Any string | A name for your separator |
| `icon` | string | Optional but recommended | Any `mdi:` icon | An icon for your separator |
| `card_layout` | string | Optional | `normal` (default), `large`, `large-2-rows` | Styling layout of the card, see [card layouts](#card-layouts) |
| `columns` | string | Optional | `1`, `2`, `3` or `4` (default) | Number of columns when placed in a **section view** (e.g. `2` is 2/4) |
| `rows` | string | Optional | `1` (default), `2`, `3` or `4` | Number of rows when placed in a **section view** |
| `sub_button` | object | Optional | See [sub-buttons](#sub-buttons) | Add customized buttons fixed to the right |
Example
A separator/divider for a "Covers" section
```yaml
type: custom:bubble-card
card_type: separator
name: Covers
icon: mdi:window-shutter
```
Empty column
This card is here to fill an empty column. This is useful if you have a horizontal-stack
in your pop-up with only one card. Take a look at the bottom right corner of this screenshot to (not) see it.
Empty column options
This card has no options and doesn’t support styling, though it does support layout options for HA sections.
Example
An empty column in an horizontal stack
```yaml
type: horizontal-stack
cards:
- type: custom:bubble-card
card_type: button
...
- type: custom:bubble-card
card_type: empty-column
```
Sub-buttons
In every card that supports that option, you can add sub-buttons to customize your cards even more. You can, for exemple, create a button that can control a vacuum, a weather card, or almost anything that you can come up with. These sub-buttons support the tap actions and most of the button options.
Sub-buttons options
**Options (YAML + description)
**
| Name | Type | Requirement | Supported options | Description |
| --- | --- | --- | --- | --- |
| `entity` | string | Optional | Any entity | An entity to control |
| `name` | string | Optional | Any string | A name for your sub-button, if not defined it will display the entity name |
| `icon` | string | Optional | Any `mdi:` icon | An icon for your sub-button, if not defined it will display the entity icon |
| `show_background` | boolean | Optional | `true` (default) or `false` | Show a background for your sub-button, it will change its color based on your entity state |
| `show_state` | boolean | Optional | `true` or `false` (default) | Show or hide the state of your `entity` |
| `show_name` | boolean | Optional | `true` or `false` (default) | Show or hide the name |
| `show_icon` | boolean | Optional | `true` (default) or `false` | Show or hide the icon |
| `show_last_changed` | boolean | Optional | `true` or `false` (default) | Show the last changed time of your `entity` |
| `show_attribute` | boolean | Optional | `true` or `false` (default) | Show an attribute of your `entity` below its `name` |
| `attribute` | string | Optional (required if `show_attribute` is set to `true`) | An attribute from your `entity` | The attribute to show (e.g. `brightness`) |
| `tap_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on sub-button click, if undefined, `more-info` will be used. |
| `double_tap_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on sub-button double click, if undefined, `toggle` will be used. |
| `hold_action` | object | Optional | See [actions](#tap-double-tap-and-hold-actions) | Define the type of action on sub-button hold, if undefined, `more-info` will be used. |
Examples
A button with some sub-buttons to make a vacuum card (like on the screenshot)
```yaml
type: custom:bubble-card
card_type: button
button_type: switch
name: Vacuum
entity: vacuum.downstairs
icon: mdi:robot-vacuum
show_state: true
show_last_changed: true
tap_action:
action: more-info
button_action:
tap_action:
action: more-info
sub_button:
- name: Battery
icon: mdi:battery
show_name: false
show_icon: true
show_background: false
show_attribute: true
attribute: battery_level
- name: Return to dock
icon: mdi:home
show_background: false
tap_action:
action: call-service
service: vacuum.return_to_base
target:
entity_id: vacuum.downstairs
- name: Pause
icon: mdi:pause
show_background: false
tap_action:
action: call-service
service: vacuum.pause
target:
entity_id: vacuum.downstairs
- name: Start
icon: mdi:play
tap_action:
action: call-service
service: vacuum.start
target:
entity_id: vacuum.downstairs
styles: >-
.bubble-button-card-container {
/* Change the background color when the vacuum get an error (optional), more details in the styles template section */
background: ${state === 'error' ? 'rgb(200, 80, 40)' : ''} !important;
}
/* Change the first sub-button battery icon based on the battery_icon attribute, more details in the styles template section */
${subButtonIcon[0].setAttribute("icon", hass.states['vacuum.downstairs'].attributes.battery_icon)}
```
A button slider with a sub-button that shows the brightness and one that toggle the light (like on the screenshot)
```yaml
type: custom:bubble-card
card_type: button
button_type: slider
name: Kitchen
entity: light.kitchen
icon: mdi:fridge-outline
show_last_updated: true
sub_button:
- name: Brightness
icon: mdi:fridge-outline
show_icon: false
show_background: false
show_attribute: true
attribute: brightness
- name: Toggle button
icon: mdi:lightbulb
tap_action:
action: toggle
```
A button that shows the inside and outside temperature with the weather for today and tomorrow (screenshot included)
> Bad luck for me it's cloudy all the time but all the icons are changing based on the weather.
```yaml
type: custom:bubble-card
card_type: button
button_type: state
entity: weather.openweathermap
name: Weather
show_state: true
card_layout: large-2-rows
sub_button:
- name: Home temperature
icon: mdi:home-thermometer-outline
entity: sensor.home_temperature
show_state: true
show_icon: true
show_background: false
- name: Outside temperature
entity: sensor.outside_temperature
show_state: true
show_background: false
- name: Today
entity: sensor.home_realfeel_temperature_max_0d
show_name: true
show_state: true
tap_action:
action: more-info
- name: Tomorrow
entity: sensor.home_realfeel_temperature_max_1d
show_name: true
show_state: true
show_background: false
styles: >-
/* Change the third and fourth sub-button icon based on the forecast.condition attribute, more details in the styles template section */
${subButtonIcon[2].setAttribute("icon", getWeatherIcon(hass.states['sensor.weather_forecast_daily'].attributes.forecast[0]?.condition))}
${subButtonIcon[3].setAttribute("icon", getWeatherIcon(hass.states['sensor.weather_forecast_daily'].attributes.forecast[1]?.condition))}
```
Card layouts
Bubble Card fully supports the Home Assistant section view, you can change the card layout to make the card bigger and also change the number of columns or rows the card should occupy in your section view (only on the cards that support that option). These layouts are also supported in all other view types.
**Available card layouts
**
| Layout | Description |
| --- | --- |
| `normal` | The regular layout (not optimized for the section view) |
| `large` | A larger layout (optimized for the section view) |
| `large-2-rows` | A larger layout with 2 rows of sub-buttons (optimized for the section view) |
Example
A large button that shows energy statistics with 2 rows of sub-buttons (screenshot included)
```yaml
type: custom:bubble-card
card_type: button
button_type: state
card_layout: large-2-rows
name: Energy
entity: sensor.current_power_production
icon: mdi:home-lightning-bolt-outline
show_state: true
button_action:
tap_action:
action: navigate
navigation_path: '#energy'
sub_button:
- entity: sensor.electricity_counter
icon: mdi:counter
show_background: false
show_state: true
tap_action:
action: more-info
- entity: sensor.today_s_energy_production
show_state: true
show_background: false
- entity: sensor.average_daily_consumption
show_background: false
show_state: true
- entity: sensor.this_week_production
show_state: true
show_background: false
icon: mdi:calendar-week
```
Tap, double tap and hold actions
You can also use Home Assistant default tap actions, double tap actions and hold actions on the cards that supports this option. For example, this allows you to display the “more info” window by holding a button icon or running a service when a sub-button is pressed.
Action options
**Options (YAML + description)
**
| Name | Type | Supported options | Description |
| --- | --- | --- | --- |
| `action` | string | `more-info`, `toggle`, `call-service`, `navigate`, `url`, `fire-dom-event`, `none` | Action to perform |
| `target` | object | | Only works with `call-service`. Follows the [home-assistant syntax](https://www.home-assistant.io/docs/scripts/service-calls/#targeting-areas-and-devices) |
| `navigation_path` | string | Any path of your dashboard | Path to navigate to (e.g. `'#kitchen'` for opening a pop-up) when action defined as navigate |
| `url_path` | string | Any link | URL to open on click (e.g. `https://www.google.com`) when action is `url` |
| `service` | string | Any service | Service to call (e.g. `media_player.media_play_pause`) when `action` defined as `call-service` |
| `data` or `service_data` | object | Any service data | Service data to include (e.g. `entity_id: media_player.kitchen`) when `action` defined as `call-service` |
| `confirmation` | object | See [confirmation](https://www.home-assistant.io/dashboards/actions/#options-for-confirmation) | Display a confirmation pop-up (not a Bubble Card one), overrides the default `confirmation` object |
Example
A button to open a pop-up
```yaml
type: custom:bubble-card
card_type: button
button_type: name
name: Kitchen
icon: mdi:fridge
button_action:
tap_action:
action: navigate
navigation_path: '#kitchen'
```
Styling
You can add custom styles in the editor or by adding styles: |
in YAML without using card-mod which allows you to modify the CSS style of all the cards.
[!TIP]
To understand which style classes can be modified, you can take a look at the src/cards
folder in this repository. In each card folder, you will find a file named styles.ts
. These files contain all the applied styles.
You can also find a lot of examples on the Home Assistant forum by doing a bit of searching.
The Bubble theme for Home Assistant (like on the screenshots) can be found here.
[!IMPORTANT]
Please note that you will have to add !important;
to some CSS styles that are already defined (see examples below).
Examples
Changing the font size of any Bubble Card
```yaml
styles: |
* {
font-size: 16px !important;
}
```
Changing the background color of a single button in an horizontal buttons stack
```yaml
styles: >
/* Selector for the '#kitchen' button */
.kitchen > .color-background {
background-color: blue !important;
}
```
Changing the background color of a button
```yaml
styles: |
.bubble-button-card-container {
background: rgba(12,120,50,0.5) !important;
}
```
To change the color when it's `on` take a look at the style templates below.
Changing the color of a button slider
```yaml
styles: |
.bubble-range-fill {
background: rgba(79, 69, 87, 1) !important;
opacity: 1 !important;
}
```
Changing the line color of a separator
```yaml
styles: |
.bubble-line {
background: var(--primary-text-color);
opacity: 0.1;
}
```
Changing the color of an icon
```yaml
styles: |
.bubble-icon {
color: white !important;
}
```
For an horizontal buttons stack icon.
```yaml
.kitchen > .bubble-icon {
color: grey !important
}
```
Changing the background color of an icon container
```yaml
styles: |
.bubble-icon-container {
background: rgb(230, 128, 41);
}
```
Changing the size of the sub-buttons (perfect for the large layout)
```yaml
styles: |
.bubble-sub-button {
height: 48px !important;
min-width: 48px !important;
}
```
Changing the background color of the second sub-button
```yaml
styles: |
.bubble-sub-button-2 {
background-color: blue !important;
}
```
Changing the size of an icon
For the main icon.
```yaml
styles: |
.bubble-icon {
--mdc-icon-size: 26px !important;
}
```
For the sub-button icons.
```yaml
styles: |
.bubble-sub-button-icon {
--mdc-icon-size: 26px !important;
}
```
Using a picture rather than an icon in a sub button
```yaml
sub_button:
- icon: none
styles: |-
.bubble-sub-button-1 {
background-image: url("/local/pictures/your_picture.jpg");
background-size: cover;
}
```
Just upload this picture in a “pictures” folder (or the name you want) in the Home Assistant “www” folder.
Advanced example: Creating an horizontal row of sub-buttons (screenshot included)
> I really love this one, I use it as a header on my dashboard.
```yaml
type: custom:bubble-card
card_type: button
card_layout: large
button_type: name
show_icon: false
show_name: false
sub_button:
- name: Mute
icon: mdi:volume-off
tap_action:
action: toggle
service: input_boolean.toggle
entity: input_boolean.silent_mode
- name: Covers
entity: cover.all_group
show_background: false
tap_action:
action: navigate
navigation_path: '#cover'
- name: Shopping list
icon: mdi:cart-outline
show_background: false
tap_action:
action: navigate
navigation_path: '#shopping-list'
- name: Security
icon: mdi:video-outline
show_background: false
tap_action:
action: navigate
navigation_path: '#security'
- name: Settings
icon: mdi:cog
show_background: false
tap_action:
action: navigate
navigation_path: '#configuration'
styles: |
.card-content {
width: 100%;
margin: 0 !important;
}
.bubble-button-card-container {
background: none;
}
.bubble-sub-button {
height: 46px !important;
width: 46px !important;
}
.bubble-sub-button-container {
width: 100%;
justify-content: space-between !important;
}
.bubble-sub-button-icon {
--mdc-icon-size: inherit !important;
}
.bubble-name-container {
margin-right: 0px !important;
}
```
![Sub-buttons-everywhere](https://github.com/Clooos/Bubble-Card/assets/36499953/3bf04969-e00d-4755-89df-481e8f7d73b2)
Templates
Bubble Card doesn’t support Jinja templates but advanced users can add templates in JS directly in their custom styles. For example, this allows you to dynamically change an icon, the texts or the colors of an element, to show or hide an element conditionally (like a sub-button), or almost anything based on a state, an attribute and more.
[!TIP]
More information about JS templates here. My advice is to always take a look at your browser console to be sure that everything is working correctly.
Available variables and functions
Variables
You have access to these variables in most cards:
- `state` will return the state of your defined `entity`.
- `entity` will return your entity you defined like `switch.test` in this example.
- `icon` can be used like this to change the icon `icon.setAttribute("icon", "mdi:lightbulb")`.
- `subButtonIcon[0]` can be used like this to change the first sub-button icon `subButtonIcon[0].setAttribute("icon", "mdi:lightbulb")`, `[0]` is the first sub-button icon, `[1]` the second...
- `card` will return the card element in the DOM.
- `hass` is an advanced variable that allows you even more control, for example you can return the state of `light.kitchen` like this `hass.states['light.kitchen'].state` or an attribute like this `hass.states[entity].attributes.brightness`.
- `this` will return a lot of usefull informations about your setup and dashboard, only use this if you know what you are doing.
Functions (getWeatherIcon
)
You have access to all the global JS functions, but you have also access to:
- `getWeatherIcon` can be used to return a weather icon based on a state that return the weather. For example, you can can do this `${subButtonIcon[2].setAttribute("icon", getWeatherIcon(hass.states['sensor.weather_forecast_daily'].attributes.forecast[0]?.condition))}` to change the third sub-button icon to today's weather icon, `.forecast[1]?.condition` is for tomorrow...
You will have to create a template sensor for that. Here is what you can add in your `configuration.yaml`:
```yaml
- trigger:
- platform: time_pattern
hours: /2
action:
- service: weather.get_forecasts
data:
type: daily
target:
entity_id: weather.home
response_variable: daily
sensor:
- name: Weather Forecast Daily
unique_id: weather_forecast_daily
state: "{{ now().isoformat() }}"
attributes:
forecast: "{{ daily['weather.home'].forecast }}"
```
Examples
Changing the background color of a button that is red when it's off
and green when it's on
```yaml
type: custom:bubble-card
card_type: button
entity: switch.test
name: Test
styles: |
.bubble-button-background {
opacity: 1 !important;
background-color: ${state === 'on' ? 'blue' : 'red'} !important;
}
```
Changing the background color of a button based on an entity for the horizontal buttons stack
```yaml
styles: |
.kitchen > .color-background {
background-color: ${hass.states['light.kitchen'].state === 'on' ? 'blue' : 'red'} !important;
}
```
Showing/Hiding a sub-button conditionally
This one is showing the first sub-button only when my vacuum is stuck.
```yaml
styles: |
.bubble-sub-button-1 {
display: ${hass.states['vacuum.downstairs'].state === 'error' ? '' : 'none'} !important;
}
```
This one is showing a sub-button when the battery is below 10%. Usefull with a sub-button that shows "Low battery".
```yaml
styles: |
.bubble-sub-button-1 {
display: ${hass.states['vacuum.downstairs'].attributes.battery_level <= 10 ? '' : 'none'} !important;
}
```
Changing an icon or sub-button icon conditionally
This one is changing a button icon only when a vacuum is stuck.
```yaml
styles: |
${icon.setAttribute("icon", hass.states['vacuum.downstairs'].state === 'error' ? 'mdi:alert' : 'mdi:robot-vacuum')}
```
This one is changing the first sub-button icon only when a vacuum is stuck.
```yaml
styles: |
${subButtonIcon[0].setAttribute("icon", hass.states['vacuum.downstairs'].state === 'error' ? 'mdi:alert' : 'mdi:robot-vacuum')}
```
Changing an icon or sub-button icon color conditionally
This one is changing a button icon color based on its state.
```yaml
styles: |
.bubble-icon {
color: ${hass.states['light.your_light'].state === 'on' ? 'green' : 'red'} !important;
}
```
This one is changing a sub-button icon color based on its state. `.bubble-sub-button-1` is the first sub-button, replace `1` if you want to change another sub-button icon.
```yaml
styles: |
.bubble-sub-button-1 > ha-icon {
color: ${hass.states['light.your_light'].state === 'on' ? 'green' : 'red'} !important;
}
```
Animating a fan icon conditionally
This one is rotating a button icon when a fan is `on`.
```yaml
styles: |-
.bubble-icon {
animation: ${hass.states['fan.you_fan'].state === 'on' ? 'slow-rotate 2s linear infinite' : ''};
}
@keyframes slow-rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
```
Templating texts (like name or state)
This one is changing a button name/state with "It's currently sunny" depending on your weather.
```yaml
styles: |
${card.querySelector('.bubble-name').innerText = "It's currently " + hass.states['weather.home'].state}
```
If you want to template the state (`.bubble-state`) don't toggle `show_state: true` just toggle `show_attribute: true` without any attribute.
Advanced example: Changing the color of a sub-button when a pop-up is open
```yaml
styles: |
${window.addEventListener('location-changed', () => {
card.querySelector('.bubble-sub-button-1').style.backgroundColor = this.location.href.includes('#kitchen') ? 'blue' : '';
})}
```
Advanced example: Templating a separator name based on a state translated to your language
You can use `hass.formatEntityState(state)` to transtale a state and `hass.formatEntityAttributeValue(state, "attribute")` to translate an attribute.
This one is changing the name and the icon based on the weather, "Nuageux" means "Cloudy" in French.
![image](https://github.com/Clooos/Bubble-Card/assets/36499953/35ac9d0f-c3b8-4c09-9c15-fe6954011d55)
```yaml
type: custom:bubble-card
card_type: separator
icon: mdi:weather-cloudy
sub_button:
- entity: sensor.outside_temperature
icon: mdi:thermometer
name: Temperature
show_state: true
show_background: false
styles: >
.bubble-line {
background: white;
opacity: 1;
}
${card.querySelector('.bubble-name').innerText =
hass.formatEntityState(hass.states['weather.maison'])}
${icon.setAttribute("icon",
getWeatherIcon(hass.states['weather.maison'].state))}
```
Custom components conflicts
⚠️ For now there are some features that are not working with:
- Kiosk mode, but this is fixed in Kiosk mode v6.0.1
Help
Feel free to open an issue if something is not working as expected.
Got questions or thoughts about Bubble Card? Want to share your dashboards or discoveries? You can go on the Home Assistant forum, on the Bubble Card subreddit or on the GitHub Discussions section.
Donate
I dedicate most of my spare time to making this project the best it can be. So if you appreciate my work, any donation would be a great way to show your support 🍻
Thank you everyone for your support, you all are my greatest motivation!