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

Any Card-mod gurus able to help me on this? I’m trying to target this state-switch <div> to set overflow: visible so that the background colour/image can ‘escape’.

This is what it currently looks like:

This is the desired look:

This is the <div> I can target with overflow: visible to make it work under styles #root {}:

I’ve attempted to wrap the state-switch-card within a custom:mod-card but I’m not sure if this is the correct approach?

thanks!

YAML
      - type: custom:stack-in-card
        view_layout:
          grid-area: main1
          justify-self: middle
          show:
            mediaquery: '(min-width: 600px)'
        card_mod:
          style: |
            #root {
              overflow: visible !important;
            }
            :host {
              margin-top: -300px !important;
              padding-top: 300px !important;
              overflow: visible !important;
              margin-left: -4px !important;
              }
            ha-card {
              background-color: rgba(0,0,0,0) !important;
              backdrop-filter: blur(0px) !important;
              border-radius: 30px 30px 30px 30px !important;
              box-shadow: none !important;
              overflow: visible !important;
              }
        cards:
          - type: custom:mod-card
            card:
              type: custom:state-switch
              entity: hash
              transition: slide-left
              transition_time: 500
              view_layout:
                grid-area: main1
              states:
                kitchen:
                  type: custom:layout-card
                  layout_type: grid
                  view_layout:
                    grid-area: main1
                  layout:
                    grid-template-columns: auto 300px 300px auto
                    grid-template-rows: 1fr
                  cards:
                    - type: custom:mini-media-player

Is it possible to center all of these entities?

image

Im using multiple-entity-row

type: entities
entities:
  - entity: sensor.nordpool_kwh_se3_sek_3_095_0
    type: custom:multiple-entity-row
    icon: none
    name: false
    state_header: Spotpris
    entities:
      - entity: sensor.pool_heater_power
        format: precision0
        name: Förbr/nu
        unit: watt
      - entity: sensor.daily_energy_peak
        format: precision2
        name: Förbr/idag
      - entity: sensor.monthly_energy_peak
        format: precision2
        name: Förbr/mån

I just can’t cope with the scrollbar.
I try to remove it by making it wider. I change the width in the inspector and it works. But I can’t figure out where my mistake is.
Inspector path:

/html/body/home-assistant//home-assistant-main//app-drawer-layout/partial-panel-resolver/ha-panel-lovelace//hui-root//ha-app-layout/div/hui-view/hui-masonry-view//div/div[2]/hui-vertical-stack-card//div/hui-entities-card//ha-card/div/div[3]/hui-element//hui-horizontal-stack-card//div/mod-card[2]//ha-card/hui-entities-card//ha-card/div/div/hui-buttons-row//hui-buttons-base//div
Screenshot

My code:

YAML
                  - type: 'custom:hui-element'
                    card_type: horizontal-stack
                    cards:
                      - type: custom:mod-card
                        card:
                          type: entities
                          entities:
                            - entity: input_select.nachalo_stirki
                              card_mod:
                                style:
                                  hui-generic-entity-row $: |
                                    state-badge {
                                      display: none;
                                    }
                          card_mod:
                            style: |
                              ha-card {
                                box-shadow: none;
                              }
                      - type: custom:mod-card
                        card:
                          type: entities
                          entities:
                          - type: buttons
                            entities:
                              - entity: automation.wm_start_auto
                                state_color: true
                                icon: 'mdi:washing-machine-alert'
                                name: Запустить по расписанию
                                tap_action:
                                  action: call-service
                                  service: automation.toggle
                                  service_data:
                                    entity_id: automation.wm_start_auto
                                card_mod:
                                  style: 
                                    hui-buttons-row $ hui-buttons-base $: |
                                      .ha-scrollbar {
                                        width: 130% !important;
                                      }
                          card_mod:
                            style: |
                              ha-card {
                                box-shadow: none;
                              }

What is now:
image
What I want to get:
image
I would be grateful for any help and / or any recommendations for improving the code.
Perhaps it would be more correct to change the width of the column of a horizontal stack, for example, in a ratio of 40/60%?

