A different take on designing a Lovelace UI

conditional_media in my opinion was the hardest thing to wrap my head around.

Based on the info you provided, you have not updated the conditional_media template.

This template has 2 templates inside out it one for the possible options and one for the selected option that should be the name of the entity you would like to display

This is mine, it might help for you to see what I have changed.

---
unique_id: conditional_media
name: conditional_media
state: >
  {% set recently_added = 'Last added' %}
  {% set paused_timeout_minutes = 15 %}
  {% set media_players = [
    states.media_player.plex_prologue_mason,
    states.media_player.spotify,
    states.media_player.living_room_tv,
    states.media_player.plex_plex_for_lg_lg_oled65cxpta ] %}

  {% macro media(state) %}
  {% set state = media_players | selectattr('state','eq',state) | list %}
  {% set last_changed = recently_added if state | length == 0 else state | map(attribute='last_changed') | list | max %}
    {{ state | selectattr('last_changed','eq', last_changed) | map(attribute='name') | list | join }}
  {% endmacro %}

  {% set on = media_players | selectattr('state','eq','on')| list %}
  {% set timeout_playing = False if on | length == 0 else
    (as_timestamp(now()) - as_timestamp(on | map(attribute='last_changed') | list | max)) < paused_timeout_minutes * 60 %}

  {% set playing = media_players | selectattr('state','eq','playing') | list %}
  {% set timeout_playing = False if playing | length == 0 else
    (as_timestamp(now()) - as_timestamp(playing | map(attribute='last_changed') | list | max)) < paused_timeout_minutes * 60 %}

  {% set paused = media_players | selectattr('state','eq','paused') | list %}
  {% set timeout_paused = False if paused | length == 0 else
    (as_timestamp(now()) - as_timestamp(paused | map(attribute='last_changed') | list | max)) < paused_timeout_minutes * 60 %}

  {% if playing %}
    {{ media('playing') if timeout_playing else media('paused') if timeout_paused else media('playing') }}
  {% elif on %}
    {{ media('on')}}
  {% elif paused %}
    {{ media('paused') if timeout_paused else recently_added }}
  {% else %}
    {{ recently_added }}
  {% endif %}
options: >
  {% set recently_added = ['Last added'] %}
  {% set media_players = [
    states.media_player.living_room_tv,
    states.media_player.plex_prologue_mason,
    states.media_player.spotify,
    states.media_player.plex_plex_for_lg_lg_oled65cxpta ] %}
  {{ recently_added + media_players | map(attribute='name') | list }}
select_option:
  service: select.select_option
  target:
    entity_id: select.conditional_media
  data:
    option: >
      {{ option }}

I started to learn it by myself yesterday :wink: this video helped me a lot to get started. Make Awesome SVG Animations with CSS // 7 Useful Techniques - YouTube

Graph part came from post #3181

Nevertheless, this is the slightly modified template code I’m using

graph:
  custom_fields:
    graph:
      card:
        type: "custom:mini-graph-card"
        height: 200
        entities:
          - entity: "[[[ return variables.graph_entity ]]]"
        hours_to_show: 48
        points_per_hour: 1
        line_width: 8
        font_size: 75
        decimals: 0
        show:
          name: false
          icon: false
          state: false
          legend: false
          labels: false
          labels_secondary: false
          points: false
        color_thresholds:
          - value: 40
            color: "#276696"
          - value: 50
            color: "#228C22"
          - value: 55
            color: "#d35400"
          - value: 60
            color: "#c0392b"          
  styles:
    card:
      - border-width: 0  
    custom_fields:
      card:
        - border-width: 0
      graph: [bottom: 0%, left: 0%, width: 125%, position: absolute, margin: 0% 0% 0% 0% ] #-13% -14%]
  card_mod:
    style: |
      :host{
        --accent-color: #039be5;
        --ha-card-border-width: 0px;
      }

But it should not interfere with the circle.

the console.log gives the actual value

