Home Assistant card (replacing former bar-card config)

Hi @Mariusthvdb Nice template for button card… :clap:

I recently created something similar for my custom card. so let me improve your template. I modified the function so that the background gradient width is in the range of the maximum entity current value, instead of the entire 100% card width. I created two versions, one with a color gradient and the other with color blocks. Maybe someone prefers this style more.

2025-07-01 23.35.21

base card template:

ts_bar_card:
  show_state: true
  styles:
    grid:
      - grid-template-areas: '"i n s"'
      - grid-template-columns: 50px 1fr
    name:
      - width: 100%
      - color: white
      - font-weight: 400
      - font-size: 16px
      - text-align: left
      - z-index: 2
    state:
      - z-index: 2
    icon:
      - z-index: 2
    card:
      - height: 26px
      - padding: 4px 8px
      - font-size: 1em
      - border-radius: 8px
      - position: relative
      - background: var(--secondary-background-color)

gradient

  - type: custom:button-card
    entity: input_number.test_max_value
    name: Color Gradient
    template:
      - ts_bar_card
      - color_gradient_bar
color_gradient_bar:
  styles:
    custom_fields:
      bar:
        - position: absolute
        - top: 0
        - left: 0
        - bottom: 0
        - width: 100%
        - height: 100%
        - border-radius: 8px
        - z-index: 1
        - transition: width 0.5s ease-out
        - background: >
            [[[
              let currentLevel = parseFloat(entity.state),
                  maxValue = variables.max_value || 100;
              function generateGradient() {
                const colorThresholds = [
                  { "value": 0, "color": "#00ff4c"},
                  { "value": 20, "color": "#d49adf" },
                  { "value": 40, "color": "#00d5ff"},
                  { "value": 60, "color": "#850000"},
                  {"value": 80,"color": "#342678"},
                  {"value": 90,"color": "#7968cf"}
                ]
                const sorted = colorThresholds.sort((a, b) => a.value - b.value);
                const _level = Math.min(currentLevel, maxValue);

                let stops = [];
                let lastColor = sorted[0].color;

                for (const { value, color } of sorted) {
                  if (value > _level) break;
                  const percentage = (value / _level) * 100;
                  stops.push(`${color} ${percentage}%`);
                  lastColor = color;
                }

                const normalizedLevel = 100;
                const lastStop = stops[stops.length - 1];
                if (!lastStop?.endsWith(`${normalizedLevel}%`)) {
                  stops.push(`${lastColor} ${normalizedLevel}%`);
                }

                return `linear-gradient(90deg, ${stops.join(', ')})`;
              }
              return generateGradient();
            ]]]
  custom_fields:
    bar: >
      [[[
        let currentLevel = parseFloat(entity.state);
        setTimeout(() => {
          let elt = this.shadowRoot,
              card = elt.getElementById('card'),
              container = elt.getElementById('container'),
              bar = elt.getElementById('bar');
          if (elt && card && container && bar) {
            card.insertBefore(bar, container);
            bar.style.width = currentLevel + '%';
          }
        }, 0);
        return ' ';
      ]]]

color blocks

  - type: custom:button-card
    entity: input_number.test_max_value
    name: Color Block
    template:
      - ts_bar_card
      - color_block_bar
color_block_bar:
  styles:
    custom_fields:
      bar:
        - position: absolute
        - top: 0
        - left: 0
        - bottom: 0
        - width: 100%
        - height: 100%
        - border-radius: 8px
        - z-index: 1
        - transition: width 0.5s ease-out
        - background: >
            [[[
              let currentLevel = parseFloat(entity.state),
                  maxValue = variables.max_value || 100;
              function generateColorBlocks() {
                const colorThresholds = [
                  { "value": 0, "color": "#00ff4c"},
                  { "value": 20, "color": "#d49adf" },
                  { "value": 40, "color": "#00d5ff"},
                  { "value": 60, "color": "#850000"},
                  {"value": 80,"color": "#342678"},
                  {"value": 90,"color": "#7968cf"}
                ]
                const sorted = colorThresholds.sort((a, b) => a.value - b.value);
                const cappedLevel = Math.min(currentLevel, maxValue);

                let stops = [];

                for (let i = 0; i < sorted.length - 1; i++) {
                  const current = sorted[i];
                  const next = sorted[i + 1];

                  if (current.value > cappedLevel) break;

                  const fromValue = (current.value / cappedLevel) * 100;
                  const toValue = (Math.min(next.value, cappedLevel) / cappedLevel) * 100;

                  stops.push(`${current.color} ${fromValue}%`, `${current.color} ${toValue}%`);

                  if (next.value >= cappedLevel) break;
                }

                let lastThreshold;

                for (let i = sorted.length - 1; i >= 0; i--) {
                  if (sorted[i].value <= cappedLevel) {
                    lastThreshold = sorted[i];
                    break;
                  }
                }
                if (lastThreshold && lastThreshold.value < cappedLevel) {
                  const start = (lastThreshold.value / cappedLevel) * 100;
                  stops.push(`${lastThreshold.color} ${start}%`, `${lastThreshold.color} 100%`);
                }

                return `linear-gradient(90deg, ${stops.join(', ')})`;

              }
              return generateColorBlocks();
            ]]]
  custom_fields:
    bar: >
      [[[
        let currentLevel = parseFloat(entity.state);
        setTimeout(() => {
          let elt = this.shadowRoot,
              card = elt.getElementById('card'),
              container = elt.getElementById('container'),
              bar = elt.getElementById('bar');
          if (elt && card && container && bar) {
            card.insertBefore(bar, container);
            bar.style.width = currentLevel + '%';
          }
        }, 0);
        return ' ';
      ]]]

bars in entities card
2025-07-01 23.44.05

bars in entities card
  - type: entities
    entities:
      - entity: input_number.test_max_value
      - type: custom:button-card
        entity: input_number.test_max_value
        name: Color Gradient
        template:
          - ts_bar_card
          - color_gradient_bar
      - type: custom:button-card
        entity: input_number.test_max_value
        name: Color Block
        template:
          - ts_bar_card
          - color_block_bar
    state_color: true
1 Like