Can I use <div> to show a background image in a Markdown card?

Hello!

Can I use < div > or something else to show a background image in a Markdown card?

I have this dynamically built card, but I want icons to span the part that shows a game (understanding that the resolution of the available icon might be too small):

grafik

This is my code:

type: markdown
title: Steam Games
content: |
  {% if state_attr('sensor.steam_inventory', 'games') %}
    {% for game in state_attr('sensor.steam_inventory', 'games') %}
    ### ![Icon für {{ game.name }}](https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{{ game.appid }}/{{ game.img_icon_url }}.jpg) {{ game.name }}  
    **Play time:** {% set total_minutes = game.playtime_windows_forever %} {% set months = total_minutes // 43200 %} {% set days = (total_minutes % 43200) // 1440 %} {% set hours = ((total_minutes % 43200) % 1440) // 60 %} {% set minutes = (total_minutes % 43200) % 60 %} {% if total_minutes > 0 %} {% if months > 0 %}{{ months }} {{ 'month' if months == 1 else 'months' }}, {% endif %}{{ days }} {{ 'day' if days == 1 else 'days' }}, {{ hours }} hours, {{ minutes }} minutes{% else %}never played{% endif %}
    {% if not loop.last %}
    ---
    {% endif %}
    {% endfor %}
  {% else %}
    No data found. Check sesnor.
  {% endif %}

Sorry that I did not manage to properly format it. I use it as pasted here. As soon as I start using > or | the output of the value comes under the “Play time” in a new row - for all games - which I do not like. I hope you can understand my code nevertheless and help me to understand how/where to change it, so the source of the icon rather serves as the source for a background image.

Thanks for your help! :+1:

PS for users interested in how to use the required REST api sensor - here it is:

  - platform: rest
    name: "Steam Inventory"
    unique_id: "steam_inventory"
    resource: !secret steam_api_url
    scan_interval: 600
    value_template: "OK"
    json_attributes_path: "$.response"
    json_attributes:
      - games
    headers:
      User-Agent: HomeAssistant
    timeout: 10

The secret steam_api_url is stored in my secrets.yaml and looks as follows (my Steam ID redacted, of course):

steam_inventory_url: "https://steamcommunity.com/inventory/12345678901234567/753/6?l=english&count=5000"

BTW, if somebody knows, if and how the above sensor code could take the url not being secret but only the Steam ID from secrets.yaml inserted, please drop me a line, too. :blush: I did not manage it and therefore placed the whole url into my secrets.yaml file.

Can you just use card_mod?

type: markdown
title: Steam Games
content: |
  {% if state_attr('sensor.steam_inventory', 'games') %}
    {% for game in state_attr('sensor.steam_inventory', 'games') %}
    ### ![Icon für {{ game.name }}](https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{{ game.appid }}/{{ game.img_icon_url }}.jpg) {{ game.name }}
    **Play time:** {% set total_minutes = game.playtime_windows_forever %} {% set months = total_minutes // 43200 %} {% set days = (total_minutes % 43200) // 1440 %} {% set hours = ((total_minutes % 43200) % 1440) // 60 %} {% set minutes = (total_minutes % 43200) % 60 %} {% if total_minutes > 0 %} {% if months > 0 %}{{ months }} {{ 'month' if months == 1 else 'months' }}, {% endif %}{{ days }} {{ 'day' if days == 1 else 'days' }}, {{ hours }} hours, {{ minutes }} minutes{% else %}never played{% endif %}
    {% if not loop.last %}
    ---
    {% endif %}
    {% endfor %}
  {% else %}
    No data found. Check sensor.
  {% endif %}
card_mod:
  style: |
    ha-card {
      background-image: url(https://icons.iconarchive.com/icons/titch-ix/game/256/Fallout-3-icon.png);
      background-size: 8em;  /* Or contain, or other CSS properties */
      background-position: right top;
      background-repeat: no-repeat;
      /* Optional:  Add padding if the text is too close to the edge */
      padding-left: 25%;
      /* Optional: Improve text readability with a background overlay */
      /* background-color: rgba(0, 0, 0, 0.5);  Semi-transparent black */
      color: yellow;  /* Change text color if needed */
    }

Screenshot 2025-02-04 205608

type: markdown
title: Steam Games
content: |
  {% if state_attr('sensor.steam_inventory', 'games') %}
    {% for game in state_attr('sensor.steam_inventory', 'games') %}
    ### ![Icon für {{ game.name }}](https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{{ game.appid }}/{{ game.img_icon_url }}.jpg) {{ game.name }}
    **Play time:** {% set total_minutes = game.playtime_windows_forever %} {% set months = total_minutes // 43200 %} {% set days = (total_minutes % 43200) // 1440 %} {% set hours = ((total_minutes % 43200) % 1440) // 60 %} {% set minutes = (total_minutes % 43200) % 60 %} {% if total_minutes > 0 %} {% if months > 0 %}{{ months }} {{ 'month' if months == 1 else 'months' }}, {% endif %}{{ days }} {{ 'day' if days == 1 else 'days' }}, {{ hours }} hours, {{ minutes }} minutes{% else %}never played{% endif %}
    {% if not loop.last %}
    ---
    {% endif %}
    {% endfor %}
  {% else %}
    No data found. Check sensor.
  {% endif %}
card_mod:
  style: |
    ha-card {
      background-image: url("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcShD-XhQQ_Zd7hsFG3_X3Ycev8N8EP-g2XplQ&s");
      background-size: contain;  /* Or contain, or other CSS properties */
      background-position: center; 
      background-repeat: no-repeat;
      /* Optional:  Add padding if the text is too close to the edge */
      padding-left: 5em;
      padding-top: 55%;
      /* Optional: Improve text readability with a background overlay */
      /* background-color: rgba(0, 0, 0, 0.5);  Semi-transparent black */
      color: white;  /* Change text color if needed */
    }

Screenshot 2025-02-04 210505

1 Like

@ColtonYYZ
Thank you very much, and please accept my apologies for my late reply.

I tested lots of things, but the problem is that the code cycles through the attribute (which can get quite large, depending on the dynamically increasing number of games). As far as I understand it, the card_mod part can only be applied once per card. My card, however, shows one game per “box” (separated by ---). Consequently, I can only show the same background for the whole card but not for an individual game.

If it is possible to have card_mod code in the middle of the content block, it might help, but I have not found a proper syntax that works (likely, as it is not supposed to work like this).

My second problem is that I found I cannot put the URL from this line:

### ![icon for {{ game.name }}](https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{{ game.appid }}/{{ game.img_icon_url }}.jpg) {{ game.name }}

… into the card_mod code like this:

card_mod:
  style: |
    ha-card {
      background-image: url(https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{{ game.appid }}/{{ game.img_icon_url }}.jpg);
      background-size: 8em;
      background-position: right;
      background-repeat: no-repeat
    }

I.e., when I replace the static URL from your example:

(https://icons.iconarchive.com/icons/titch-ix/game/256/Fallout-3-icon.png)

… by this URL that I use to dynamically fetch the game icon:

(https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{{ game.appid }}/{{ game.img_icon_url }}.jpg)

… nothing is displayed as background.

If you or anybody else has some further thoughts about my 2 problems, I am eager to hear back from you. Thank you so much! :+1:

Hi! Because I don’t play steam games I can’t visualize what it is that you’re trying to do with the icons. Are you able to create a mock-up sample using paint or some other photo editing software and post it here so that I can visually understand what you want it to show? Thank you!

1 Like

Hi! Here is what it looks like now (in German, sorry). It is one markdown card, currently showing only 2 entries, but there can be more:

One background image per game would be great. If the icons from the source are too small, I would be happy to make them a bit larger, if not possible as background.

Here is the current code:

type: grid
cards:
  - type: heading
    heading: 🔄 Meine zuletzt gespielten Steam-Spiele
    heading_style: title
    icon: ""
    grid_options:
      columns: full
  - type: markdown
    content: |
      {% if state_attr('sensor.steam_inventory', 'games') %}
        {% set sorted_games = state_attr('sensor.steam_inventory', 'games') | sort(attribute='rtime_last_played', reverse=true) %}
        {% for game in sorted_games %}
        {% if game.playtime_windows_forever > 0 %}
        ### ![Icon für {{ game.name }}](https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/{{ game.appid }}/{{ game.img_icon_url }}.jpg) {{ game.name }}
        **🕒 Spielzeit (Windows):** {% set total_minutes = game.playtime_windows_forever %}{% set months = total_minutes // 43200 %}{% set days = (total_minutes % 43200) // 1440 %}   {% set hours = ((total_minutes % 43200) % 1440) // 60 %}{% set minutes = (total_minutes % 43200) % 60 %}{% if months > 0 %}{{ months }} {{ 'Monat' if months == 1 else 'Monate' }}, {% endif %}{{ days }} {{ 'Tag' if days == 1 else 'Tage' }}, {{ hours }} Stunden, {{ minutes }} Minuten
        **🔄 Letztes Mal gespielt:** {% if game.rtime_last_played > 0 %}{{ game.rtime_last_played | timestamp_custom('%d.%m.%Y %H:%M') }}{% else %}Noch nie gespielt{% endif %}
        **📊 Hat Community Statistiken:** {{ 'Ja' if game.get('has_community_visible_stats', None) else 'Nicht verfügbar' }}
        {% if game.get('has_community_visible_stats') %}**📈 Statistiken:** {% if game.get('statistics') and game.statistics %}{% for stat_name, stat_value in game.statistics.items() %} - **{{ stat_name }}:** {{ stat_value }}{% endfor %}{% else %}nicht verfügbar{% endif %}
        {% endif %}
        {% if not loop.last %}
        ---
        {% endif %}
        {% endif %}
        {% endfor %}
      {% else %}
        Keine Daten gefunden. Bitte Sensor-Konfiguration prüfen.
      {% endif %}
    grid_options:
      columns: full
column_span: 1

I wish, I knew how to write the code reader-friendly (especially all those if clauses), i.e. with line breaks and indetations, but then the displayed information is also broken up.