(function anonymous(states,entity,user,hass,variables,html
) {
'use strict';  
  console.log(states['sensor.woonkamer_temperature'].state)
  return states['sensor.woonkamer_temperature'].state; 

})

18.76

Hi , thank you for the reply. unfortunately I can’t solve the puzzle.
Static image until a player is activated would be enough.

#################################################
#                                               #
#                  BASE MEDIA                   #
#                                               #
#################################################

base_media:
  variables:
    media_on: >
      [[[ return !entity || ['playing', 'paused'].indexOf(entity.state) !== -1; ]]]
    media_off: >
      [[[ return !entity || ['off', 'idle', 'standby', 'unknown', 'unavailable'].indexOf(entity.state) !== -1; ]]]
  tap_action:
    action: >
      [[[
        return variables.media_on
            ? 'call-service'
            : 'none';
      ]]]
    service: media_player.media_play_pause
    service_data:
      entity_id: >
        [[[
          return variables.entity_id;
        ]]]
  double_tap_action:
    action: more-info
  styles:
    card:
        - color: >
            [[[
              let entity_picture = entity === undefined || entity.attributes.entity_picture;
              if (variables.state === 'off' || variables.state === 'idle' || variables.state === 'standby' ||
                variables.state === 'unknown' || variables.state === 'unavailable' || entity === undefined) {
                return 'rgba(255, 255, 255, 0.3)';
              }
              return (variables.state != 'off' && variables.state != 'idle' && variables.state != 'standby') && (entity_picture == null) ? 'rgba(0, 0, 0, 0.6)' : '#efefef';
            ]]]
        - text-shadow: >
            [[[
              let entity_picture = entity === undefined ? null : entity.attributes.entity_picture;
              if (variables.state === 'off' || variables.state === 'idle' || variables.state === 'standby' || variables.state === 'unknown' || variables.state === 'unavailable') {
                return entity_picture == null ? 'none' : '1px 1px 5px rgba(18, 22, 23, 0)';
              }
              return entity_picture == null ? 'none' : '1px 1px 5px rgba(18, 22, 23, 0.9)';
            ]]]
#################################################
#                                               #
#                     MEDIA                     #
#                                               #
#################################################

media:
  template:
    - base
    - base_media
  styles:
    custom_fields:
      icon:
        - width: 70%
        - margin-left: 2%
        - fill: '#9da0a2'
        - display: >
              [[[
                return variables.media_off || variables.entity_picture === undefined
                    ? 'initial'
                    : 'none';
              ]]]
    card:
      - background-color: none
      - background-size: cover
      - background-position: center
      - background-image: >
            [[[
              let entity_picture = entity === undefined || entity.attributes.entity_picture;
              if (variables.state === 'off' || variables.state === 'idle' || variables.state === 'standby' ||
                variables.state === 'unknown' || variables.state === 'unavailable' || entity === undefined) {
                return 'linear-gradient(0deg, rgba(115, 115, 115, 0.2) 0%, rgba(115, 115, 115, 0.2) 100%)';
              }
              return (variables.state != 'off' && variables.state != 'idle' && variables.state != 'standby') && (entity_picture == null) ?
                'linear-gradient(0deg, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0.8) 100%)' :
                'linear-gradient(0deg, rgba(0,0,0,.8) 0%, rgba(0,0,0,0) 100%), url(' + entity_picture + ')';
            ]]]


#################################################
#                                               #
#               CONDITIONAL MEDIA               #
#                                               #
#################################################

