šŸ”¹ Card-mod - Add css styles to any lovelace card

Hey Ildar, getting back to this. It was one of the last cards I had still to perfectionizeā€¦

even with your exact config, the text of my template would still run through the images, because it crosses the half of the card, as you can see below.
Even after having cut the word Media in each attribute. (see the template in the config)

So I decided to give it a try an have them vertically stacked, first the markdown, below the image, and found only 2 ways to do so really.

1- a core entities card and set a background on that (and an empty entities list). We need to set the height of the background manually, and that is a bit of a trial and error, but, the end result is really nice

2- a custom:button-card, set to 1/1, no action (can change of course) and nothing fancy

for both cards I needed to find a way to fill the full width. 16px allround. this is what I did:

1- entities card

type: vertical-stack
cards:
  - type: custom:auto-entities
    show_empty: false
    card:
      type: entities
      title: Plex Playing
      card_mod:
        style: |
          .card-header {
            background-color: var(--background-color-off);
            color: var(--text-color-off);
            padding-top: 0px;
            padding-bottom: 0px;
            margin: 0px 0px 16px 0px;
          }
    filter:
      include:
        - entity_id: 'media_player.plex*'
          state: /playing|paused|'on'/
          options:
            type: custom:hui-element
            card_type: markdown
            card_mod:
              style: |
                ha-card.type-markdown {
                  box-shadow: none;
                  margin: -8px -16px;
                }
            content: >
              {% set player = config.entity %}
              {% if states(player) not in ['unknown','unavailable'] %}
              {%- for attr in states[player].attributes %}
                {%- if not attr in ['media_content_id','icon','entity_picture', 'hide_attributes',
                                    'media_position_updated_at', 'media_duration','media_position',
                                    'player_source', 'media_content_rating',
                                    'is_volume_muted','username','friendly_name', 'volume_level',
                                    'supported_features'] %}
                {{attr.split('media_')[1]|replace('_',' ')|title}}: {{states[player].attributes[attr]|title}} {%- endif %}
              {% endfor %} User: {{state_attr(player,'username')}}
              {% else %} Nothing playing
              {% endif %}

          sort:
            method: name

  - type: custom:auto-entities
    show_empty: false
    card:
      type: entities
      card_mod:
        style: |
          ha-card {
            margin: -8px 0px 0px 0px;
            box-shadow: none;
          }
    filter:
      include:
        - entity_id: 'media_player.plex*'
          state: /playing|paused|'on'/
          options:
            type: custom:hui-element
            card_type: entities
            card_mod:
              style: |
                ha-card {
                  background: url({{state_attr(config.entity,'entity_picture')}});
                  box-shadow: none;
                  background-size: cover;
                  margin: -16px;
                  height: 500px;
                }
            entities: []

and the button-card:

replace with

  - type: custom:auto-entities
    show_empty: false
    card:
      type: entities
      card_mod:
        style: |
          ha-card {
            margin: -8px 0px 0px 0px;
            box-shadow: none; /* not really necessary because of button card mode below */
          }
          .card-content {
            margin: -16px;
          }
    filter:
      include:
        - entity_id: 'media_player.plex*'
          state: /playing|paused|'on'/
          options:
            type: custom:button-card
            aspect_ratio: 1/1
            show_name: false
            show_icon: false
            tap_action: none
            card_mod:
              style: |
                ha-card {
                  background: url({{state_attr(config.entity,'entity_picture')}});
                  box-shadow: none;
                  background-size: cover;
                }

result:

note the button really is square, the entities card seems a longer image.
On the iPhone this fits the full screen perfectly.

I also tried it with core picture card, but ofc it complains it needs an imageā€¦ didnt really try hard yet, and maybe I can overcome that with config-template-card. That would require yet another custom-card, and Iā€™d like to keep it as simple as can be.
didnt test a stack-in-cardā€¦
but for you I just did, and it works the same, can simply replace vertical-stack with custom:stack-in-card, and still need several of the mods, so no real advantage I guess

I think this construction is ā€œmore traditionalā€, more clear.
The ā€œ.:ā€ means ā€œselect the current elementā€ - but what is a meaning of using this for the 1st selector?
Ok, it is not a mistake to use the ā€œ.:ā€ first - but it is less clear.

O.k. Thanks. Thought there is more in regard to performance or something else. Compare to my questions somewhere above in the thread.

Read this, I find it very useful.

Note that 99.99 % of my examples are WITHOUT optimization but could be a bit MORE CLEAR for new people since they show DOM navigation:
without optimization:

element:
  $:
    element:
      $: |
        element {
          ...
        }

with optimization:

element $ element $: |
  element {
    ..
  }

Yes. It is. Funny that this was one day before my question above. Didnā€™t see this before and we had the same questions more or less in parallel.

Only donā€™t get the leading $ till now

element-a:
  $ element-b $:

But most probably have to read and re-think the post several times again.

He explains:

will create one card-mod element in each element-a , and one in the shadowRoot of the first element-b in the each element-a .

