šŸ”¹ Card-mod - Super-charge your themes!

THANK YOU for this.

Iā€™ve been trying to make closing the more-info popups easier on mobile instead of reaching to the top-left X (any ideas out there??), and with your sample Iā€™ve made them more of a popup where I can click on the sides/bottom (outside) to close it:

They also adjust height automatically based on the content.

  card-mod-more-info-yaml: |
    .: |
      @media (max-width: 450px) {
        ha-dialog {
            --mdc-dialog-min-width: calc(95vw)!important;
            --mdc-dialog-min-height: 0!important;
            --mdc-dialog-max-height: 90%!important;
            --dialog-surface-margin-top: 20px!important;
            --ha-dialog-border-radius: 20px!important;
        }
      }
    ha-more-info-info:
      $: |
        @media (max-width: 450px) {
          .container {
            min-height: auto!important;
          }
        }

I also tried making a border-radius on bottom-right, but although clicking the radius area works (closes the popup) on desktop, it doesnā€™t display (nor tapping it works) on iOS HA app (although it does in the screenshot for some reason). On Chrome iOS, it displays but doesnā€™t close the popup.

Iā€™m not very good with card-mod (understanding the $, .:, |, etc.)

1 Like

I donā€™t have black as default so need to set it back to black in the bar only.

i donā€™t have underscores? :stuck_out_tongue:

Edit: the minus -
It works now, Thanks!

Yes, I meant hyphens, not underscores)

1 Like

Need a little help with classesā€¦

Iā€™m trying to establish different classes that I can use to style certain domains of card, for example:

type: tile
entity: light.sofa_lights
card_mod:
  class: light

or

type: tile
entity: switch.coffee_machine
card_mod:
  class: switch

Here is my theme file:

test:
  card-mod-theme: test
  card-mod-card-yaml: |
      .: |
        @keyframes fadeIn {
          0% { opacity: 0; }
          100% { opacity: 1; }
        }
        
        ha-card {
          height: 60px !important;
          width: 180px !important;
          animation: fadeIn 1s ease;
          border-radius: 15px;
          border-color: transparent;
          box-shadow: 0px 0px 0px 0px;
          background:
            {% if is_state(config.entity, 'on') %} white
            {% else %} rgba(0,0,0,0.3) {% endif %}
        }

        .icon-container {
          position: absolute !important;
          margin-left: -20px !important;
          margin-top: -20px !important;
          left: 30px !important;
          top: 50% !important
        }
      
        ha-card.light ha-tile-icon {
          --tile-icon-color:
            {% if is_state(config.entity, 'on') %} var(--tile-color)
            {% else %} gold {% endif %} !important
        }

        ha-card.switch ha-tile-icon {
          --tile-icon-color:
            {% if is_state(config.entity, 'on') %} var(--tile-color)
            {% else %} palegreen {% endif %} !important
        }

        ha-card.automation ha-tile-icon {
          --tile-icon-color:
            {% if is_state(config.entity, 'on') %} var(--tile-color)
            {% else %} lightgrey {% endif %} !important
        }

        ha-tile-info {
          position: absolute !important;
          padding: 0% !important;
          margin-top: -20px;
          left: 60px;
          top: 50%;
          max-width: 110px
        }
      
      ha-tile-icon$: |
        div.shape::before {
          background-color:
            {% if is_state(config.entity, 'on') %} var(--tile-icon-color)
            {% else %} rgba(0,0,0,0.6) {% endif %}
          }
          
      ha-tile-info$: |
        span.primary {
          color:
            {% if is_state(config.entity, 'on') %} black
            {% else %} white {% endif %};
          }
          
        span.secondary {
          color:
            {% if is_state(config.entity, 'on') %} grey
            {% else %} lightgrey {% endif %};
          font-size: 14px
          }