conditional_media:
  aspect_ratio: 1000/996
  template:
    - base
    - base_media
    - icon_play_pause
  variables:
    i: >
      [[[
        if (entity) {
            let data = entity.attributes.data;
            return data === undefined || Math.floor(Math.random() * (data.length - 1)) + 1;
        }
      ]]]
  state_display: >
    [[[
      if (entity) {
          let elt = this.shadowRoot,
              await = setTimeout(marquee, 100),
              data = entity.attributes.data,
              artist = entity.attributes.media_artist,
              title = entity.attributes.media_title;

            if (data !== undefined) {
                var number = data[variables.i].number === undefined && data[variables.i].aired !== undefined
                    ? `(${data[variables.i].aired.split("-")[0]})`
                    : data[variables.i].number === undefined && data[variables.i].aired === undefined
                        ? ' '
                        : data[variables.i].number,
                output = `${data[variables.i].title} ${number}`;
            } else {
                var output = artist === undefined && title !== undefined
                    ? title
                    : title === undefined && artist !== undefined
                        ? artist
                        : title !== undefined && artist !== undefined
                            ? `${artist} - ${title}`
                            : variables.translate_idle;
            }

          function marquee() {
              let state = elt.getElementById("state"),
                  container = elt.getElementById("container");

              if (state && container) {
                  state.innerHTML = output;
                  let ro = new ResizeObserver(entries => {
                      let spacer = "&nbsp;".repeat(3),
                          s = entries[0],
                          c = entries[1],
                          r = s && s.contentRect &&
                              c && c.contentRect &&
                              s.contentRect.width !== 0 &&
                              c.contentRect.width !== 0;

                      if (r && s.contentRect.width < c.contentRect.width) {
                          state.classList.remove("marquee");
                      }
                      else if (r && s.contentRect.width >= c.contentRect.width) {
                          state.innerHTML = `${output} ${spacer} ${output} ${spacer}&nbsp;`;
                          state.classList.add("marquee");
                      }
                  });
                  ro.observe(state);
                  ro.observe(container);
              }
          }
          return output;
      }
      return variables.translate_unknown;
    ]]]
  tap_action:
    action: call-service
    service: media_player.media_play_pause
    service_data:
      entity_id: >
        [[[ return variables.entity_id; ]]]
  styles:
    grid:
      - gap: 0.65%
    name:
      - padding: 0.2vw
      - margin: -0.2vw
    state:
      - padding-bottom: 5.25%
      - max-width: unset
      - overflow: visible
    card:
      - padding: 5.75% 5.25% 0 5.75%
      - border-radius: calc(var(--button-card-border-radius) / 2)
      - background: rgba(115, 115, 115, 0.2) center center/cover no-repeat
      - background-image: &media_background_image >
          [[[
            if (entity) {
                let data = entity.attributes.data;
                return data && (data[variables.i].fanart || data[variables.i].poster)
                    ? `url("${data[variables.i].fanart}"), url("${data[variables.i].poster}")`
                    : `url("${variables.entity_picture}")`;
              }
          ]]]
      - color: >
          [[[
            return entity === undefined
                ? '#97989c'
                : '#efefef';
          ]]]
      - text-shadow: >
          [[[
            return entity === undefined
                ? 'none'
                : '1px 1px 5px rgba(18, 22, 23, 0.9)';
          ]]]
    custom_fields:
      icon:
        - width: 30%
        - fill: >
            [[[
              return entity && variables.media_on
                  ? 'rgba(255, 255, 255, 0.8)'
                  : '#9da0a2';
            ]]]
      blur_overlay:
        - display: block
        - position: absolute
        - width: 103.1%
        - height: 103.1%
        - filter: var(--blur-intensity)
        - clip-path: >
            inset(74.5% 1.45% 1.45% 1.45% round 0 0 calc(var(--button-card-border-radius) / 2) calc(var(--button-card-border-radius) / 2))
        - background: center center/cover no-repeat
        - background-image: *media_background_image
        - left: -1.5%
        - bottom: -1.6%
  custom_fields:
    blur_overlay: >
      [[[
        setTimeout(() => {
            let elt = this.shadowRoot,
                card = elt.getElementById('card'),
                container = elt.getElementById('container'),
                blur_overlay = elt.getElementById('blur_overlay');
            if (elt && card && container && blur_overlay) {
                card.insertBefore(blur_overlay, container);
            }
          }, 0);
        return ' ';
      ]]]

      #################################################
      #                                               #
      #                     MEDIA                     #
      #                                               #
      #################################################

      - type: grid
        title: Media
        view_layout:
          grid-area: media
        columns: 1
        cards:

          - type: custom:swipe-card
            parameters:
              roundLengths: true
              effect: coverflow
              speed: 650
              spaceBetween: 20
              threshold: 7
              coverflowEffect:
                rotate: 80
                depth: 300
            cards:

              - type: horizontal-stack
                cards:

                    - type: conditional
                      conditions:
                        - entity: select.conditional_media
                          state_not: Spotify_D
                        - entity: select.conditional_media
                          state_not: Spotify_L
                        - entity: select.conditional_media
                          state_not: PLEX

                      card:
                        type: custom:button-card
                        entity: media_player.spotify_dennis
                        name: Currently playing
                        tap_action:
                          action: none
                        template:
                          - conditional_media
                          - icon_spotify

                    - type: conditional
                      conditions:
                        - entity: select.conditional_media
                          state: Spotify_D
                      card:
                        type: custom:button-card
                        entity: media_player.spotify_dennis
                        template:
                          - conditional_media
                          - icon_spotify

                    - type: conditional
                      conditions:
                        - entity: select.conditional_media
                          state: Spotify_L
                      card:
                        type: custom:button-card
                        entity: media_player.spotify_lillian
                        template:
                          - conditional_media
                          - icon_spotify

                    - type: conditional
                      conditions:
                        - entity: select.conditional_media
                          state: PLEX
                      card:
                        type: custom:button-card
                        entity: media_player.plex_dennis_plex_for_lg_lg_oled48cx6lb
                        template:
                          - conditional_media
                          - icon_plex

            # SWIPE CARD - 2nd PAGE
              - type: grid
                columns: 1
                cards:

what values are in the select.conditional_media entity?

have you modified the code in the select template sensor for select.conditional_media?

thanks with that I was able to test and I found the issue, you have 2 options to solve this

ignore the broken line that should just be an issue on my end.

option 1: update the circle template

in button_card_templates/circle.yaml

find this section of code

           /* * * * * * * * * * * * * * * * * *
            *                                 *
            *              OTHER              *
            *                                 *
            * * * * * * * * * * * * * * * * * */

            else if (variables.state_on) {
                return circle(state, input, unit);
            }

and replace it with this

            /* * * * * * * * * * * * * * * * * *
            *                                  *
            *              SENSOR              *
            *                                  *
            * * * * * * * * * * * * * * * * * */

            else if (domain === 'sensor') {
                return circle(state, input, unit);
            }

           /* * * * * * * * * * * * * * * * * *
            *                                 *
            *              OTHER              *
            *                                 *
            * * * * * * * * * * * * * * * * * */

            else if (variables.state_on) {
                return circle(state, input, unit);
            }

changes to the base template like this can result in some issues and when you update you will need to remember to not remove that change

option 2: override the custom_fields

add the code to draw the circle to your custom template

template

graph:
  template:
    - base
    - circle
  custom_fields:
    circle: >
      [[[
        let r = 22.1,
          c = r * 2 * Math.PI,
          tspan = '<tspan dx=".2" dy="-.4">',
          domain = entity.entity_id.split('.')[0],
          state = variables.state_on,
          input = variables.circle_input || ' ',
          unit = variables.circle_input_unit || ' ';
        return `
          <svg viewBox="0 0 50 50">
            <style>
              circle {
                transform: rotate(-90deg);
                transform-origin: 50% 50%;
                stroke-dasharray: ${c};
                stroke-dashoffset: ${typeof input === 'number' && c - input / 100 * c};
                stroke-width: var(--c-stroke-width);
                stroke: ${state ? 'var(--c-stroke-color-on)' : 'var(--c-stroke-color-off)'};
                fill: ${state ? 'var(--c-fill-color-on)' : 'var(--c-fill-color-off)'};
              }
              text {
                font-size: var(--c-font-size);
                font-weight: var(--c-font-weight);
                letter-spacing: var(--c-letter-spacing);
                fill: var(--c-font-color);
              }
              tspan {
                font-size: var(--c-unit-font-size);
              }
              #circle_value, tspan {
                text-anchor: middle;
                dominant-baseline: central;
              }
            </style>
            <circle id="circle_stroke" cx="25" cy="25" r="${r}"/>
            <text id="circle_value" x="50%" y="52%">${input}${tspan}${unit}</tspan></text>
          </svg>

          ${domain === 'light' && `
              <input id="circle_slider" type="range" min="0" max="100" value="${input}">
          `}
        `;
      ]]]
    graph:
      card:
        type: "custom:mini-graph-card"
        height: 200
        entities:
          - entity: "[[[ return variables.graph_entity ]]]"
        hours_to_show: 48
        points_per_hour: 1
        line_width: 8
        font_size: 75
        decimals: 0
        show:
          name: false
          icon: false
          state: false
          legend: false
          labels: false
          labels_secondary: false
          points: false
        color_thresholds:
          - value: 40
            color: "#276696"
          - value: 50
            color: "#228C22"
          - value: 55
            color: "#d35400"
          - value: 60
            color: "#c0392b"          
  styles:
    card:
      - border-width: 0  
    custom_fields:
      card:
        - border-width: 0
      graph: [bottom: 0%, left: 0%, width: 125%, position: absolute, margin: 0% 0% 0% 0% ] #-13% -14%]
  card_mod:
    style: |
      :host{
        --accent-color: #039be5;
        --ha-card-border-width: 0px;
      }

