🔹 Card-mod - Add css styles to any lovelace card

em vs px depends on your usecase.

Honestly most of the time for what we end up doing with card mod px is fine.

em is relative sized to the size of the font.
So 1.5em with a font size of 16px is 24px. Because 1.5em is just sayinf 150% of 16px.

Whilst px is static. We tend to want static with what we do in card mod.

But again, depends on the exact usecase.

Here’s my recent accomplishment with card_mod. It took me many hours of trying to re-learn the DOM navigation stuff but I persevered and succeeded. The battle was with icons and icon colors in the custom:multiple-entity-row element. The most time consuming for me was changing the icon_color in the secondary entity. The achievement was this layout which also utilizes the declutter-card and the card-mod card, both for my first time:

Lovelace raw config

** Edited to reflect recomended code by @Ildar_Gabdullin (post #5750)
** and use of |iif() by @Mariusthvdb (post #2671)

decluttering_templates:
  iblinds:
    card:
      type: vertical-stack
      cards:
        - type: custom:mushroom-title-card
          title: ''
          subtitle: '[[display_name]]'
          alignment: center
        - type: entities
          entities:
            - entity: cover.[[blind]]
              type: custom:multiple-entity-row
              name: ' '
              show_state: false
              card_mod:
                style:
                  hui-generic-entity-row:
                    $: |
                      state-badge {
                        --card-mod-icon: 
                          {% if is_state('cover.[[blind]]','open') %} phu:blind-tilt-open;
                          {% elif is_state('cover.[[blind]]','closed') %} phu:blind-tilt-closed;
                          {% else %} mdi:help-circle;
                          {% endif %}
                        color:
                          {% if is_state(config.entity,'open') %} green;
                          {% elif is_state(config.entity,'closed')%} beige;
                          {% else %} red;
                          {% endif %}
                      }
                    .: |
                      div.entity:nth-child(2) state-badge {
                        {% set percentage = states(config.entities[0].entity)|int(0) %}
                        {% set r, g, b = 0, 0, 0 %}
                        {% if (percentage <= 51) %}
                          {% set r = 255 %}
                          {% set g = (5.0 * percentage) | round | int %}
                        {% else %}
                          {% set g = 255 %}
                          {% set r = (505 - 4.89 * percentage) | round | int %}
                        {% endif %}
                        color: {{ "#%0x" | format( r * 0x10000 + g * 0x100 + b * 0x1 ) }};
                      }
              entities:
                - entity: sensor.[[blind]]_battery_level
                  name: Battery
                  unit: ' '
                - entity: sensor.[[blind]]_battery_level
                  name: false
                  icon: true
          show_header_toggle: false
          state_color: false
          card_mod:
            class: inline-card
        - type: custom:slider-button-card
          slider:
            direction: bottom-top
            background: gradient
            attribute: tilt
            use_state_color: true
            use_percentage_bg_opacity: true
            toggle_on_click: false
            show_track: true
            force_square: false
            invert: true
          action_button:
            mode: toggle
            show: false
          icon:
            icon: ''
            show: false
            use_state_color: false
          entity: cover.[[blind]]
          show_state: true
          compact: false
          name: Living Room
          show_name: false
        - type: custom:slider-button-card
          slider:
            direction: left-right
            background: gradient
            use_state_color: false
            use_percentage_bg_opacity: false
            toggle_on_click: false
            show_track: false
            force_square: false
            invert: false
          icon:
            show: false
          entity: input_number.[[blind]]
          show_state: true
          compact: true
          show_name: true
          name: 'Preset:'
          action_button:
            show: false
Card stack 1
type: vertical-stack
cards:
  - type: custom:mushroom-title-card
    title: ''
    subtitle: Kitchen
    alignment: center
  - type: horizontal-stack
    cards:
      - type: custom:decluttering-card
        template: iblinds
        variables:
          - blind: kitchen_blind_1
          - display_name: Blind 1
      - type: custom:decluttering-card
        template: iblinds
        variables:
          - blind: kitchen_blind_2
          - display_name: Blind 2
      - type: custom:decluttering-card
        template: iblinds
        variables:
          - blind: kitchen_blind_3
          - display_name: Blind 3
view_layout:
  column: 1
Card stack 2
type: custom:mod-card
card_mod:
  style:
    hui-horizontal-stack-card $: |
      div#root > :first-child {
        width: 66%;
        flex: auto; 
      }
      div#root > :last-child {
        width: 33%;
        flex: auto; 
      }