But refering to this

E.g. the following will apply styles to the #shadow-root of the first action button in an alarm-panel card:

"#armActions mwc-button$": |

This already takes only the first. Or is there something missing in the explanation around ā€œin the eachā€, e.g. ā€œ[only] in the [first shadow root of] each element-aā€?

had another go at the Plex card:

type: vertical-stack
cards:
  - type: custom:auto-entities
    show_empty: false
    card:
      type: entities
      title: Plex Playing
      card_mod:
        style: |
          .card-header {
            background-color: black;
            color: orange;
            padding-top: 0px;
            padding-bottom: 0px;
          }
    filter:
      include:
        - entity_id: 'media_player.plex*'
          state: /playing|paused|'on'/
          options:
            type: custom:hui-element
            card_type: markdown
            theme: plex # <-- set background for the markdown and still use a background-image
            card_mod:
              style: |
                ha-card.type-markdown {
                  background-image: url('/local/various/plex.png');
                  background-position: right;
                  background-size: contain;
                  background-repeat: no-repeat;
                  box-shadow: none;
                  color: silver;
                  margin: 8px -16px -16px -16px;
                }
            content: >
              {% set player = config.entity %}
              {% if states(player) not in ['unknown','unavailable'] %}
              <font color='orange'>**User:**</font> {{state_attr(player,'username')}}
              {% for attr in states[player].attributes %}
                {%- if not attr in ['media_content_id','icon','entity_picture','hide_attributes',
                                    'media_position_updated_at','media_duration','media_position',
                                    'player_source','media_content_rating',
                                    'is_volume_muted','username','friendly_name','volume_level',
                                    'supported_features'] %}
               <font color=orange> **- {{attr.split('media_')[1]|replace('_',' ')|title}}:**</font> {{states[player].attributes[attr]|title}} {% endif %}
              {%- endfor %}
              {% else %} Nothing playing
              {% endif %}
          sort:
            method: name

note:
I wanted to see if I could use the Plex icon as background-image, and that worked well, but, ofc, that removes the option for the background: black which I had set, as background for the Plex colors: orange for bold, silver for regular text.

I almost conceded, but then I suddenly remembered we can set a theme on Markdown cardsā€¦

created this huge theme:

plex:
  card-background-color: black

and set it in the markdown config. So now I can benefit from a background image And a background color!

One more improvement would be to use the User in the card title, must have a look how to do that most efficiently

this helps:

  - type: custom:auto-entities
    show_empty: false
    card:
      type: entities
      card_mod:
        style: |
          .card-content {
            margin: -16px;
          }
    filter:
      include:
        - entity_id: 'media_player.plex*'
          state: /playing|paused|'on'/
          options:
            type: custom:button-card
            template: button_default_title
            name: >
              [[[ return 'Plex playing: ' + states['this.entity_id'].attributes.username; ]]]
            show_icon: false
            styles:
              card:
                - color: orange
                - background-color: black

but now I have 3 times the same auto-entities filterā€¦huh? it does work but seems awfully inefficient,

or, for the fun of it, mimicking the iPhone frontscreen:

            name: >
              [[[ var caption = 'Plex playing:&nbsp';
                  var title = states['this.entity_id'].attributes.media_title;
                  var artist = states['this.entity_id'].attributes.media_artist;
                  var album  = states['this.entity_id'].attributes.media_album_name;
                  return `<div style='display: flex; padding: 0px 16px 0px 0px;'>
                      <div>${caption}</div>
                      <marquee>
                      <span style='color:silver;align-items:center;'>${artist} - ${album} - ${title}</span>
                      </marquee>`;]]]

Feb-02-2022 15-57-33

could be smoother, but hey, whoā€™s complaining

2 Likes

Hello Guys,

I have recently start using Dwainā€™s Dashboard. It look pretty awesome but I am struggling a bit with some CSS changes.

I have this CCS:

I want to apply extra width to the hui-vertical-stack-card , but I have tried serveral things. Nothing seems to work.

    - type: vertical-stack
      style:
         hui-vertical-stack-card:
           $: |
             .item {
               width: 850px;
             }

Can someone please assist me on this?

You need to wrap your vertical-stack inside a mod-card. Check for it on the card-mod docs.

Thx you for your answer.

I have already managed to fix it with te following


    - type: vertical-stack
      cards:
        - type: entities
          style: |
            ha-card {
              width: 950px !important;
              max-width: max-content;
            }
            :host {
              width: 950px;
            }

well, I do believe I am lost for options. I did test all (I think) of the examples in this post to style (color) to simple icons:

      - type: conditional
        conditions:
          - entity: binary_sensor.selected_hue_group_active_scene
            state: 'off'
        row:
          entity: script.activate_hue_dynamic_scene
          icon: mdi:play
          action_name: play
          card_mod:
            style:
              hui-generic-entity-row:
                $:
                  state-badge:
                    $: |
                      ha-state-icon {
                        color: green;
                      }
      - type: conditional
        conditions:
          - entity: binary_sensor.selected_hue_group_active_scene
            state: 'on'
        row:
          entity: script.deactivate_hue_dynamic_scene
          icon: mdi:stop
          action_name: stop
          card_mod:
            style:
              hui-generic-entity-row:
                $: |
                  state-badge {
                    color: red;
                  }