Also I want to resize all the icon size separate, but I cant get it to work. Any tips how and where to put the card-mod is appreciated!

image

My code:

entity: sensor.nibe_bt50_room_temp_s1
icon: none
type: custom:multiple-entity-row
name: false
state_header: Inne
format: precision1
entities:
  - entity: alarm_control_panel.verisure_alarm
    style:
      hui-generic-entity-row:
        $: |
          state-badge {
            --mdc-icon-size: 50px;
          }
    format: precision1
    icon: true
    name: false
    state_color: true
  - entity: binary_sensor.all_doors
    name: false
    icon: true
    state_color: true
    hide_if: 'on'
  - entity: binary_sensor.garageport_status_door
    name: false
    icon: true
    state_color: true
    hide_if: 'on'
  - entity: sensor.nibe_bt1_outdoor_temperature
    format: precision1
    name: Ute

Create a small code snippet describing your case and post here.
Currently it is hard to understand the problem w/o seeing the code.

The first thought:

As I already told you:


Why using hui-element?
The only case is “use horizontal stack inside Entities card”.
But in this case the left card will be not aligned with respect to other entity rows:

type: entities
entities:
  - sun.sun
  - type: custom:hui-element
    card_type: horizontal-stack
    ...

изображение


Wrong style.
Styles for buttons described here.
Should be:

          - type: buttons
            entities:
              - entity: automation.test
                ...
            card_mod:
              style:
                hui-buttons-base $: |
                  .ha-scrollbar {
                    width: 130% !important;
                  }

And the total code is (assuming that the stack is placed inside Entities card):

type: entities
entities:
  - sun.sun
  - type: custom:hui-element
    card_type: horizontal-stack
    cards:
      - type: entities
        entities:
          - entity: input_select.test_value
            card_mod:
              style:
                hui-generic-entity-row $: |
                  state-badge {
                    display: none;
                  }
        card_mod:
          style: |
            ha-card {
              box-shadow: none;
            }
      - type: entities
        entities:
          - type: buttons
            entities:
              - entity: automation.test
                state_color: true
                icon: mdi:washing-machine-alert
                name: Запустить по расписанию
                tap_action:
                  action: call-service
                  service: automation.toggle
                  service_data:
                    entity_id: automation.test
            card_mod:
              style:
                hui-buttons-base $: |
                  .ha-scrollbar {
                    width: 130% !important;
                  }
        card_mod:
          style: |
            ha-card {
              box-shadow: none;
            }

изображение

This variant looks more aligned:

type: entities
entities:
  - sun.sun
  - type: custom:stack-in-card
    mode: horizontal
    card_mod:
      style:
        hui-horizontal-stack-card $: |
          div#root :first-child {
            width: 45%;
            flex: unset; 
          }
        .: |
          ha-card {
            box-shadow: none;
          }
    cards:
      - type: entities
        entities:
          - entity: input_select.test_value
            card_mod:
              style:
                hui-generic-entity-row $: |
                  state-badge {
                    display: none;
                  }
                .: |
                  ha-paper-dropdown-menu {
                    margin-left: 8px !important;
                  }
        card_mod:
          style: |
            .card-content {
              padding: 0px;
            }
      - type: entities
        entities:
          - type: buttons
            entities:
              - entity: automation.test
                state_color: true
                icon: mdi:washing-machine-alert
                name: Запустить по расписанию
                tap_action:
                  action: call-service
                  service: automation.toggle
                  service_data:
                    entity_id: automation.test
            card_mod:
              style:
                hui-buttons-base $: |
                  .ha-scrollbar {
                    justify-content: flex-end;
                    padding-right: 0px !important;
                  }
                  .ha-scrollbar ha-chip {
                    padding-right: 0px ;
                  }
        card_mod:
          style: |
            .card-content {
              padding: 0px;
              padding-top: 4px;
            }

изображение

@Pelican
Check this:

type: vertical-stack
cards:
  - type: entities
    entities:
      - entity: input_number.test_number
        name: height
  - type: picture-elements
    style: |
      ha-card {
        --image-height: {{states('input_number.test_number')|int}};
      }
    elements:
      - type: image
        image: /local/images/blue.jpg
        style:
          transform-origin: left bottom
          left: 110px
          top: 439px
          width: 82px
          height: 1px
          transform: translate(-50%,-50%) scale(1,var(--image-height))
    image: /local/images/tank.png

Untitled Projectdddd

BUT - I gonna disappoint you - the image elements do not keep the same position with respect to the main image because the main image is scaled automatically dependingly on the card size! That means that the water will be in the tank only if the card’s size is constant.
Here is a case when the card’s size is changed:
изображение
And specifying positions & sizes in “%” does not help.

1 Like

@Ildar_Gabdullin you are a genius! Thank you very much.

It works perfectly. The masks are made with the same width as the main image and I position them at full width, so they scale perfectly. My final solution ended up making the main image “full” and the masks look “empty”. I position the masks at some % from top of the main image and scale them down according to the depth sensor. It also works on my phone.

The sensor values have to be made to be a percentage either in the sensor integration (ESPHome in this case) or in the card.

I believe this is the best solution for showing tank levels and I can’t thank you enough for your help.

So to be complete, here is the yaml:

    - type: picture-elements
      image: /local/background_image.png
      card_mod:
        style: | 
          ha-card {
            --mask1-height: {{states('sensor.level1')|int}};
            --mask2-height: {{states('sensor.level2')|int}};
          }          
      elements:
        - type: image
          image: /local/mask1.png
          style:
            top: 0%
            width: 100%
            height: 1px
            transform: translate(0%,0%) scale(1,var(--mask1-height))
        - type: image
          image: /local/mask1.png
          style:
            top: 0%
            width: 100%
            height: 1px
            transform: translate(0%,0%) scale(1,var(--mask2-height))

But in your example the top = 0.
IMHO the most tricky part is to calculate top position of the image…
The images must keep relative positions after resizing of the window.

Hi @Ildar_Gabdullin

You are right. I am applying it in a few different scenarios and the top may not always be at 0. Here is what the first application looks like:


The aerator and (animated) bubbles are simple SVGs elements. Mask1 overlays the bubbles, so the bubble level is always right. I have some other applications where the top levels will not be the same.

You are 100% correct in that the top position is the hardest, but if all your masks have the same width it becomes a lot easier.

Do you specify “top” in px or % ?

I used % for the tops. Only px I used was for the mask height.

Please post a sample code for calculating “top”.

OK I made a new example. Remember the top does not change because the masks show “emptiness”. So the masks starts at the top of each tank (which stays the same) and stretch down. I made the tank background in such a way that the three mask tops start at 20%, 50% and 0%. In the 569px high main background graphic, that was around 119px (20%), 285px (50%) and of course, 0.

So let’s start with a sensor. I use ESPHome (or Tasmota) for PC boards I made for the ESP-07. The ultrasonic sensor for Tank 1 in ESPHome is defined like this:

sensor:
  - name: "tank1"
    id: ads1115_49_0
    ads1115_id: ads1115_49
    multiplexer: 'A0_GND'
    update_interval: 1s     
    gain: 2.048
    platform: ads1115
    unit_of_measurement: "m"
    icon: "mdi:gauge"
    accuracy_decimals: 0
    filters:
    - calibrate_linear:
          - 0.100 -> 0.0
          - 1.000 -> 270   
    - median:
        window_size: 10
        send_every: 1
        send_first_at: 1

This gives me a calibrated and filtered output of the distance between the sensor and the liquid. 10cm is full (0) and 1m is empty (270) for a range of 90cm.