use like this now

              - type: custom:button-card
                entity: sensor.woonkamer_humidity
                name: Vochtigheid
                template:
                  - graph
                variables:
                  circle_input: >
                    [[[ return states['sensor.woonkamer_temperature'].state; ]]] 
                  circle_input_unit: "°C"
                  graph_entity: sensor.woonkamer_humidity
1 Like

Hi Mason,
Thank you for the homerun. Found the problem in a file called: tv_media.yaml
Used your previous posted conditional_media code and states are now correct and updating.
Will work on the Plex thumbnails or static image now when no players are active.
Many thanks.

1 Like

sweet that was the issue that then, it’s hard to know what words to use sometimes but im happy we got there in the end.

the code I provided is custom to my situation, I would recommend you modify the code from @Mattias_Persson to fit your situation, that way you can modify it when needed.

you can use the template section of the dev tools to debug the template until you get it just right

1 Like

Thank you. I didn’t know that it was basically just using an SVG and CSS animations to do this. I have been out of touch with web design for quite a while.

I have been working on the garage door icon and can not seem to get it implemented properly. I have created a gist of my current coding and what is happening with what I think is relevant information at the top of the gist. If anyone would be willing to help diagnose what is going on, please leave comments in the gist so that it is not cluttering this thread. Any help is appreciated.
Garage Door SVG Animation (Not working) · GitHub

Side thought: Has anyone made a database of custom icons that are being used?