and have no succes at all. Neither of my scripts get a colored icon, do I need a step extra in the path maybe?
hui-conditional-row > hui-script-entity-row").shadowRoot.querySelector("hui-generic-entity-row").shadowRoot.querySelector("state-badge").shadowRoot.querySelector("ha-state-icon").shadowRoot.querySelector("ha-icon").shadowRoot.querySelector("ha-svg-icon")

grrr.
back to custom-uiā€¦

  customize:

    script.deactivate_hue_dynamic_scene:
      icon_color: red

    script.activate_hue_dynamic_scene:
      icon_color: green

Was described here.

      - type: conditional
        conditions:
          - entity: input_boolean.test_boolean
            state: 'off'
        row:
          entity: script.test_script
          icon: mdi:play
          action_name: play
        card_mod:
          style:
            hui-script-entity-row $ hui-generic-entity-row $: |
                state-badge {
                  color: magenta;
                }

ŠøŠ·Š¾Š±Ń€Š°Š¶ŠµŠ½ŠøŠµ

I am having a problem changing colour based on state for my alarm system.
I would like sensors to be green if not activated and red if activated.
I am using the following code, but I am still getting yellow if activated and blue if not activated.
Could anyone please offer advice.
Thank you.

type: entities
entities:
  - entity: binary_sensor.downstairs_back
    icon: mdi:window-closed-variant
  - entity: binary_sensor.kitchen_pir
  - entity: binary_sensor.downstairs_front
    icon: mdi:window-open-variant
  - entity: binary_sensor.font_room_pir
  - entity: binary_sensor.kitchen_pir
  - entity: binary_sensor.pir_util_landing
    card_mod:
      style: |
        ha-card .header .icon {
        {% if is_state(config.entity,'on') %}
          color: green;
          % else %}  
          color: red;
        {% endif %}  
        }
  - entity: binary_sensor.front_door
    icon: mdi:door-closed
  - entity: binary_sensor.tv_room_pir
  - entity: binary_sensor.upstairs_back
    icon: mdi:window-closed-variant
  - entity: binary_sensor.upstairs_front
    icon: mdi:window-closed-variant
  - entity: binary_sensor.utility_room
    icon: mdi:door-closed
  - entity: binary_sensor.garage_sensor
  - entity: binary_sensor.pir_front_hall
    icon: mdi:motion-sensor-off
state_color: true

using a plain fold:

  - type: custom:fold-entity-row
    head:
      type: section
      label: Alerts settings/selectors
      card_mod: &label
        style: |
          .label {
            margin-left: 0px;
          }
    padding: 0
    no_animation: true
    entities:
      - type: custom:slider-entity-row
        entity: input_number.quakes_near
      - input_select.quakes_near

thereā€™s a cutoff of the balloon on the number slider:

Schermafbeelding 2022-02-05 om 10.51.54

would there be a preferred way of presenting that? Setting a margin on the #items maybe, or on the input_number itself?

btw, if I exchange the top 2 entities you can see the balloon CAN overflow the entity above:

    entities:
      - input_select.quakes_near
      - type: custom:slider-entity-row
        entity: input_number.quakes_near

might be the best solution, though Id still love to understand whatā€™s happening. Is it the fold preventing the balloon showing, or is it something in the core slider.

1st post ā†’ link at the bottom ā†’ post with many links ā†’ post for Entities card

Strange, I do not see a cutoff:
ŠøŠ·Š¾Š±Ń€Š°Š¶ŠµŠ½ŠøŠµ
Check your card-mod theme or disable it.

Thank you.
I have followed the link, but I cannot find how to change the colors based of state of entity unfortunately.

Then write & post a code for applying a STATIC style to the element you need, afterwards people will tell you how to change the style dynamically (if it is possible).

Done. Thanks!

             - type: weblink
                name: Gehe zu Config-Dashboard
                url: /config/dashboard
                icon: mdi:arrow-right
                card_mod:
                  style: |
                    a {
                      padding-left: 45px;
                    }

1 Like

Probably I am not getting your question.
The ā€œ[first shadow root of] each element-aā€ is meaningless since each element has only ONE shadowRoot.
I do not see how that ā€œ"#armActions mwc-button$": |ā€ case may be contradictory to the ā€œwill create one card-mod element in each element-a , and one in the shadowRoot of the first element-b in the each element-a .ā€.
If you have any doubts please share them. I think this is an interesting topicā€¦

Perhaps ignore my interpretations and/or try to understand and explain the leading $ in your words. I donā€™t give up trying to undertand. :wink:

element-a:
  $ element-b $:

Currently I neither understand nor see happening, what Thomas explained.