card:
  type: horizontal-stack
  cards:
    - type: vertical-stack
      cards:
        - type: vertical-stack
          cards:
            - type: custom:mushroom-title-card
              title: ''
              subtitle: Living Room
              alignment: center
            - type: horizontal-stack
              cards:
                - type: custom:decluttering-card
                  template: iblinds
                  variables:
                    - blind: living_room_blind
                    - display_name: Window
                - type: custom:decluttering-card
                  template: iblinds
                  variables:
                    - blind: patio_door_blind
                    - display_name: Patio Door
    - type: vertical-stack
      cards:
        - type: custom:mushroom-title-card
          title: ''
          subtitle: Master Bedroom
          alignment: center
        - type: horizontal-stack
          cards:
            - type: custom:decluttering-card
              template: iblinds
              variables:
                - blind: bedroom_blind
                - display_name: Window
view_layout:
  column: 1

I also make use of the script python_script.set_state HACS add-on to override the state of my iBlinds horizontal tilt blinds:

Automation
alias: iBlinds State Update
description: ""
trigger:
  - platform: state
    entity_id:
      - cover.kitchen_blind_1
      - cover.kitchen_blind_2
      - cover.kitchen_blind_3
    attribute: current_tilt_position
  - platform: state
    entity_id:
      - cover.kitchen_blind_1
      - cover.kitchen_blind_2
      - cover.kitchen_blind_3
    to: unknown
condition: []
action:
  - service: python_script.set_state
    data:
      entity_id: "{{ trigger.entity_id }}"
      state: >-
        {{ iif( 5 < state_attr(trigger.entity_id, 'current_tilt_position') <
        95,'open', 'closed') }}
  - service: saver.save_state
    data:
      entity_id: "{{ trigger.entity_id }}"
mode: parallel

and have similar code in my Home Assistant startup automation to override the state at startup.
Note: only three blinds are being overridden as the other three are older v2 blinds and I have those templated:

Blind templates
  - platform: template
    covers:
      living_room_blind:
        friendly_name: Living Room
        unique_id: living-room-blind-template
        value_template: '{{ iif (1 < state_attr("cover.living_room_blind_hidden","current_position")|int(0) < 99 , "open", "closed") }}'
        tilt_template: '{{100 - (state_attr("cover.living_room_blind_hidden","current_position")|int(default=0)) }}'
        set_cover_tilt_position:
          service: cover.set_cover_position
          data_template:
            entity_id: cover.living_room_blind_hidden
            position: '{{100 - tilt}}'
        open_cover:
          service: cover.set_cover_position
          data_template:
            entity_id: cover.living_room_blind_hidden
            position: '{{100.0 - states("input_number.living_room_blind")|float(0)}}'
        close_cover:
          service: cover.set_cover_position
          data_template:
            entity_id: cover.living_room_blind_hidden
            position: 100
        icon_template: >-
          {{ iif(this.state =='open','phu:blind-tilt-open','phu:blind-tilt-closed') }}
          
      patio_door_blind:
        friendly_name: Patio Door
        unique_id: patio-door-blind-template
        value_template: '{{ iif (1 < state_attr("cover.patio_door_blind_hidden","current_position")|int(0) < 99 , "open", "closed") }}'
        tilt_template: '{{100 - (state_attr("cover.patio_door_blind_hidden","current_position")|int(default=0)) }}'
        set_cover_tilt_position:
          service: cover.set_cover_position
          data_template:
            entity_id: cover.patio_door_blind_hidden
            position: '{{100 - tilt}}'
        open_cover:
          service: cover.set_cover_position
          data_template:
            entity_id: cover.patio_door_blind_hidden
            position: '{{100.0 - states("input_number.patio_door_blind")|float(0)}}'
        close_cover:
          service: cover.set_cover_position
          data_template:
            entity_id: cover.patio_door_blind_hidden
            position: 100
        icon_template: >-
          {{ iif(this.state =='open','phu:blind-tilt-open','phu:blind-tilt-closed') }}
            
      bedroom_blind:
        friendly_name: Bedroom
        unique_id: bedroom-blind-template
        value_template: '{{ iif (1 < state_attr("cover.bedroom_blind_hidden","current_position")|int(0) < 99 , "open", "closed") }}'
        tilt_template: '{{100 - (state_attr("cover.bedroom_blind_hidden","current_position")|int(default=0)) }}'
        set_cover_tilt_position:
          service: cover.set_cover_position
          data_template:
            entity_id: cover.bedroom_blind_hidden
            position: '{{100 - tilt}}'
        open_cover:
          service: cover.set_cover_position
          data_template:
            entity_id: cover.bedroom_blind_hidden
            position: '{{100.0 - states("input_number.bedroom_blind")|float(0)}}'
        close_cover:
          service: cover.set_cover_position
          data_template:
            entity_id: cover.bedroom_blind_hidden
            position: 100
        icon_template: >-
          {{ iif(this.state == 'open','phu:blind-tilt-open','phu:blind-tilt-closed') }}
