Styling elements in Picture elements card: a small tutorial

any option to color a state label:

  - type: state-label
    entity: sensor.netto_stroom_kosten_vandaag
    title: Netto stroom kosten
    style:
      color: black # need {{'green' if entity.state > 0 else 'crimson'}}
      font-weight: bold
      font-size: 25px
      top: 88%
      left: 48%

I did manage to use the global card_mod:

card_mod:
  style: |
      ha-card {
        {%- if states('sensor.grid_energy_total')|float(0) < 0 -%}
        --energy-color: green;
        {%- else -%}
        --energy-color: crimson;
        {%- endif -%}
      }

and on the element

  - type: state-label
    entity: sensor.netto_stroom_kosten_vandaag
    title: Netto stroom kosten
    style:
      color: var(--energy-color)

I fear having to change some other variables too, way too complex…

Summary

This text will be hidden

THANK YOU, THANK YOU, THANK YOU SO MUCH

1 Like

Anybody know if its possible to change the icon: based on some sensors status?

  1. For template sensors you may define icon dynamically.
  2. For some domains & device_classes icon is set dynamically dependingly on a state.
  3. card-mod may be used in SOME cases to replace an icon (goto card-mod repo for details).
1 Like

Which program you used for making floor plan?

I used adobe illustrator (helps that I’m a graphic designer).
I think some people use online floorplan tools like smartdraw: https://cloud.smartdraw.com/

1 Like

How did you make glow effects for lights? Where did you get furniture elements? Can you share configuration for ground floor on this link?

I’m a graphic designer. I drew the furniture elements myself using adobe illustrator (with separate versions with the lights on and off) and used picture elements code to determine which versions are displayed.

Answering an question “How to adapt PE card for different viewports”

May be I have not tried enough - but so far I chose a way “different backgrounds with different aspect-ratio”.
Assume we are talking about a floorplan.
Assume the image itself is rectangular 2:1 (wide).
Create a PNG file: an image in the center, transparent left & right margins, and select dimensions dependingly of your screen (let it be a desktop).
Assume you now have 3.5:1 image with transparent margins - and this image perfectly fits your desktop.

Then check same on your another screen (let it be a tablet).
Then create another PNG for this screen.

Now you have two PNG images, for both of them you will probably have to re-define positions & scales of elements.
So you have 2 sets for 2 clients (i.e. two different cards):

  • PNG file
  • positions & scales.

Now you need to display card_1 on a client_1, card_2 on a client_2.
Possible ways:

  1. Place both cards into state-switch card a required card will be disaplyed dependingly on a viewport (go to a corr. thread for details, not using this card).
  2. Create a different user for client_2, place both cards on different views, hide these views for a corresponding user (i.e. user_1 will see view_1 with card_1, user_2 will see view_2 with card_2).
1 Like

I’ve managed to achieve a fairly good approach with the grid layout_card.
I use a grid of 3 columns, of which the center column is relative to the viewport height.

grid-template-columns: 1fr calc(79vh) 1fr
grid-template-rows: auto
place-content: center center
grid-template-areas: |
  "left main right"

For me, a width of 79% relative to the height of the viewport resulted in the picture-elements card being scaled to the right size.
The card itself is sent to the ‘main’ or center column:

view_layout:
  grid-area: main

Now I have a flexible layout for all portrait screen orientations.
When using the CSS mediaquery the same can be done for landscape screen orientations.

I’m having difficulties applying the lessons in this tutorial to a custom:canvas-gauge-card. It seems that it’s height can only be given in pixels and this is fixed: it doesn’t scale with the dashboard. I’ve produced a much simplified version of my tide gauge to demonstrate the problem. On the PC it looks like this:


but on my Android phone like this:

I’ve experimented with the picture elements layout rules given earlier (changing the aspect ratio of the grid I’m using to demonstrate the issues) and it makes no difference the the gauge. I then went on to attempt to use mediaquery to set the vertical scale according to the screen height, but I must be getting the usage wrong because nothing I’ve tried makes any difference. Can anyone offer any suggestions on how to make the gauge fit the card independent of screen size?
The test code is:

type: custom:card-templater
layout_type: custom:masonry-layout
card:
  type: picture-elements
  image: /local/images/grid1280x1000.jpg
  title: tide
  elements:
    - type: custom:canvas-gauge-card
      entity: sensor.tide_high
      style:
        left: 10%
        bottom: 0%
        transform: none
      gauge:
        type: linear-gauge
        width: 150
        height: 600
        majorTicks: none
        strokeTicks: false
        animate: false
        barStrokeWidth: 0
        barBeginCircle: false
        valueBox: false

The background image is


and a version of the finished tide gauge card looks like this:

Your post is fantastic.

