Lovelace Soft UI - Simple and Clean Lovelace Configuration

@NovaG @Darbos here’s the code - I’ll do a proper update to github once I’ve done some code commenting - I also changed it to be it’s own card on a separate lovelace view rather than popup so it would need to be adjusted for that: https://raw.githubusercontent.com/samrenfrew/homeassistant/master/tv_remote.yaml

Couple of notes:

  • Top left item is using mini-media-player to show TV source and info
  • Rather than sun.sun, I set up a new input_boolean helper called ‘dark_mode’ - an automation can then be setup to toggle theme using this input_boolean, which can also be automated to change depending on sun.sun position
  • I tried to limit the use of card-mod styling - I found that it was fine for standard CSS changes, but using if states within the style card caused pretty noticeable lag when it loaded. The custom:button-card mod has similar javascript if states and loads a lot faster
2 Likes

If you wanted to do ABC DEF etc underneath the numbers, you can use custom_fields option within the button-card mod to add them underneath

Screenshot 2020-06-21 at 12.50.36

name: '1'
show_icon: false
show_name: true
styles:
  card:
    - width: 60px
    - height: 60px
    - border-radius: 15px
    - margin-right: 10px
    - margin-bottom: 10px
    - margin-left: 15px
    - box-shadow: |
        [[[if (states['input_boolean.dark_mode'].state == 'off')
            return "-4px -4px 8px 0 rgba(255,255,255,.5),4px 4px 8px 0 rgba(0,0,0,.03)";
          return "-4px -4px 6px 0 rgba(50, 50, 50,.5),4px 4px 6px 0 rgba(0,0,0,.15)";
        ]]]
  custom_fields:
    numbers:
      - overflow: unset
      - box-shadow: none
      - font-size: 12px
      - color: var(--paper-item-icon-active-color)
  grid:
    - grid-template-areas: '"n" "numbers"'
    - grid-template-columns: 1fr
    - grid-template-rows: 1fr min-content min-content
  name:
    - font-weight: bold
    - font-family: Helvetica
tap_action:
  action: call-service
  service: webostv.button
  service_data:
    button: 1
    entity_id: media_player.tv
custom_fields:
  numbers: 'ABC'
type: 'custom:button-card'
1 Like

Thanks, I’ve got some suggestions on how to improve your card. I will do some testing and post back if I feel it’s useful.

It does look better now with your suggested changes.

Capture

So here is the things I would change:

  • The button can be the name of the field
  • The entity id should be the entity of the button
  • covert everything to variables
  • Lastly make it a template so it can be used everywhere.
    tap_action:
      action: call-service
      service: webostv.button
      service_data:
        button: '[[[ return variables.main]]]'
        entity_id: '[[[ return entity.entity_id; ]]]'
    custom_fields:
      numbers: '[[[ return variables.subtext]]]'
    variables:
      main: 1
      subtext: ABC

@N-l1

I have implemented the new code that corrects the problems with the font encountered by 0.111 but I get this gray background, why?

@N-l1 sorry for the tag but do you have any screenshots of your lights.yaml Lovelace views? Really keen to see how it looks?

It would be good to have a separate thread for this card. I don’t see one already. I am trying to get started with it to test it out but I’m not getting the tap action to work. I figured a new thread for the card would be best but should really be started by the author.

Done! Thanks for the suggestion :wink:

1 Like

@http_edo13, the code works with me. I’m not getting a grey background :thinking: mind sharing your code?

@Eldudemeister, all the screenshots are here. The light one you are referring to is the third one :smiley:

1 Like

Thanks, sorry, completely missed it :smile:

1 Like
cards:
  - content: |
      # Weather
    style: |
      .: {
         --paper-card-background-color: none;
         box-shadow: none;
      }
      ha-markdown:
      $: |
        h1 {
          font-size: 20px;
          font-weight: bold;
          font-family: Helvetica;
          letter-spacing: '-0.01em';
        }
    type: markdown
  - entity: weather.dark_sky
    style: |
      ha-card {
          background-color: var(--primary-background-color);
          border-radius: 15px;
          margin: 20px;
          box-shadow: 
               {% if is_state('sun.sun', 'above_horizon') %}
                   -8px -8px 8px 0 rgba(255,255,255,.5),8px 8px 8px 0 rgba(0,0,0,.03);
               {% else %}
                   -8px -8px 8px 0 rgba(50, 50, 50,.5),8px 8px 8px 0 rgba(0,0,0,.15);
               {% endif %}   
       }
    type: 'custom:simple-weather-card'
type: vertical-stack


this is the card for weather, with grey background in title “weather”

Hi @http_edo13, looks like you missed ha-card. This should work :slightly_smiling_face:

cards:
  - content: |
      # Weather
    style: 
      .: |
        ha-card {
          --paper-card-background-color: none !important;
          box-shadow: none !important;
        }
      ha-markdown:
      $: |
        h1 {
          font-size: 20px;
          font-weight: bold;
          font-family: Helvetica;
          letter-spacing: '-0.01em';
        }
    type: markdown
  - entity: weather.dark_sky
    style: |
      ha-card {
          background-color: var(--primary-background-color);
          border-radius: 15px;
          margin: 20px;
          box-shadow: 
               {% if is_state('sun.sun', 'above_horizon') %}
                   -8px -8px 8px 0 rgba(255,255,255,.5),8px 8px 8px 0 rgba(0,0,0,.03);
               {% else %}
                   -8px -8px 8px 0 rgba(50, 50, 50,.5),8px 8px 8px 0 rgba(0,0,0,.15);
               {% endif %}   
       }
    type: 'custom:simple-weather-card'
type: vertical-stack

Thank you!

Sorry, me again, is there a way to move the smaller button cards onto the next row? At the moment, I have a row of 5 light buttons but I have to scroll across on my phone (iphone 8) to see the final button. Is there a way of moving it onto the row below?
Config is below:

cards:
  - entity: light.cubby_light
    hold_action:
      action: more-info
      haptic: medium
    icon: 'mdi:lamp'
    name: Cubby
    show_icon: true
    show_name: true
    state:
      - styles:
          icon:
            - color: 'var(--paper-item-icon-active-color)  '
        value: 'on'
    style: |
      ha-card {
        margin: 5px;  
        margin-left: 6.5px;
        box-shadow: 
         {% if is_state('sun.sun', 'above_horizon') and is_state('light.cubby_light', 'on') %}
           inset -4px -4px 8px 0 rgba(255,255,255,.5), inset 4px 4px 8px 0 rgba(0,0,0,.03);
         {% elif is_state('sun.sun', 'above_horizon') and is_state('light.cubby_light', 'off') %}                      
           -5px -5px 8px 0 rgba(255,255,255,.5),5px 5px 8px 0 rgba(0,0,0,.03);
         {% elif is_state('sun.sun', 'below_horizon') and is_state('light.cubby_light', 'on') %}                      
           inset -4px -4px 10px 0 rgba(50, 50, 50,.5), inset 4px 4px 12px 0 rgba(0,0,0,.3); 
         {% elif is_state('sun.sun', 'below_horizon') and is_state('light.cubby_light', 'off') %}   
           -5px -5px 8px 0 rgba(50, 50, 50,.5),5px 5px 8px 0 rgba(0,0,0,.15);
         {% endif %}                      
      }
      @media only screen and (max-width: 600px) {
         ha-card {
           margin: 3px; 
           margin-left: 4px;                   
         }
      }
      @media only screen and (min-width: 1200px) {
         ha-card {
           margin: 8px;  
           margin-left: 11px;               
         }
      }
    styles:
      card:
        - width: 80px
        - height: 80px
        - border-radius: 15px
        - background-color: var(--primary-background-color)
      icon:
        - color: var(--primary-text-color)
    tap_action:
      action: toggle
      haptic: light
    type: 'custom:button-card'
  - entity: group.decklights
    hold_action:
      action: more-info
      haptic: medium
    icon: 'mdi:spotlight'
    name: Deck
    show_icon: true
    show_name: true
    state:
      - styles:
          icon:
            - color: 'var(--paper-item-icon-active-color)  '
        value: 'on'
    style: |
      ha-card {
        margin: 5px;  
        margin-left: 6.5px;
        box-shadow: 
          {% if is_state('sun.sun', 'above_horizon') and is_state('switch.plug_01_relay_1', 'on') %}
            inset -4px -4px 8px 0 rgba(255,255,255,.5), inset 4px 4px 8px 0 rgba(0,0,0,.03);
          {% elif is_state('sun.sun', 'above_horizon') and is_state('switch.plug_01_relay_1', 'off') %}                      
            -5px -5px 8px 0 rgba(255,255,255,.5),5px 5px 8px 0 rgba(0,0,0,.03);
          {% elif is_state('sun.sun', 'below_horizon') and is_state('switch.plug_01_relay_1', 'on') %}                      
            inset -4px -4px 10px 0 rgba(50, 50, 50,.5), inset 4px 4px 12px 0 rgba(0,0,0,.3); 
          {% elif is_state('sun.sun', 'below_horizon') and is_state('switch.plug_01_relay_1', 'off') %}   
            -5px -5px 8px 0 rgba(50, 50, 50,.5),5px 5px 8px 0 rgba(0,0,0,.15);
          {% endif %}                      
      }
      @media only screen and (max-width: 600px) {
         ha-card {
           margin: 3px; 
           margin-left: 4px;                   
         }
      }
      @media only screen and (min-width: 1200px) {
         ha-card {
           margin: 8px;  
           margin-left: 11px;               
         }
      }
    styles:
      card:
        - width: 80px
        - height: 80px
        - border-radius: 15px
        - background-color: var(--primary-background-color)
      icon:
        - color: var(--primary-text-color)
    tap_action:
      action: toggle
      haptic: light
    type: 'custom:button-card'
  - entity: light.bulb
    hold_action:
      action: more-info
      haptic: medium
    icon: 'mdi:door'
    name: Front Door
    show_icon: true
    show_name: true
    state:
      - styles:
          icon:
            - color: 'var(--paper-item-icon-active-color)  '
        value: 'on'
    style: |
      ha-card {
        margin: 5px;                
        box-shadow: 
          {% if is_state('sun.sun', 'above_horizon') and is_state('light.bulb', 'on') %}
            inset -4px -4px 8px 0 rgba(255,255,255,.5), inset 4px 4px 8px 0 rgba(0,0,0,.03);
          {% elif is_state('sun.sun', 'above_horizon') and is_state('light.bulb', 'off') %}                      
            -5px -5px 8px 0 rgba(255,255,255,.5),5px 5px 8px 0 rgba(0,0,0,.03);
          {% elif is_state('sun.sun', 'below_horizon') and is_state('light.bulb', 'on') %}                      
            inset -4px -4px 10px 0 rgba(50, 50, 50,.5), inset 4px 4px 12px 0 rgba(0,0,0,.3); 
          {% elif is_state('sun.sun', 'below_horizon') and is_state('light.bulb', 'off') %}   
            -5px -5px 8px 0 rgba(50, 50, 50,.5),5px 5px 8px 0 rgba(0,0,0,.15);
          {% endif %}                           
      }
      @media only screen and (max-width: 600px) {
         ha-card {
           margin: 3px; 
           margin-left: 4px;                   
         }
      }
      @media only screen and (min-width: 1200px) {
         ha-card {
           margin: 8px;  
           margin-left: 11px;               
         }
      }
    styles:
      card:
        - width: 80px
        - height: 80px
        - border-radius: 15px
        - background-color: var(--primary-background-color)
      icon:
        - color: var(--primary-text-color)
    tap_action:
      action: toggle
      haptic: light
    type: 'custom:button-card'
  - entity: light.bedside_light
    hold_action:
      action: more-info
      haptic: medium
    icon: 'mdi:bed-double'
    name: Bedside
    show_icon: true
    show_name: true
    state:
      - styles:
          icon:
            - color: 'var(--paper-item-icon-active-color)  '
        value: 'on'
    style: |
      ha-card {
        margin: 5px;  
        box-shadow: 
          {% if is_state('sun.sun', 'above_horizon') and is_state('light.bedside_light', 'on') %}
            inset -4px -4px 8px 0 rgba(255,255,255,.5), inset 4px 4px 8px 0 rgba(0,0,0,.03);
          {% elif is_state('sun.sun', 'above_horizon') and is_state('light.bedside_light', 'off') %}                      
            -5px -5px 8px 0 rgba(255,255,255,.5),5px 5px 8px 0 rgba(0,0,0,.03);
          {% elif is_state('sun.sun', 'below_horizon') and is_state('light.bedside_light', 'on') %}                      
            inset -4px -4px 10px 0 rgba(50, 50, 50,.5), inset 4px 4px 12px 0 rgba(0,0,0,.3); 
          {% elif is_state('sun.sun', 'below_horizon') and is_state('light.bedside_light', 'off') %}   
            -5px -5px 8px 0 rgba(50, 50, 50,.5),5px 5px 8px 0 rgba(0,0,0,.15);
          {% endif %}     
      }
      @media only screen and (max-width: 600px) {
         ha-card {
           margin: 3px; 
           margin-left: 4px;                   
         }
      }
      @media only screen and (min-width: 1200px) {
         ha-card {
           margin: 8px;  
           margin-left: 11px;               
         }
      }
    styles:
      card:
        - width: 80px
        - height: 80px
        - border-radius: 15px
        - background-color: var(--primary-background-color)
      icon:
        - color: var(--primary-text-color)
    tap_action:
      action: toggle
      haptic: light
    type: 'custom:button-card'
  - entity: light.wled
    hold_action:
      action: more-info
      haptic: medium
    icon: 'mdi:bed-single-outline'
    name: Jasper
    show_icon: true
    show_name: true
    state:
      - styles:
          icon:
            - color: 'var(--paper-item-icon-active-color)  '
        value: 'on'
    style: |
      ha-card {
        margin: 5px;  
        margin-left: 6.5px;
        box-shadow: 
         {% if is_state('sun.sun', 'above_horizon') and is_state('light.wled', 'on') %}
           inset -4px -4px 8px 0 rgba(255,255,255,.5), inset 4px 4px 8px 0 rgba(0,0,0,.03);
         {% elif is_state('sun.sun', 'above_horizon') and is_state('light.wled', 'off') %}                      
           -5px -5px 8px 0 rgba(255,255,255,.5),5px 5px 8px 0 rgba(0,0,0,.03);
         {% elif is_state('sun.sun', 'below_horizon') and is_state('light.wled', 'on') %}                      
           inset -4px -4px 10px 0 rgba(50, 50, 50,.5), inset 4px 4px 12px 0 rgba(0,0,0,.3); 
         {% elif is_state('sun.sun', 'below_horizon') and is_state('light.wled', 'off') %}   
           -5px -5px 8px 0 rgba(50, 50, 50,.5),5px 5px 8px 0 rgba(0,0,0,.15);
         {% endif %}                      
      }
      @media only screen and (max-width: 600px) {
         ha-card {
           margin: 3px; 
           margin-left: 4px;                   
         }
      }
      @media only screen and (min-width: 1200px) {
         ha-card {
           margin: 8px;  
           margin-left: 11px;               
         }
      }
    styles:
      card:
        - width: 80px
        - height: 80px
        - border-radius: 15px
        - background-color: var(--primary-background-color)
      icon:
        - color: var(--primary-text-color)
    tap_action:
      action: toggle
      haptic: light
    type: 'custom:button-card'
