šŸ”¹ Layout-card - Take control of where your cards end up

Hopefully someone can help me make sense of this. I have a layout with header, (potential) subheader, main, and some footer cards. While header and footer will adapt to screensize/width, my main area for some reason seems to want to align only with the box shown in the screenshot. Not sure what I am missing here, can anyone point me in the right direction with this code:

title: home
path: home
icon: mdi:home
theme: ios-dark-mode-blue-red
background: "var(--background-image)"
type: custom:grid-layout
layout:
  margin: -0.5vh 1vh 0vh
  card_margin: 0px 0px 0px 0px
  grid-template-columns: auto
  grid-template-rows: 17vh 2vh 61vh 2vh 9vh 9vh
  grid-template-areas: |
    "header"
    "subheader"
    "main"
    "footer_title"
    "footer"
    "menu"
cards:
  - type: custom:button-card # HEADER
    view_layout:
      grid-area: header
    template: header
    variables:
      view: home
  - type: custom:layout-card # MAIN
    view_layout:
      grid-area: main
    layout_type: custom:vertical-layout
    layout:
      height: 61vh
      margin: 0vh 0vh 0vh 0vh
      padding: 0vh 0.4vh
    cards:
#################MAIN AREA######################################
      - type: vertical-stack
        cards:
        - type: custom:button-card
          template: room_card
          variables:
            room_card_name: Schlafzimmer
            room_card_icon: mdi:bed-king-outline
            room_card_temp: sensor.bedroom_echo_temperature
            entity_1: light.bedroom
            entity_1_icon: mdi:bed-outline
            entity_2: light.desklamp
            entity_2_icon: mdi:desk-lamp 
            entity_3: light.bathroom
            entity_3_icon: mdi:shower-head 
            media_player: media_player.40_tcl_roku_tv
            climate: climate.living_room
            popup_id: '#remote_bedroom'
            climate_popup: '#climate_bedroom'

Hi, maybe a new version available too soon. HA Core 2024.3, is not yet available.

The beta is actually available :wink:

I am having issues with the card_margin option inside a grid layout. It is not having an effect and if I am placing a grid inside a grid, the margins add up.

Tried card_margin: 0px 0px 0px 0px, card_margin: 0px 0px 0px 0px !important, card_margin: 0ā€¦

check this:

and this:

Im having some struggle aligning my cards for my tablet that is 1920*1200px.


How do I move the card up into the gap?

Are my card settings ok or should I change something? Im very new to this cardā€¦
im using layout card with these settings:

margin: 0px
padding: 0px
grid-template-columns: 300px 245px 245px 245px 190px
grid-template-rows: auto
grid-template-areas: |
ā€œrow1-1 row1-2 row1-3 row1-4 row1-5ā€
ā€œrow2-1 row2-2 row2-3 row2-4 row2-5ā€
ā€œrow3-1 row3-2 row3-3 row3-4 row3-5ā€
ā€œrow4-1 row4-2 row4-3 row4-4 row4-5ā€
ā€œrow5-1 row5-2 row5-3 row5-4 row5-5ā€

Hey there,

is it possible to set the zoom of a card content
like with (this works, but its for every screensize):

card_mod:
  style: |
    ha-card {
      zoom: 120%;
    }

but depending on the mediaquery?
At the moment i have:

type: custom:grid-layout
    layout:
      max_cols: 3
      height: calc(100vh)
      mediaquery:
        '(max-width: 500px)':
          grid-template-columns: 100%
          grid-template-rows: auto
        '(max-width: 1200px)':
          grid-template-columns: 50% 50%
          grid-template-rows: 33.3% 33.3% 33.3%
        '(max-width: 2200px)':
          grid-template-columns: 33.3% 33.3% 33.3%
          grid-template-rows: 45% 45%

But some card-contents are too small (fonts, iconsā€¦) when showing the dashboard on a big screen (the third option above).

regards
Stephan

You should use ā€œstretchā€ instead of ā€œzoomā€

Stretch, can be used with either ( justify-self: / justify-items: )
Stretch can also be used with (aling-items / align-self:)

And Yes this will also be in All screensize ( but it should fill 100% , of i.e a cell ) , and not 120% of a predefined card-width