As you can see, I have specified class-specific elements in the .: section (for example,
ha-card.light ha-tile-icon
and these work fine. However I canā€™t seem to get the code right for shadowDOM elements (like
ha-tile-icon$
) - any ideas how I need to format it?

getting back to this Ince more, as I wanted to see what it would look like if a power sensor was used in the menu column.

posting here, because the technique used in core and here doesnt hold in that case, because the number if digits can grow much bigger than 2ā€¦

had t style from the right side instead if the calculated left:

      a[data-panel='ui-data'] paper-icon-item:after {
              content: "{{states('sensor.netto_verbruik')}}";
              /*left: calc(var(--app-drawer-width) - 42px);*/
              right: 12px;
              position: absolute;
              min-width: 20px;
              box-sizing: border-box;
              border-radius: 24px;
              font-weight: 400;
              background-color: {{'saddlebrown' if states('sensor.levering_of_verbruik')|int(default=0) > 0
                                   else 'gold'}};
              line-height: 20px;
              text-align: center;
              padding: 0px 6px;
              color: {{'ivory' if states('sensor.netto_verbruik')|int(default=0) > 0
                        else 'saddlebrown'}};
              /*var(--text-accent-color, var(--text-primary-color));*/
              font-size: 14px;
      }

SchermĀ­afbeelding 2023-03-07 om 13.17.49

Still no sure it is perfect, but it does look kind if ok. except for the collapsed menuā€¦

but I ever use that anywayā€¦

in my case:
ŠøŠ·Š¾Š±Ń€Š°Š¶ŠµŠ½ŠøŠµ

right, how did you manage that?

Ivā€™e tried centering the contentā€¦ but no, didnt help

Sorry, what?

I am using a code from my theme which was posted here.

HA!!
Sorry I couldnā€™t resist replying. I believe he meant ā€˜manageā€™.
(I know you are both not native English speakers)

this has nothing to do with non-native, but with fat fingers and auto-correctā€¦

but yes: How did you manage ?

:wink:

could you please test with a longer string? and a minus like ā€œ-1234ā€?
because that is where the spacing went off in the full menu bar (the right side issue I mentioned above), and also with the collapsed menu, it being really off-center

your font-size btw seems much smaller than the core notification? Thatā€™s what I copied the styles from, hoping to get those to look alike as much as possible

I made this mod for positive values <=9999 since this is an ALERT badge.
If talking about ā€œissuesā€ or ā€œerrorsā€ - do not think that values > 9999 are expected, mainly values <100.

Anyway:
999:
ŠøŠ·Š¾Š±Ń€Š°Š¶ŠµŠ½ŠøŠµ

9999 - almost unreadable:
ŠøŠ·Š¾Š±Ń€Š°Š¶ŠµŠ½ŠøŠµ

-1234:
ŠøŠ·Š¾Š±Ń€Š°Š¶ŠµŠ½ŠøŠµ

Font size is set dependingly on a value.
Could differ from a default one, I do not know.

In see! I checked the wrong section, and now see that you use this:

      a[data-panel='lovelace-security'] paper-icon-item:after {
        {% set NUMBER_OF_ISSUES = states('sensor.security_number_of_issues_home')|float(default=0) %}
        {% if is_state('binary_sensor.security_mode_guarded_home','on') and NUMBER_OF_ISSUES > 0 %}
          content: "{{NUMBER_OF_ISSUES|round(0)}}";
          {% if NUMBER_OF_ISSUES < 10 %}
            font-size: 14px;
            padding: 0px 6px;
          {% elif NUMBER_OF_ISSUES >= 10 and NUMBER_OF_ISSUES < 100 %}
            font-size: 11px;
            padding: 0px 4px;
          {% elif NUMBER_OF_ISSUES >= 100 and NUMBER_OF_ISSUES < 1000 %}
            font-size: 8px;
            padding: 0px 3px;
          {% else %}
            font-size: 6px;
            padding: 0px 2px;
          {% endif %}
          font-weight: 400;
          left: calc(var(--app-drawer-width) - 42px);
          position: absolute;
          min-width: 20px;
          box-sizing: border-box;
          border-radius: 50%;
          background-color: var(--theme-security-issues);
          line-height: 20px;
          text-align: center;
          color: var(--text-accent-color, var(--text-primary-color));
        {% endif %}
      }

hmm, must check that based on my possible values from -8000 to +8000 as its a power meter.

will post back if I MANAGEā€¦ :wink:
btw, I dont mind if it overflows the icon, I just would like to position it centrally in the collapsed menu column

back !

this would do fine:

      a[data-panel='ui-data'] paper-icon-item:after {
              content: "{{states('sensor.netto_verbruik')}}";
              {% set length = states('sensor.netto_verbruik')|length %}
              {% set table = {1:42,2:48,3:52,4:56,5:60} %}
              {% set pix = table.get(length,42) %}
              left: calc(var(--app-drawer-width) - {{pix}}px);
              /*right: 14px;*/
              position: absolute;
              min-width: 20px;
              box-sizing: border-box;
              border-radius: 24px;
              font-weight: 400;
              font-size: 14px;
              line-height: 20px;
              text-align: center;
              padding: 0px 6px;
              background-color: {{'saddlebrown' 
                                    if states('sensor.levering_of_verbruik')|int(default=0) > 0
                                    else 'gold'}};
              color: {{'ivory' if states('sensor.netto_verbruik')|int(default=0) > 0
                        else 'saddlebrown'}};
      }

it does change the approach I had before: it no longer takes a fixed distance to the right column border, but tries to centralize it:

SchermĀ­afbeelding 2023-03-07 om 23.49.36

if you see the template, it is quite straightforward, as it uses 4pixels per character.

no changing paddings or font-size, which is not very attractive, this makes it look like ā€˜coreā€™ styling.

just had a brainwaveā€¦, and figured why no add this to the Energy panel item in the left side menuā€¦

so yes, that works too:

SchermĀ­afbeelding 2023-03-08 om 10.31.45

however, I can Not color the icon itself, even though the code seems to point the same item:

      a[data-panel='energy'] paper-icon-item ha-icon {
          color: {{'saddlebrown' if states('sensor.levering_of_verbruik')|int(default=0) > 0
                    else 'gold'}};
          /*background: {{'gold' if states('sensor.levering_of_verbruik')|int(default=0) > 0
                           else 'saddlebrown'}};
            border-radius: 24px*/
      }

      a[data-panel='energy'] paper-icon-item:after {
              content: "{{states('sensor.netto_verbruik')}}";
              {% set length = states('sensor.netto_verbruik')|length %}
              {% set table = {1:42,2:48,3:52,4:56,5:60} %}
              {% set pix = table.get(length,42) %}
              left: calc(var(--app-drawer-width) - {{pix}}px);
              /*right: 14px;*/
              position: absolute;
              min-width: 20px;
              box-sizing: border-box;
              border-radius: 24px;
              font-weight: 400;
              font-size: 14px;
              line-height: 20px;
              text-align: center;
              padding: 0px 6px;
              background-color: {{'saddlebrown' if
                                   states('sensor.levering_of_verbruik')|int(default=0) > 0
                                   else 'gold'}};
              color: {{'ivory' if states('sensor.netto_verbruik')|int(default=0) > 0
                        else 'saddlebrown'}};
      }

and the elements mod like this

is indeed not shown, like it does for the other menu items.

So, can we Not color the Energy panel icon?

trying to move the paper-tab-selection-bar (white bar below the icon) to the top of the icon.

anyone knows how to do it?

Screenshot 2023-03-08 123631

please could anyone help me out how to get to the Assist button in the menu-bar?

      app-toolbar > ha-icon-button > button[aria-label='Assist'] {
        {% if is_state('input_boolean.hide_assist','on') %}display: none;{% endif %}
      }

does not work even though:

and

      /* Hide the quickbar launcher. mdi:magnifier */
      app-toolbar > ha-icon-button {
        {% if is_state('input_boolean.hide_search','on') %}display: none;{% endif %}
      }

takes out both search And Assist buttonā€¦

Just in case anyone else had the same problem as me, this is the context you need to use if trying to add class-specific modifications to shadowDOM elements either in a card or in a theme:

theme.yaml:

theme-name:
  card-mod-theme: theme-name
  card-mod-card-yaml: |
     ### for the card or elements in the card
     .: |
        ha-card.classname {
          height: 60px !important;
        }

        ha-card.classname ha-tile-icon {
          --tile-icon-color:
            {% if is_state(config.entity, 'on') %} var(--tile-color)
            {% else %} gold {% endif %} !important
        }

     ### for shadowDOM elements - get path by inspecting element
     ha-card.classname>div.tile>div.content>div.icon-container>ha-tile-icon$: |
       div.shape::before {
         background-color: white
         }
1 Like

I do not think it will work.
In short:
this will work:

ha-card.some_class some_element { ... }

this will not:

ha-card.some_class some_element $:
  some_element { ... }

Are you sure your idea works?

I know only one method of defining a ā€œclassy shadowRoot elementā€ - using variables.

Try it. It works.

Here is a theme Iā€™m building at the moment:

test:
  card-mod-theme: test
  card-mod-card-yaml: |
    .: |
      @keyframes fadeIn {
        0% { opacity: 0; }
        100% { opacity: 1; }
      }

      ha-card {
        height: 60px !important;
        width: 180px !important;
        animation: fadeIn 1s ease;
        border-radius: 15px;
        border: none;
        background:
          {% if is_state(config.entity, 'on') %} white
          {% else %} rgba(0,0,0,0.5) {% endif %}
      }

      ha-card.automation {
        --tile-color:
          {% if is_state(config.entity, 'on') %} lightgrey !important
          {% else %} grey !important {% endif %};
        --mdc-ripple-color: lightgrey !important;
      }

      ha-card.light {
      }

      ha-card.switch {
        --tile-color:
          {% if is_state(config.entity, 'on') %} palegreen !important
          {% else %} grey !important {% endif %};
        --mdc-ripple-color: palegreen !important;
      }

      ha-card.water {
        --tile-color:
          {% if is_state(config.entity, 'on') %} deepskyblue !important
          {% else %} grey !important {% endif %};
        --mdc-ripple-color: deepskyblue !important;
      }

      .icon-container {
        position: absolute !important;
        margin-left: -20px !important;
        margin-top: -20px !important;
        left: 30px !important;
        top: 50% !important;
      }

      ha-card.automation ha-tile-icon {
        --tile-icon-color:
          {% if is_state(config.entity, 'on') %} white
          {% else %} lightgrey {% endif %} !important
      }

      ha-card.light ha-tile-icon {
        --tile-icon-color:
          {% if is_state(config.entity, 'on') %} white
          {% else %} gold {% endif %} !important
      }

      ha-card.switch ha-tile-icon {
        --tile-icon-color:
          {% if is_state(config.entity, 'on') %} white
          {% else %} palegreen {% endif %} !important
      }

      ha-card.water ha-tile-icon {
        --tile-icon-color:
          {% if is_state(config.entity, 'on') %} white
          {% else %} deepskyblue {% endif %} !important
      }

      ha-tile-info {
        position: absolute !important;
        padding: 0% !important;
        margin-top: -20px;
        left: 60px;
        top: 50%;
        max-width: 110px
      }
    ha-card.automation>div.tile>div.content>div.icon-container>ha-tile-icon$: |
      div.shape::before {
        opacity: 0
        }
      div.shape {
        background-color:
          {% if is_state(config.entity, 'on') %} lightgrey
          {% else %} rgba(0,0,0,0.2) {% endif %};
        }
    ha-card.light>div.tile>div.content>div.icon-container>ha-tile-icon$: |
      div.shape::before {
        opacity: 0
        }
      div.shape {
        background-color:
          {% if is_state(config.entity, 'on') %} var(--tile-color)
          {% else %} rgba(0,0,0,0.2) {% endif %};
        }
    ha-card.switch>div.tile>div.content>div.icon-container>ha-tile-icon$: |
      div.shape::before {
        opacity: 0
        }
      div.shape {
        background-color:
          {% if is_state(config.entity, 'on') %} palegreen
          {% else %} rgba(0,0,0,0.2) {% endif %};
        }
    ha-card.water>div.tile>div.content>div.icon-container>ha-tile-icon$: |
      div.shape::before {
        opacity: 0
        }
      div.shape {
        background-color:
          {% if is_state(config.entity, 'on') %} deepskyblue
          {% else %} rgba(0,0,0,0.2) {% endif %};
        }
        
    ha-tile-info$: |
      .primary {
        color:
          {% if is_state(config.entity, 'on') %} black
          {% else %} white {% endif %};
        }
        
      .secondary {
        color:
          {% if is_state(config.entity, 'on') %} grey
          {% else %} lightgrey {% endif %};
        font-size: 14px
        }

In my dashboard I simply set the theme and then use tile cards, each with an assigned class. The themed shadowDOM elements (in this case, the div.shape bits for colouring the icon) work correctly showing different colours for different classes.

Great that you posted here your real code - but could you demonstrate it with a short solution? (which may be reproduced)