1 Like

No need to use/define variables on such a deep level of DOM.
Besides, posting long code distracts users from a solution itself.
But I myself really appreciate an intention to share a successful result with people.

1 Like

I will give your comment a like!
Myself, I hate the lack of detail often prevalent when perusing threads.
As for the deep level of DOM I arrived at, it was after many hours and the turning point was discovering the online card-mod-helper tool plus the need to remove spaces within the selector. I haven’t discovered (yet) how to shorten it… As for the use of variables, my bad! Will attempt to correct…

1 Like

Hey,
it is posoble to reduce the gabs in a mini_graph_card?
416037685_7310432232334376_8394963742747464180_n
Card Mod is installed, but i have no idear.

big Thanks Andi

Daniel, the solution you posted is rather not optimal.
Check 1st post → link at the bottom → styles for m-e-r

type: entities
entities:
  - type: custom:multiple-entity-row
    entity: sun.sun
    card_mod:
      style:
        hui-generic-entity-row $: |
          state-badge {
            color: orange;
          }
        .: |
          div.entity:nth-child(1) state-badge {
            color: cyan;
          }
          div.entity:nth-child(2) state-badge {
            color: red;
          }
    entities:
      - entity: sun.sun
        name: false
        icon: mdi:car
      - icon: mdi:link
    icon: mdi:account

image

Ofc, colors of “secondary” icons may be done directly by using a native “styles” option; with card-mod you may make colors templated by jinja.
Also, icon’s color (for the main entity & “secondary” entities) may be also controlled automatically w/o card-mod by theme variables in some cases.

1 Like

I know grid is less common here and I did not find any fitting examples, so maybe it is not a grid problem.
But I am creating a card with vertical-stack, entities, custom:button-card and markdown.

Card hierarchy is

  • Vertical-stack
    ** Custom:Layout-card (type grid)
    *** Two custom:button-card in the first grid (i.e. first row of vertical-stack)
    *** 5 Entities and 2x5 markdown cards (with custom:config-templater) in the second grid (i.e. second row of vertical-stack)

Unfortunately, there is a gap between the first and second row (two custom:layout-card grids).
In addition, the content of all my markdown cards (populated with custom:config-templater) is aligned top/start instead of center.

Does anybody know where I need to apply my styling to fix these two issues?

Almost. An em is specifically the width of the letter M of the current font at its current size. Similar is ex, which is the height of the letter x. This matters, because a font of size 24pt isn’t just a 2x scaled up version of the 12pt font. In some cases it is, but for well-designed fonts this isn’t the case. So, if you have a UI where different font sizes are used at different screen sizes, using these relative measures scale things in a special non-linear proportion. Otherwise, we could just have stuck to a percentage, but that won’t always look right. Anyway, I thought it would be interesting to know. There was a time I took a lot of interest in typography.

6 Likes

Thanks for the slight correction. Was not aware of the use of em vs ex and why they are named that - every day is a school day! :slight_smile:

1 Like

How to combine different mods in same card?

I want to change the icon size and secondary text in a tile card, but I cannot seem to do both. When I just do one or the other, it works.

One card mod changes the tile icon size:

card_mod:
  style: |
    ha-tile-icon {
      --mdc-icon-size: 12px;
    }

The other changes the secondary info in the tile card:

card_mod:
  style:
    ha-tile-info$: |
      .secondary {
        color: grey !important;
        font-weight: bold !important;
        visibility: hidden;
      }
      .secondary:before {
        visibility: visible;
        content: {% if is_state('media_player.samsung_ue75ju7000', 'on') %}
         'TV is on'
        {% else %}
         '{{state_attr('climate.floorC82B96A543E8_4_climate', 'current_temperature')}} °C'
        {% endif %}
      }

Simply putting the mods into the same does not work (in this case only the icon size changes):

card_mod:
  style: |
    ha-tile-icon {
      --mdc-icon-size: 12px;
    }
    ha-tile-info$: |
      .secondary {
        color: grey !important;
        font-weight: bold !important;
        visibility: hidden;
      }
      .secondary:before {
        visibility: visible;
        content: {% if is_state('media_player.samsung_ue75ju7000', 'on') %}
         'TV is on'
        {% else %}
         '{{state_attr('climate.floorC82B96A543E8_4_climate', 'current_temperature')}} °C'
        {% endif %}
      }

Probably a CSS formatting or syntax issue, right? Have tried seeking help in the CSS documentation, CSS validators and asked ChatGBT, but so far no success? What am I doing wrong?

1st post → link at the bottom → other → combining

Apologies. Not sure what you are referring to. Tried looking at the bottom of the first post for a link called other or combining, but didn’t see one?

There is only 1 link in the end of the 1st post

sorry, found this, which I believe you are ferring to: :small_blue_diamond: Card-mod - Add css styles to any lovelace card - #3907 by Ildar_Gabdullin

But not sure how to apply this? What is wrong in my example?

No, not the link you posted.
Follow that one about “combining”

I started with this one (🔹 Card-mod - Add css styles to any lovelace card - #3905 by Ildar_Gabdullin) but it seemed the other one was the explanation. Tried adding .: | but it seemed to make no difference.

(This also does not work):

card_mod:
  style:
    ha-tile-info$: |
      .secondary {
        color: grey !important;
        font-weight: bold !important;
        visibility: hidden;
      }
      .secondary:before {
        visibility: visible;
        content: {% if is_state('media_player.samsung_ue75ju7000', 'on') %}
         'TV is on'
        {% else %}
         '{{state_attr('climate.floorC82B96A543E8_4_climate', 'current_temperature')}} °C'
        {% endif %}
      }
      .: |
      ha-tile-icon {
      --mdc-icon-size: 12px;
      }

I would suggest to try on simpler examples w/o templates, pseudoclasses etc.

Thanks! This helped me see the indentation error. This works!:

card_mod:
  style:
    ha-tile-info$: |
      .secondary {
        color: grey !important;
        font-weight: bold !important;
        visibility: hidden;
      }
      .secondary:before {
        visibility: visible;
        content: {% if is_state('media_player.samsung_ue75ju7000', 'on') %}
         'TV is on'
        {% else %}
         '{{state_attr('climate.floorC82B96A543E8_4_climate', 'current_temperature')}} °C'
        {% endif %}
      }
    .: |
      ha-tile-icon {
      --mdc-icon-size: 20px;
      }

Thank you so much for your time,

I’m still not sure exactly what you meant by this…

Assume we have this multi-level structure:
element A → element B → element C → element D
For simplicity - assume that on each level an element has only one child.
Assume we need to apply some property like “color: red”.
We need to go down only to the level (not deeper) where this property is really meaningful (even may be not used yet - but the child element may inherit this property; this is a trick which MAY be useful if the child element is changed in some version of HA).
Means - no need to set the property to the element D if it is sufficient on a level C.

Next, assume this feature (color) may be set by some variable.
I.e. on this level C the color is by default defined as “var(–ha-super-color, #ff00ff)”.
Means - you may set this “–ha-super-color” on the level A - and this will work.

But if there is only ONE level - check a simple example based on your+mine codes:

        hui-generic-entity-row $: |
          state-badge {
            --card-mod-icon-color: orange;
          }
        .: |
          div.entity:nth-child(1) state-badge {
            --card-mod-icon-color: cyan;
          }
          div.entity:nth-child(2) state-badge {
           --card-mod-icon-color: red;
          }

No need to use vars here. On this level a property may be used.

1 Like