type: horizontal-stack

Hi @Eldudemeister, no worries, glad to help. If you only access the UI from your phone, you can adjust the size of each button (so more will fit) by changing the width + height or by changing the margin. This, however, will probably mess up the sizing of the card on any other display. A better method would be responsive sizing by adjusting the margin here (shrink it to 2 or 1.5px)

      @media only screen and (max-width: 600px) {
         ha-card {
           margin: 3px; 
           margin-left: 4px;                   
         }
      }

You can find out more about it in a similar issue here, and in other closed issues on GitHub. Let me know if you need more help.

Thanks for this, is there a way to move a button onto the next line instead? I’ve tried changing the margin but it doesnt change on my phone…

You can always just create another card for the second row. However, if you would like to do it responsively, you would probably need something like state-switch. E.g. display one single row with 5 buttons when the screen size is big; then if the screen size is small, display 2 rows, one with 4 button and another with a single button :grinning:

1 Like

If you upgraded to 0.113 and have ‘broken’ markdown cards: see release notes -> breaking changes -> frontend: themes :slightly_smiling_face:

1 Like

A few questions:

  1. How can and middle align the text on the right of the icons under Home to the icon itself? How can I move them down a bit?

  2. The description “There are currently no lights on” is updated every minute. Is there any way for it to update as I turn on/off a light?

  3. Sensor element’s bottom half is not rounded.