A Complete Guide to CSS Grid | CSS-Tricks - CSS-Tricks.
CSS reference - CSS: Cascading Style Sheets | MDN. (choose properties)

And this ( Move/resize by ā€œdragging the vertical delimiterā€ ( code | result )

W3Schools Tryit Editor.

Hello @boheme61 ,

thanks for the help. But I didnā€™t found any information how to use ā€œstretchā€ in ha-cardā€¦(Iā€™m not so good in CSS)

Can you give me a short example how to use it in my case?

regards

Stephan

By using Card-mod !

šŸ”¹ Card-mod - Add css styles to any lovelace card.

And the Search Box in this Forum can also be used to search in the whole Forum, or in a Specific Topic, like i.e above

Search results for 'justify-content; stretch' - Home Assistant Community.

Beside, Various cards have various options, as as all custom:-cards are build by individuals, they are build different, and behave different. ( Some devā€™s of custom cards specify width in (px), in the card.js, some with ā€œmaxā€ etc. etc. )

If you have a use.case ! , with a specific card, i suggest you ask/search either in a Topic for that card, or in some of the big card-mod Topics

But as you mention specifics, within a card (fonts, icons etc) , you will have to read and test alot, upon your big-tv screen, Fonts / Pics are often specified in px.

But to be honest, i have no ā€œissuesā€ with the scaling on various devices
from Mobile(Max 900px), to laptop (1366x768 ), to TV (1920x1080 )

And you havenā€™t ā€œshovedā€ anything, or mentioned how your Browser is connected to your big-tv ( You do know you can specify i.e resolution , and in some case i.e text-size.( on the device/connection)
But again if you build ā€œadaptiveā€ there should not be any problems, as i have experienced

I got this pretty weird issue that when I use the layout card in horizontal mode (nested in a gridded button card, the button stack vertically.

See as follows

My corresponding code for the custom field is:

          time:
            card:
              type: custom:layout-card
              layout_type: horizontal
              layout:
                card_margin: 0
                margin: 0
                padding: 0
                max_width: 168px
              cards:
              - type: custom:button-card
                icon: ios:arrow-down
                triggers_update: input_number.climate_duration
                tap_action:
                  action: call-service
                  service: input_number.decrement
                  service_data:
                    entity_id: input_number.climate_duration
                styles:
                  card:
                  - height: 42px
                  - width: 42px
              - type: custom:button-card
                icon: ios:arrow-down
                triggers_update: input_number.climate_duration
                tap_action:
                  action: call-service
                  service: input_number.decrement
                  service_data:
                    entity_id: input_number.climate_duration
                styles:
                  card:
                  - height: 42px
                  - width: 42px

With the styles:

      - type: custom:button-card
        tap_action:
          action: toggle
        styles:
          grid:
            - grid-template-rows: 1fr 1fr 1fr 1fr
            - grid-template-columns: 1fr min-content min-content min-content
            - grid-template-areas: "'i t1 m s' 'l t2 m s' 'n t3 m s' 'time t4 m s'"
          card:
            - background-color: rgba(var(--ios-systemgray3),0.7);
            - border-radius: var(--border-radius);
            - padding: 10px;
          custom_fields:
            m:
              - justify-self: end
              - align-content: start
            s:
              - justify-self: end
              - padding-left: 12px
            t1:
              - justify-self: end
              - padding-right: 12px
              - font-size: "12px"
            t2:
              - justify-self: end
              - padding-right: 12px
              - font-size: "12px"
            t3:
              - justify-self: end
              - padding-right: 12px
              - font-size: "12px"
            t4:
              - justify-self: end
              - padding-right: 12px
              - font-size: "12px"
            time:
              - font-size: "12px"
              - justify-self: start

Any chance someone can point out what Iā€™m doing wrong here? I mean, even if some style is messed up the last thing I would expect using horizontal mode is anything stacking vertically.

Try grid layout and define the columns

     - type: custom:layout-card
       layout_type: custom:grid-layout
       layout:
          grid-template-columns: 1fr 1fr
       cards:
          - type:

I have been trying for a while to make my 3 columns custom sizes.
Iā€™ve tried with the dashboard layout set to Panel, masonry(layout-card) and grid(layout-card).

Iā€™ve tried with the card in the dashboard being custom:masonry-layout and custom:grid-layout

Iā€™ve tried setting the grid-template-columns to pixels, percents and fr. Whatever I do all 3 columns continue to be the exact same size as each other. I donā€™t understand what Iā€™m doing wrong.

Here is the code I have currently, hoping someone can help me.:

type: custom:layout-card
layout_type: custom:grid-layout
layout:
  width: 1250
  max_cols: 3
layout_options:
  grid-template-columns: 350px 450px 450px
  grid-template-rows: auto
  grid-template-areas: |
    "left middle right"
cards:
  - type: vertical-stack
    cards:
      - square: false
        type: grid
        cards:
          - type: vertical-stack
            view_layout:
              grid-area: left
            cards:
              - type: entity
                entity: sensor.sun_next_dawn
                name: Next Dawn
              - type: entity
                entity: sensor.sun_next_dusk
                name: Next Dusk
          - type: vertical-stack
            view_layout:
              grid-area: middle
            cards:
              - show_state: true
                show_name: true
                camera_view: live
                type: picture-entity
                entity: camera.front_porch_camera
                image: >-
                  http://192.168.0.0/ISAPI/Streaming/channels/101/picture?snapShotImageType=JPEG
                name: Front Porch Camera
                camera_image: camera.front_porch_camera
              - show_state: true
                show_name: true
                camera_view: live
                type: picture-entity
                entity: camera.north_yard_camera
                image: >-
                  http://192.168.0.0/ISAPI/Streaming/channels/201/picture?snapShotImageType=JPEG
                name: North Yard Camera
                camera_image: camera.north_yard_camera
          - type: vertical-stack
            view_layout:
              grid-area: right
            cards:
              - show_state: true
                show_name: true
                camera_view: live
                type: picture-entity
                entity: camera.back_yard_camera
                image: >-
                  http://192.168.0.0/ISAPI/Streaming/channels/401/picture?snapShotImageType=JPEG
                name: Back Yard Camera
                camera_image: camera.back_yard_camera
              - show_state: true
                show_name: true
                camera_view: live
                type: picture-entity
                entity: camera.south_yard_camera
                image: >-
                  http://192.168.0.0/ISAPI/Streaming/channels/301/picture?snapShotImageType=JPEG
                name: South Yard Camera
                camera_image: camera.south_yard_camera
        columns: 3

EDIT: I also tried this layout without the initial vertical stack and without the initial grid card. Nothing I do changes it from 3 equal columns

EDIT: also tried no vertical stack or grid, just the grid layout-card with 3 entity cards in it, marked with the proper grid areas. Still either had 3 equal columns or just 1 column. I donā€™t get it.

For the life of me I canā€™t seem to change the color of the background on the custom layout card that contains the other cards within it. Feels like Iā€™m missing something very simple but Iā€™ve spent hours with no luck. Anyone have any idea what Iā€™m doing wrong? Excuse the poor mark-up, Iā€™m working off a laptop.

  - title: test
    type: custom:horizontal-layout
    cards:
      - type: custom:layout-card
        layout_type: custom:masonry-layout
        layout:
          width: 150
          max_cols: 2
        cards:
          - type: custom:stack-in-card
            cards:
              - type: custom:mushroom-template-card
                primary: Main Gym Door
                secondary: |-
                  {% if is_state('binary_sensor.main_gym_door','on') %}
                    Door Open
                  {% elif is_state('lock.main_gym','unlocked') %}
                    Unlocked
                  {% else %}
                    Locked
                  {% endif%}
                icon: |-
                  {% if is_state('binary_sensor.main_gym_door','on') %}
                    mdi:door-open
                  {% elif is_state('lock.main_gym','unlocked') %}
                    mdi:lock-open
                  {% else %}
                    mdi:lock
                  {% endif%}
                icon_color: >-
                  {% if is_state('lock.main_gym','locked') and
                  is_state('binary_sensor.main_gym_door','off') %}
                    red
                  {% elif is_state('binary_sensor.main_gym_door','on') %}
                    yellow
                  {% else %}
                    green
                  {% endif%}
                badge_icon: >-
                  {% set battery_level = (states('sensor.main_gym_battery') |
                  int / 10) | round(0) | int * 10 %} {% if battery_level == 100
                  %} mdi:battery {% elif battery_level > 0 %} mdi:battery-{{
                  battery_level }} {% else %} mdi:battery-alert-variant-outline
                  {% endif %}
                badge_color: >-
                  {% set battery_level = states('sensor.main_gym_battery') | int
                  %}

                  {% if battery_level > 90 %} green

                  {% elif battery_level > 60 %} light-green

                  {% elif battery_level > 50 %} lime

                  {% elif battery_level > 40 %} yellow

                  {% elif battery_level > 30 %} amber

                  {% elif battery_level > 20 %} orange

                  {% elif battery_level > 10 %} deep-orange

                  {% else %} red

                  {% endif %}
                tap_action:
                  action: more-info
                entity: sensor.main_gym_battery
                layout: vertical
              - type: custom:mushroom-lock-card
                entity: lock.main_gym
                name: Main Gym Door
                primary_info: none
                secondary_info: none
                icon_type: none
            card_mod:
              style: |
                ha-card {
                  {% if is_state('lock.main_gym','locked') and
                  is_state('binary_sensor.main_gym_door', 'off') %}
                    background: rgba(145,2,2,0.5);
                  {% elif is_state('binary_sensor.main_gym_door', 'on') %}
                    background: rgba(130,130,0,0.5);
                  {% else %}
                    background: rgba(2,61,2,0.5);
                  {% endif %}
                }
          - type: custom:stack-in-card
            cards:
              - type: custom:mushroom-template-card
                primary: Main Front Door
                secondary: |-
                  {% if is_state('binary_sensor.main_front_door_door','on') %}
                    Door Open
                  {% elif is_state('lock.main_front_door','unlocked') %}
                    Unlocked
                  {% else %}
                    Locked
                  {% endif%}
                icon: |-
                  {% if is_state('binary_sensor.main_front_door_door','on') %}
                    mdi:door-open
                  {% elif is_state('lock.main_front_door','unlocked') %}
                    mdi:lock-open
                  {% else %}
                    mdi:lock
                  {% endif%}
                icon_color: >-
                  {% if is_state('lock.main_front_door','locked') and
                  is_state('binary_sensor.main_front_door_door','off') %}
                    red
                  {% elif is_state('binary_sensor.main_front_door_door','on') %}
                    yellow
                  {% else %}
                    green
                  {% endif%}
                badge_icon: >-
                  {% set battery_level =
                  (states('sensor.main_front_door_battery') | int / 10) |
                  round(0) | int * 10 %} {% if battery_level == 100 %}
                  mdi:battery {% elif battery_level > 0 %} mdi:battery-{{
                  battery_level }} {% else %} mdi:battery-alert-variant-outline
                  {% endif %}
                badge_color: >-
                  {% set battery_level =
                  states('sensor.main_front_door_battery') | int %}

                  {% if battery_level > 90 %} green

                  {% elif battery_level > 60 %} light-green

                  {% elif battery_level > 50 %} lime

                  {% elif battery_level > 40 %} yellow

                  {% elif battery_level > 30 %} amber

                  {% elif battery_level > 20 %} orange

                  {% elif battery_level > 10 %} deep-orange

                  {% else %} red

                  {% endif %}
                tap_action:
                  action: more-info
                entity: sensor.main_front_door_battery
                layout: vertical
              - type: custom:mushroom-lock-card
                entity: lock.main_front_door
                name: Main Front Door
                primary_info: none
                secondary_info: none
                icon_type: none
            card_mod:
              style: |
                ha-card {
                  {% if is_state('lock.main_front_door','locked') and
                  is_state('binary_sensor.main_front_door_door', 'off') %}
                    background: rgba(145,2,2,0.5);
                  {% elif is_state('binary_sensor.main_front_door_door', 'on') %}
                    background: rgba(130,130,0,0.5);
                  {% else %}
                    background: rgba(2,61,2,0.5);
                  {% endif %}
                }
          - type: custom:stack-in-card
            cards:
              - type: custom:mushroom-template-card
                primary: Main Hot Tub Door
                secondary: >-
                  {% if
                  is_state('binary_sensor.main_basement_to_hot_tub_door','on')
                  %}
                    Door Open
                  {% elif is_state('lock.main_basement_to_hot_tub','unlocked')
                  %}
                    Unlocked
                  {% else %}
                    Locked
                  {% endif%}
                icon: >-
                  {% if
                  is_state('binary_sensor.main_basement_to_hot_tub_door','on')
                  %}
                    mdi:door-open
                  {% elif is_state('lock.main_basement_to_hot_tub','unlocked')
                  %}
                    mdi:lock-open
                  {% else %}
                    mdi:lock
                  {% endif%}
                icon_color: >-
                  {% if is_state('lock.main_basement_to_hot_tub','locked') and
                  is_state('binary_sensor.main_basement_to_hot_tub_door','off')
                  %}
                    red
                  {% elif
                  is_state('binary_sensor.main_basement_to_hot_tub_door','on')
                  %}
                    yellow
                  {% else %}
                    green
                  {% endif%}
                badge_icon: >-
                  {% set battery_level =
                  (states('sensor.main_basement_to_hot_tub_battery') | int / 10)
                  | round(0) | int * 10 %} {% if battery_level == 100 %}
                  mdi:battery {% elif battery_level > 0 %} mdi:battery-{{
                  battery_level }} {% else %} mdi:battery-alert-variant-outline
                  {% endif %}
                badge_color: >-
                  {% set battery_level =
                  states('sensor.main_basement_to_hot_tub_battery') | int %}

                  {% if battery_level > 90 %} green

                  {% elif battery_level > 60 %} light-green

                  {% elif battery_level > 50 %} lime

                  {% elif battery_level > 40 %} yellow

                  {% elif battery_level > 30 %} amber

                  {% elif battery_level > 20 %} orange

                  {% elif battery_level > 10 %} deep-orange

                  {% else %} red

                  {% endif %}
                tap_action:
                  action: more-info
                entity: sensor.main_basement_to_hot_tub_battery
                layout: vertical
              - type: custom:mushroom-lock-card
                entity: lock.main_basement_to_hot_tub
                name: Main Hot Tub Door
                primary_info: none
                secondary_info: none
                icon_type: none
            card_mod:
              style: |
                ha-card {
                  {% if is_state('lock.main_basement_to_hot_tub','locked') and
                  is_state('binary_sensor.main_basement_to_hot_tub_door', 'off') %}
                    background: rgba(145,2,2,0.5);
                  {% elif is_state('binary_sensor.main_basement_to_hot_tub_door', 'on') %}
                    background: rgba(130,130,0,0.5);
                  {% else %}
                    background: rgba(2,61,2,0.5);
                  {% endif %}
                }
    card_mod:
      style: |
        ha-card {
          background-color: rgba(0,0,0,0.85);
        }

Multiple rows / colums can be done like:

grid-row-start: auto 
grid-row-end: span 2

grid-column-start: auto
grid-column-end: span 2

on the view options per grid item

I used a grid layout and was able to get what i was looking for.

Hello guys,

Do you know how to remove this difference from other cards using the grid layout-card?

image

margin: 0
grid-template-columns: 85% 1fr
grid-template-areas: |
  "left right"
mediaquery:
  "(max-width: 600px)":
    grid-template-columns: 80% 1fr
    grid-template-areas: |
      "left right"

Thank you a lot for your help :laughing:

Use the margin: setting like this margin: -10px 0px 0px 0px

margin: -10px 0px 0px 0px
grid-template-columns: 85% 1fr
grid-template-areas: |
  "left right"
mediaquery:
  "(max-width: 600px)":
    grid-template-columns: 80% 1fr
    grid-template-areas: |
      "left right"
1 Like

As an FYI to everyone using this: With the new 2024.06 update, layout-card dashboards break if they are using the break-card. The dashboard will all just be in one column instead of multiple.

Github issue is already present for this: Layout-break doesn't cause a column break in HA 2024.6 Ā· Issue #291 Ā· thomasloven/lovelace-layout-card Ā· GitHub

I want to document the fix here. Editing the yaml configuration of the dashboard, changing this:

type: custom:vertical-layout

to this:

type: custom:layout-card
layout_type: custom:vertical-layout

The caveat with this fix is that the dashboard will no longer be editable in the GUI, just in YAML. But it should provide you with a quick fix until a fix is merged or you build an alternative dashboard (e.g. with vertical stacks).

3 Likes

I will wait for the Fix.
Or is there another card that does the same.

1 Like