#________________xbox_animado
  icon_xbox_animado:
    template:
      - base
      - loader
    styles:
      custom_fields:
        icon:
          #- clip-path: circle()
          - width: 79%
          - pointer-events: none
          - display: grid
          - margin-left: -10%
          - fill: >
              [[[
                return (variables.state === 'on' || variables.state === 'playing') ? '#107b10' : '#9da0a2';
              ]]]            
    custom_fields:
      icon: >
        [[[
          let state;
          if (variables.state === 'on' && variables.timeout < 2000) {
            state = 'on';
          } 
          if (variables.state === 'off' && variables.timeout < 2000) {
            state = 'off';
          }
          if (variables.state === 'on' && variables.timeout > 2000) {
            state = 'on_timeout';
          }
          return `
            <svg viewBox="0 0 1331.67 1333.33">
              <style>
                @keyframes on {
                  0% {
                    transform: rotate(0deg) translate(0%, 0%);
                  }
                  100% {
                    transform: rotate(-360deg) translate(-1.5%, 0%);
                  }
                }
                @keyframes off {
                  0% {
                    transform: rotateY(-360deg) translate(-1.5%, 0%);
                  }
                  45% {
                    transform: rotateY(-40deg);
                  }
                  55% {
                    transform: rotateY(0deg);
                  }
                  65% {
                    transform: rotateY(-15deg);
                  }
                  75% {
                    transform: rotateY(0deg);
                  }
                  85% {
                    transform: rotateY(-5deg);
                  }
                  95% {
                    transform: rotateY(0deg);
                  }
                }
                .on {
                  animation: on 1.1s;
                  animation-fill-mode: forwards;
                  transform-origin: 50% 50%;
                  transition-timing-function: cubic-bezier(0.85, 0, 0.15, 1);
                }
                .off {
                  animation: off 1.1s linear;
                  animation-delay: 0.05s;
                  animation-fill-mode: both;
                  transform-origin: 45% 41%;
                }
              </style>
              <path class="${state}" d="M665.83 534.66s1.66 0 0 0c200.91 152.76 541.3 528.02 438.35 634.29-117.89 102.95-270.65 164.39-438.35 164.39-167.7 0-322.13-61.44-438.35-164.39-104.61-106.27 237.44-481.53 436.69-632.63 0-1.66 1.66-1.66 1.66-1.66zm347.03-436.7C911.57 36.52 800.32-.01 665.83-.01c-134.5 0-245.74 36.53-347.03 97.97-1.66 0-1.66 1.66-1.66 3.32s1.66 1.66 3.32 1.66c129.51-28.23 325.44 83.02 343.71 94.65h3.32c18.26-11.62 214.2-122.87 343.71-94.65 1.66 0 3.32 0 3.32-1.66s0-3.32-1.66-3.32zm-813.61 92.98c-1.66 0-1.66 1.66-3.32 1.66C74.72 313.81 0 481.52 0 665.82c0 151.1 51.48 292.24 136.16 403.49 0 1.66 1.66 1.66 3.32 1.66s1.66-1.66 0-3.32C88 909.91 348.69 529.67 483.19 370.26l1.66-1.66c0-1.66 0-1.66-1.66-1.66-204.23-202.57-272.31-180.99-283.93-176.01zm649.23 174.35l-1.66 1.66s0 1.66 1.66 1.66C982.98 528.01 1242 908.26 1192.19 1066v3.32c1.66 0 3.32 0 3.32-1.66 84.68-111.25 136.16-252.39 136.16-403.49 0-184.31-74.72-352.01-197.59-473.22-1.66-1.66-1.66-1.66-3.32-1.66-9.96-3.32-78.04-24.91-282.27 176.01z"/>
            </svg>
          `;
        ]]]

It did not, will do this tomorrow.

Many thanks for getting back to me! Appreciated!!

this is the result… how to fix the graph?

Bildschirm­foto 2022-11-08 um 07.25.07

As I said in my post that issue was there before I made any modification to the code I was provided. @DevilsAdjutant might know more.

Hello dear @Mattias_Persson config enthusiasts!

Help me please with the space between cards!
I tried to modify the grip-card in many ways, with card-mod, directly in the code but no succes!
This is the code op the pop-up:

action: fire-dom-event
browser_mod:
  service: browser_mod.popup
  data:
    title: Veranda
    card_mod:
      style:
        .: |
          :host .content {
            padding: 0.1em 1.5em 1.5em 1.5em !important;
          }
          :host .main-title {
            pointer-events: none;
          }
        $: |
          .mdc-dialog__surface {
            background: transparent !important;
            border-style: none !important;
            border: 0px !important;
            box-shadow: none;
          }

    content:
      type: custom:layout-card
      layout_type: custom:grid-layout
      layout:
        grid-gap: 2px;
        grid-template-rows: 3fr
        grid-template-areas: |
          "veranda"
          "veranda2"
          "veranda3"
        mediaquery:
          #phone
          "(max-width: 800px)":
            grid-gap: 2px;
            grid-template-columns: 1fr
            grid-template-rows: 3fr
            grid-template-areas: |
              "veranda"
              "veranda2"
              "veranda3"
          #tablet
          "(max-width: 2000px)":
            grid-gap: 2px;
            grid-template-columns: 2fr #20vw
            grid-template-rows: 1fr
            grid-template-areas: |
              "veranda"
              "veranda2"
              "veranda3"
      cards:
        #################################################
        #                                               #
        #                   veranda                     #
        #                                               #
        #################################################

        - type: grid
          title: Lumini
          view_layout:
            grid-area: veranda
          columns: 4
          cards:
            - type: custom:button-card
              entity: light.shelly_shdm_1_d44ff5
              name: Candelabru
              template:
                - light
                - icon_candelabru

            - type: custom:button-card
              entity: light.shelly_shdm_1_d44ff5
              name: Candelabru
              template:
                - light
                - icon_candelabru
            - type: custom:button-card
              entity: light.led_baie
              name: L E D
              template:
                - light
                - icon_bandaled

            - type: custom:button-card
              entity: light.led_dormitor
              name: L E D
              template:
                - light
                - icon_bandaled

        - type: grid
          title: Control
          view_layout:
            grid-area: veranda2
          columns: 4
          cards:
            - type: custom:button-card
              entity: light.shelly_shdm_1_d44ff5
              name: Devote L
              template:
                - light
                - icon_hue

        - type: grid
          title: Control
          view_layout:
            grid-area: veranda3
          columns: 4
          cards:
            - type: custom:button-card
              entity: light.shelly_shdm_1_d44ff5
              name: Devote L
              template:
                - light
                - icon_hue

hi @odiv

do you have an example of what you would like to do?

I can see a few issues with the code you provided, that I will try and outline.

But 1st I recommend that you give this a read CSS Grid Layout it should help.

the gap that you outlined in the image is the column gab, but your grid-template only has the 1 column so there is no gap between them, see the section on Grid Gaps in the provided reading.

you are then trying to edit the gap on the layout-card where the items that you would like to move are in a single grid card, you will need to modify your template to have mutable columns and rows and place each card in its own sell, see CSS grid-template property.

hopeful that helps if not then try creating what you would like in paint and some one might be of more help

Hello Mason and thank you for your reply!
indeed, the code I dont think that is the best because I copyed @Laffer code and I tried to adapt for myself.
What I want to achieve is to have 3 columns with cards and in each column to have multiple rows with 4 cards by row.

this is the template you currently have.

I think this will give you the most flexibility. keep in mind that you could do this layout with vertical and horizontal stack cards and get the same outcome.

the template for this would look something like

grid-template-columns: 0.7fr repeat(4, 1fr) 0.7fr
grid-template-rows: 1fr 3fr 1fr 3fr 1fr 3fr
grid-template-areas: |
  "tital1 tital1 tital1 tital1 tital1 tital1"
  ". 1a 1b 1c 1d ."
  "tital2 tital2 tital2 tital2 tital2 tital2"
  ". 2a 2b 2c 2d ."
  "tital3 tital3 tital3 tital3 tital3 tital3"
  ". 3a 3b 3c 3d ."

after reading the information I provided this should give you a good starting point but you might need to work on the sizes to get it looking the way you would like

for the title you can use lovelace-mushroom/title.md at bb415306c867de3270490a24750d36f0604ccda6 · piitaya/lovelace-mushroom · GitHub

1 Like

Ooo @masoncrawford1994 you are such a good person and I appreciate your complete answer!
You are right, the horizontal-stack is the best solution to achieve what I want.

The only thing is that the button doesn`t resize whell in different resolutions.

Try changing

custom_fields:
      card:
        - border-width: 0
      graph: [bottom: 0%, left: 0%, width: 125%, position: absolute, margin: 0% 0% 0% 0% ] #-13% -14%]

to

custom_fields:
      card:
        - border-width: 0
      graph: [bottom: 0%, left: 0%, width: 125%, position: absolute, margin: 0% 0% -13% -14%]

This might solve it…

Thanks this worked.

I chose to use your first option. But it works just great.