Capture
22

As for that:
1.

  • First way with card-mod: Just change the margin attribute.
    • To keep the existing 20px on the left and right, but to change the top margin: 40px 20px (first is top/bottom).
    • To control each one: 10px 20px 30px 40px (clockwise starting from top)
  • Second way with button-card:
show_icon: false
show_name: false
style: |
  ha-card {
    --paper-card-background-color: none !important;
    box-shadow: none !important;
  }
styles:
  card:
    - width: 5px
    - height: 45px
type: 'custom:button-card'
# Modify height as needed
  1. If you’re using a template sensor, then specify entity_id as a string or list of strings. In 0.115, if not auto-detected, check out Heads up! Upcoming breaking change in the Template integration. I don’t know how to do it client-side.
  2. Use mod-card, just add a card: to the top, indent everything using Ctrl/Command + ] except style, and add type: 'custom:mod-card'
2 Likes

Thanks for your reply! I got the first on fixed and working with adjusting the margin attribute. I will try fix the second later but I can’t get the sensor card working.

I managed to warp it into a mod-card and both shadow and margin attribute works but not the rounded corners. Here is my code.

type: 'custom:mod-card'
style: |
  ha-card {
    margin: 10px;
    border-radius: 15px;
    background-color: var(--primary-background-color);
    box-shadow: 
      {% if is_state('sun.sun', 'above_horizon') %}
        -8px -8px 8px 0 rgba(255,255,255,.5),8px 8px 8px 0 rgba(0,0,0,.03);
      {% elif is_state('sun.sun', 'below_horizon') %}
        -8px -8px 8px 0 rgba(50, 50, 50,.5),8px 8px 8px 0 rgba(0,0,0,.15);
      {% endif %}                 
  }  
card:
  type: sensor
  entity: sensor.frigate_coral_fps
  graph: line