2 questions:

  • i’ve a 3d map of my house in hass. I wanna add to this frame like background of value of my sensor:
    image

    • type: state-label
      entity: device_tracker.2107113sg
      style:
      border-radius: 0%
      color: ‘#fff
      font-size: 6px
      font-weight: bold
      left: 23px
      top: 25%
    • type: state-label
      entity: sensor.cph2173_battery_level
      prefix: 'Fabio: ’
      style:
      border-radius: 0%
      color: ‘#fff
      font-size: 6px
      font-weight: bold
      left: 22px
      top: 32%
    • type: state-label
      entity: sensor.cph2173_steps_sensor
      style:
      border-radius: 0%
      color: ‘#fff
      font-size: 6px
      font-weight: bold
      left: 25px
      top: 35%
  1. if value of my code is TOO much long, how can say it automatically write it in 2 lines?

A comment and a question.

The questuon: I have buttons to hide/show elements on my floorplan. The button changes a helper but whern I make the element conditional on that helper it doesn’t change as expected (race condition?). I’ve hacked around it using cardmod - is there a better way?

The example image below has hidden cameras, motion sensors and people for privacy/security but temperature sensors enabled.

      - type: state-label
        entity: sensor.living_room_temp_temperature
        style:
          top: 24%
          left: 37%
          text-shadow: 0 0 5px black
        card_mod:
          style: |
            :host { 
              {% if states('input_boolean.show_temps') == 'off' %} display: none; {% endif %}
            }
        tap_action:
          action: navigate
          navigation_path: /dashboard-hvac/hvac

The comment I found that using faded yellow transparent png made a very pleasing effect when layered under lights.

Here are the three images I use, scale and rotate according to taste.

Lightblur
Lightblur-trim
Lightblur-cut

Add the image as and type: image put in in the config before the stat-label elements (or use z-index to position them above it) - Here is an example where I’m using a conditional image under a light element.

      - type: conditional
        conditions:
          - entity: switch.garage_light
            state: 'on'
        elements:
          - type: image
            image: /local/images/Lightblur.png
            style:
              top: 65%
              left: 76%
              width: 17%
          - type: image
            image: /local/images/Lightblur.png
            style:
              top: 75%
              left: 85%
              width: 17%
      - type: state-icon
        tap_action:
          action: toggle
        entity: switch.garage_light
        icon: mdi:lightbulb-fluorescent-tube
        style:
          top: 76.5%
          left: 85%
          transform: translate(-50%,-50%) scale(150%)
      - type: state-icon
        tap_action:
          action: toggle
        entity: switch.garage_light
        icon: mdi:lightbulb-fluorescent-tube
        style:
          top: 65%
          left: 76%
          transform: translate(-50%,-50%) scale(150%)

What conditional element do you mean, show a code with a conditional element with a failed attempt to use card-mod.
Anyway, check possible solutions (and a related glitch as well) for styling a conditional element in picture-elements: go to huge card-mod thread → 1st post → link at the bottom → styles for picture-elements.

Do you have a “width” properly scaled on different viewports?

Yes since width is a % of the overall picture element it scales with the picture.

1 Like

It works with card mod- it doesn’t work if I used the picure-element conditional (at least not consistently), but only for boolean helpers, using conditional for things like switches work fine.

I see no difference when using a conditional element with any entity domains.
Have already proposed you to post a faulty code, you ignored it.

This doesn’t work - it’s always positioned at bottom left.

      - type: conditional
        conditions:
          - entity: input_boolean.show_people
            state: 'on'
        elements:
          - type: image
            image: /local/images/jpp-hat.jpeg
            style:
              width: 3%
              min-width: 20px
              transform: translate(-50%,-50%)
            card_mod:
              style: |
                :host { 
                  border-radius: 50%;
                  border: 2px solid red;
                  left: {{ state_attr('device_tracker.john_s_watch','x') | float * 2.377 + 8 }}%; 
                  top: {{ 56 -(state_attr('device_tracker.john_s_watch','y') | float * 3.688)  }}% 
                }

this works - the image moves with the device tracker position from ESPresence Helper.

      - type: image
        image: /local/images/jpp-hat.jpeg
        style:
          width: 3%
          min-width: 20px
          transform: translate(-50%,-50%)
        card_mod:
          style: |
            :host { 
             {% if states('input_boolean.show_people') == 'off' 
                or 
                states('device_tracker.john_s_watch') == 'not_home' 
              %} 
                display: none; 
              {% endif %}
              border-radius: 50%;
              border: 2px solid red;
              left: {{ state_attr('device_tracker.john_s_watch','x') | float * 2.377 + 8 }}%; 
              top: {{ 56 -(state_attr('device_tracker.john_s_watch','y') | float * 3.688)  }}% 
            }