The three values go into the card’s CSS variables.

    - type: picture-elements
      image: /local/graphics/test/tankbackground.png
      card_mod:
        style: | 
          ha-card {
            --mask1-height: {{states('sensor.tank1')|int}};
            --mask2-height: {{states('sensor.tank2')|int}};
            --mask3-height: {{states('sensor.tank3')|int}};
          }          
      elements:
        - type: image
          image: /local/graphics/test/mask1.png
          style:
            transform-origin: left top
            top: 20%
            width: 100%
            height: 1px
            transform: scale(1,var(--mask1-height))
        - type: image
          image: /local/graphics/test/mask2.png
          style:
            transform-origin: left top          
            top: 50%
            width: 100%
            height: 1px
            transform: scale(1,var(--mask2-height))
        - type: image
          image: /local/graphics/test/mask3.png
          style:
            transform-origin: left top          
            top: 0%
            width: 100%
            height: 1px
            transform: scale(1,var(--mask3-height))

The result looks like this for 75% full (25% empty):
image

Here is the background image (note it shows all tanks full):


Mask 1

Mask 2

Mask 3

I hope this helps someone else. [Update - the scaling breaks. Not sure where to look next]

because I had not seen it before, and I only just discovered it :wink:

Add a scrollbar to you markdown card:

card_mod:
  style: |
    ha-card.type-markdown {
      box-shadow: none;
      margin: 0px -16px -16px -16px;
      overflow-y: scroll;
      height: 300px;
    }

(the .type-markdown trick is to make sure this card_mod is only applied to the markdown card itself, and not to an enveloping entities card if you happen to embed the markdown card, like I do in my config. This can also be used for other cards ofc, and is useful when an embedded cards card_mod causes the whole (embedding) card to go beyond the regular Lovelace default card width)

Thanks a lot, will look at the code with attention.

OK the scaling sucks. It looks like the issue comes in with scaling being calculated using something other than the main image of the picture-elements card. If you put the card in a vertical-stack or something like that, then the levels fall apart. :sob:

Here is the original:
image

Two cards stacked horizontally. It looks like the scaling is based on the total width of the vertical-stack card containing the two picture-elements card:
image

It gets worse. Even using ordinary zooming in the browser breaks it:
image

It looks like the % styling in the elements themselves (ie width: 100%) scales correctly. It is therefore the scaling transform that breaks it. The only way seems to be to access the height % of the image elements. @thomasloven - can you please help? I really tried and @Ildar_Gabdullin has been amazing with his help (thank you again Ildar).

1 Like

That was exactly what I was talking about - scaling kills the picture.
I guess that this is a nature of picture elements card - scaling breaks a relative position of elements respectively to the main image.
Do not think that card-mod may resolve it.
Once I made a floorplan: main image + “dark room” images, and every scaling broke the plan - each “dark room” image was placed to different positions when the page was resized. Finally, I made all “dark room” transparent images of the same size as the main image. That means that for every small object like a hardware sensor, a lamp etc I also need to use a large transparent image. Also, I cannot place an icon or a static text - these elements will be misplaced after resize! (this do not allow to have the same card on PC, tablet & mobile phone - they may have different viewports).

Well, there is a workaround for different viewports:

  1. Create a decluttering card for a complex card like a floorplan; use variables for calibrating a relative position of elements.
  2. Select values for these calibration variables for each viewport.
  3. Call the decluttering card with a corresponding set of variables for each device (custom:state-switch may be used).

But this workaround anyway will not help in the “window is resized” case.

Btw, there is an issue for picture elements.

Assuming I can get the aspect_ratio to work (I am probably doing something wrong because I cant get it to work), is it possible to template aspect_ratio with card-mod? If it aspect_ratio scales correctly, it will solve the problem.

I have this conditional card:

              - type: conditional
                conditions:
                  - entity: media_player.cast_camera_letto
                    state: playing
                card:
                  type: entity
                  entity: media_player.cast_camera_letto
                  attribute: app_name
                  name: ' '
                  icon: ' '
                  style: |
                    ha-card {
                      height: 40px;
                      width: auto;
                      color: green;
                      font-family: 'Georgia';
                      font-weight: normal;
                      font-size: {{ '10px' if is_state_attr('media_player.cast_camera_letto', 'app_name', 'Netflix') else '12px' }};
                      }

and i would like to have the app_name attribute with a font size 10px, but i have the font family and the font weight as expected but not the font size.
Schermata 2022-01-14 alle 13.24.25

What is wrong in this?