Skip to content
dcapslock edited this page Oct 31, 2025 · 12 revisions

The Theme support is a powerful feature of card-mod.

Not only does it allow you to mod cards, badges, glance buttons and rows *globally without having to apply the styles manually to every item, but it also allows you to apply styles to many more elements of the interface - even outside of lovelace.

How to add card-mod to a theme

If you already have some themes set up, here's a quick summary for how to merge a theme:

Original:

Google Light Theme:
  # Header:
  app-header-background-color: "#F8F8F8"
  app-header-text-color: "#424242"
  # Main Interface Colors
  primary-color: "#5F9BEA"
  light-primary-color: var(--primary-color)
  primary-background-color: "#F8F8F8"
  secondary-background-color: var(--primary-background-color)
  divider-color: var(--primary-background-color)
  # More stuff here that I cut out

Card-mod theme:

compact-header:
  card-mod-theme: compact-header
  # Header
  card-mod-root-yaml: |
    paper-tabs$: |
      .not-visible {
        display: none;
      }
      /*Uncomment this if you want the header on the bottom
      #selectionBar {
        bottom: unset !important;
      }
      */
      /*More stuff I cut out*/

New theme:

Google Light Theme:
  # Header:
  app-header-background-color: "#F8F8F8"
  app-header-text-color: "#424242"
  # Main Interface Colors
  primary-color: "#5F9BEA"
  light-primary-color: var(--primary-color)
  primary-background-color: "#F8F8F8"
  secondary-background-color: var(--primary-background-color)
  divider-color: var(--primary-background-color)
  # More stuff here that I cut out
  card-mod-theme: "Google Light Theme"
  # Header
  card-mod-root-yaml: |
    paper-tabs$: |
      .not-visible {
        display: none;
      }
      /*Uncomment this if you want the header on the bottom
      #selectionBar {
        bottom: unset !important;
      }
      */
      /*More stuff I cut out*/

Getting started

To get started, you need themes enabled in Home Assistant.

The best way to do this is to create a new /config/themes/ directory, and then add the following to your configuration.yaml

frontend:
  themes: !include_dir_merge_named themes/

After restarting Home Assistant, you can place theme files in that directory, load them with the frontend.reload_themes service:

image

and then select the theme you want in your profile settings:

image

Theme files are normally yaml documents, which contain settings for the many themeable variables available in Home Assistant, Eg:

/config/themes/red.yaml

red-theme:
  primary-color: red
  primary-text-color: white
  ha-card-border-radius: 20

image

Note that the theme name must be on the first row, and the rest should be indented one level.

Basic card-mod theme

To make a card-mod theme, the most important thing is this:

The theme must have a card-mod-theme variable set to the name of the theme.

/config/themes/red.yaml

red-theme:
  card-mod-theme: red-theme
  primary-color: red
  primary-text-color: white
  ha-card-border-radius: 20

Once card-mod-theme is set, we're ready to do some really powerful things.

To apply the basic functionality of card-mod globally, you can use the card-mod-<thing> variables, where <thing> is card, row, glance or badge.

For example, say you want a border around every row in an entities card, you may do something like this:

type: entities
entities:
  - entity: light.bed_light
    style: |
      :host {
        display: block;
        border: 1px solid black;
      }
  - entity: light.ceiling_lights
    style: |
      :host {
        display: block;
        border: 1px solid black;
      }
  - entity: light.kitchen_lights
    style: |
      :host {
        display: block;
        border: 1px solid black;
      }

This can now be added to our theme instead:

red-theme:
  card-mod-theme: red-theme
  ...
  card-mod-row: |
    :host {
      display: block;
      border: 1px solid black;
    }

And now every row in every entities or glance card has a nice black border: image

Note that the card-mod-<thing> variables contain strings containing CSS code, and must start with | or > and be indented at least one step.

Just like normal, you can use Jinja2 templating to process the styles:

red-theme:
  card-mod-theme: red-theme
  ...
  card-mod-row: |
      :host {
          display: block;
          border: 1px solid {% if is_state(config.entity, 'on') %} red {% else %} black {% endif %};
      }

image

Classes

Since version 2.0.2 Card-mod lets you set a CSS class to cards, rows, badges and glance buttons. You can then use this in your theme:

red-theme:
  card-mod-theme: red-theme
  ...
  card-mod-row: |
      ...
      :host(.teal) {
        background: teal;
      }
      :host(.purple) {
        background: purple;
      }
type: entities
entities:
  - entity: light.bed_light
  - entity: light.ceiling_lights
    card_mod:
      class: teal
  - entity: light.kitchen_lights
    card_mod:
      class: purple

image

Navigating the ShadowDOM

Just like with card-mod styles applied to a card, you can traverse the ShadowDOM structure of the thing you want to style.

To do this, you need to specify the variable card-mod-<thing>-yaml, and then the syntax is exactly the same, e.g:

red-theme:
  card-mod-theme: red-theme
  ...
  card-mod-row-yaml: |
    "*:first-child$": |
      @keyframes spin {
        0% {
          transform: rotate(0deg);
        }
        100% {
          transform: rotate(359deg);
        }
      }
      state-badge {
        {% if config.entity.startswith('fan.') and is_state(config.entity, 'on') %}
        animation: spin 5s infinite linear;
        {% endif %}
      }

Note that while the value of the card-mod-<thing>-yaml variable is actually yaml, as far as the theme is concerned it MUST be a string, which in turn contains more strings.

Special theme variables

Card-mod themes gives you access to more things to style via card-mod-<thing> and card-mod-<thing>-yaml.

Those are:

  • view
  • root
  • more-info
  • sidebar
  • dialog (since v4.0.0)
  • config (since v4.0.0)
  • developer-tools (since v4.0.0)
  • panel-custom (since v4.0.0) iFrame custom panels not supported
  • top-app-bar-fixed (since v4.0.0) Useful if theming config as top-app-bar-fixed is its own thing

NOTE: dialog does not include more-info which is its own thing.

view applies styles rooted in the hui-view element which contains the lovelace cards and badges: image This can be used to e.g. change the spacing between cards, or move the badges to a column at the left of the screen.

root applies styles rooted in the shadowRoot of the hui-root element which contains the header bar: image This can be used to style or remove the header bar.

more-info applies styles rooted in the ha-dialog element of more-info dialogs: image This can be used to style elements in the more-info dialog or its backdrop.

dialog applies to styles rooted in the dialog element of dialogs which may be ha-dialog, ha-md-dialog, ha-wa-dialog or drawer (notification uses dialog with element thing drawer). Dialogs will also have their class set to type-<dialog-type> where <dialog-type will be the dialog element name with any ha- prefix stripped. e.g. Card-mod will append add type-dialog-box to dialog boxes as used by alerts and other dialogs boxes. The Home Assistant dialog manager places dialogs in the shadowRoot of the top <home-assistant> element. The active dialog will be the last child of the shadowRoot. To view what dialog you wish to target, review the last child of this shadowRoot node. See Alert Dialogs in the Theme Cookbook for some theme styling examples for dialogs.

Clone this wiki locally