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

Guys, please help , as I am kind of CSS noob:
my goal is to have view orientation dependent layout
one kolumn in portrait
2 columns in landscape view

Also it would be nice if my cards could auto fill whole free space, but with specified max width.

Btw, kudos for the author (however more example codes would be nice)

heres my config: views: - title: null type: custom:grid-layout layout: grid-t - Pastebin.com
why it doesnt fill my template areas?

I have the same issueā€¦have you figured out any resolution yet?

I have cleared cache and also tried Chrome, IE, and Firefoxā€¦none show the layout option

OK so interface looks different, but have it kind of working.

My next question is can I specify which column and location within that column for each card discretely? The card up/down movement arrows never let me get each cards position where I want it.

@Steveuk Did you ever figure out a way to have your sidebar fixed and have the right hand side cards scroll? Iā€™m trying to accomplish something very similarā€¦

1 Like

I would like to use the grid layout to setup a tablet dashboard.
Iā€™ve started with a very basic one with a header row and a left, middle and right column below it. I place 3 cards in each column just to test it out. Everything works as expected.

Dashboard YAML
kiosk_mode:
  non_admin_settings:
    kiosk: true
    ignore_entity_settings: true
views:
  - title: Home
    path: home
    icon: mdi:home
    theme: ios-dark-mode-blue-red
    type: custom:grid-layout
    layout:
      grid-template-columns: 33% 33% 33%
      grid-template-rows: auto
      grid-template-areas: |
        "header header header"
        "left middle right"
    badges: []
    cards:
      - type: custom:mushroom-chips-card
        view_layout:
          grid-area: header
        chips:
          - type: template
            entity: input_boolean.disable_all_automations
            icon: mdi:creation
            tap_action:
              action: toggle
            icon_color: |-
              {% if is_state('input_boolean.disable_all_automations', 'on') %}
                red
              {% else %}
                green
              {% endif %}
            content: |-
              {% if is_state('input_boolean.disable_all_automations', 'on') %}
                Automations Off
              {% else %}
                Automations On
              {% endif %}
          - type: template
            entity: sensor.lights_on_count
            icon: mdi:lightbulb
            icon_color: |-
              {% if is_state('sensor.lights_on_count', '0') %}
                grey
              {% else %}
                orange
              {% endif %}
            content: '{{states("sensor.lights_on_count")}} Lights On'
            tap_action:
              action: navigate
              navigation_path: /lovelace-home/dashboard_lights
            double_tap_action:
              action: none
            hold_action:
              action: call-service
              service: homeassistant.turn_off
              data: {}
              target:
                entity_id:
                  - group.all_lights
                  - group.all_keep_light_on_switches
      - type: custom:plotly-graph
        view_layout:
          grid-area: right
          show: always
        entities:
          - entity: sensor.temperature_outside
            yaxis: y1
            line:
              color: '#FFA726'
              width: 1
            showlegend: false
            show_value: true
            texttemplate: <b>%{y}</b>Ā°C
            hovertemplate: >-
              <b>%{data.name}</b><br><i>%{x}</i><br>
              %{y}%{data.unit_of_measurement} <extra></extra>
          - entity: sensor.humidity_outside
            yaxis: y2
            line:
              color: '#78A2FF'
              width: 1
            showlegend: false
            show_value: true
            texttemplate: <b>%{y}</b>%
            hovertemplate: >-
              <b>%{data.name}</b><br><i>%{x}</i><br>
              %{y}%{data.unit_of_measurement} <extra></extra>
        hours_to_show: 28
        refresh_interval: 10
        layout:
          plot_bgcolor: '#FFFDF0'
          xaxis:
            rangeselector:
              'y': 1.05
              buttons:
                - count: 12
                  step: hour
                - count: 1
                  step: day
                - count: 3
                  step: day
                - count: 7
                  step: day
          yaxis:
            title:
              text: Temperature
            color: '#FFA726'
          yaxis2:
            title:
              text: Humidity
            color: '#78A2FF'
        time_offset: 4h
      - show_name: true
        show_icon: true
        type: button
        view_layout:
          grid-area: middle
        tap_action:
          action: toggle
        entity: light.livingroom_coatrack
      - show_name: true
        show_icon: true
        type: button
        view_layout:
          grid-area: left
        tap_action:
          action: toggle
        entity: switch.light_livingroom_and_entrance_l1

Now if I replace the card in the first column with a custom:bom-weather-card I run into problems. In edit mode it looks like I expect

Dashboard (with weather card) YAML
kiosk_mode:
  non_admin_settings:
    kiosk: true
    ignore_entity_settings: true
views:
  - title: Home
    path: home
    icon: mdi:home
    theme: ios-dark-mode-blue-red
    type: custom:grid-layout
    layout:
      grid-template-columns: 33% 33% 33%
      grid-template-rows: auto
      grid-template-areas: |
        "header header header"
        "left middle right"
    badges: []
    cards:
      - type: custom:mushroom-chips-card
        view_layout:
          grid-area: header
        chips:
          - type: template
            entity: input_boolean.disable_all_automations
            icon: mdi:creation
            tap_action:
              action: toggle
            icon_color: |-
              {% if is_state('input_boolean.disable_all_automations', 'on') %}
                red
              {% else %}
                green
              {% endif %}
            content: |-
              {% if is_state('input_boolean.disable_all_automations', 'on') %}
                Automations Off
              {% else %}
                Automations On
              {% endif %}
          - type: template
            entity: sensor.lights_on_count
            icon: mdi:lightbulb
            icon_color: |-
              {% if is_state('sensor.lights_on_count', '0') %}
                grey
              {% else %}
                orange
              {% endif %}
            content: '{{states("sensor.lights_on_count")}} Lights On'
            tap_action:
              action: navigate
              navigation_path: /lovelace-home/dashboard_lights
            double_tap_action:
              action: none
            hold_action:
              action: call-service
              service: homeassistant.turn_off
              data: {}
              target:
                entity_id:
                  - group.all_lights
                  - group.all_keep_light_on_switches
      - type: custom:plotly-graph
        view_layout:
          grid-area: right
          show: always
        entities:
          - entity: sensor.temperature_outside
            yaxis: y1
            line:
              color: '#FFA726'
              width: 1
            showlegend: false
            show_value: true
            texttemplate: <b>%{y}</b>Ā°C
            hovertemplate: >-
              <b>%{data.name}</b><br><i>%{x}</i><br>
              %{y}%{data.unit_of_measurement} <extra></extra>
          - entity: sensor.humidity_outside
            yaxis: y2
            line:
              color: '#78A2FF'
              width: 1
            showlegend: false
            show_value: true
            texttemplate: <b>%{y}</b>%
            hovertemplate: >-
              <b>%{data.name}</b><br><i>%{x}</i><br>
              %{y}%{data.unit_of_measurement} <extra></extra>
        hours_to_show: 28
        refresh_interval: 10
        layout:
          plot_bgcolor: '#FFFDF0'
          xaxis:
            rangeselector:
              'y': 1.05
              buttons:
                - count: 12
                  step: hour
                - count: 1
                  step: day
                - count: 3
                  step: day
                - count: 7
                  step: day
          yaxis:
            title:
              text: Temperature
            color: '#FFA726'
          yaxis2:
            title:
              text: Humidity
            color: '#78A2FF'
        time_offset: 4h
      - show_name: true
        show_icon: true
        type: button
        view_layout:
          grid-area: middle
        tap_action:
          action: toggle
        entity: light.livingroom_coatrack
      - type: custom:bom-weather-card
        view_layout:
          grid-area: left
        title: BOM Weather
        entity_current_conditions: sensor.marsfield_icon_descriptor_0
        entity_temperature: sensor.olympicpark_temp
        entity_forecast_high_temp_1: sensor.marsfield_temp_max_1
        entity_forecast_high_temp_2: sensor.marsfield_temp_max_2
        entity_forecast_high_temp_3: sensor.marsfield_temp_max_3
        entity_forecast_high_temp_4: sensor.marsfield_temp_max_4
        entity_forecast_high_temp_5: sensor.marsfield_temp_max_5
        entity_forecast_icon_1: sensor.marsfield_icon_descriptor_1
        entity_forecast_icon_2: sensor.marsfield_icon_descriptor_2
        entity_forecast_icon_3: sensor.marsfield_icon_descriptor_3
        entity_forecast_icon_4: sensor.marsfield_icon_descriptor_4
        entity_forecast_icon_5: sensor.marsfield_icon_descriptor_5
        entity_forecast_low_temp_1: sensor.marsfield_temp_min_1
        entity_forecast_low_temp_2: sensor.marsfield_temp_min_2
        entity_forecast_low_temp_3: sensor.marsfield_temp_min_3
        entity_forecast_low_temp_4: sensor.marsfield_temp_min_4
        entity_forecast_low_temp_5: sensor.marsfield_temp_min_5
        entity_summary_1: sensor.marsfield_short_text_1
        entity_summary_2: sensor.marsfield_short_text_2
        entity_summary_3: sensor.marsfield_short_text_3
        entity_summary_4: sensor.marsfield_short_text_4
        entity_summary_5: sensor.marsfield_short_text_5
        entity_sun: sun.sun
        entity_daytime_high: sensor.marsfield_temp_max_0
        entity_daytime_low: sensor.marsfield_temp_min_0
        entity_wind_bearing: sensor.olympicpark_wind_direction
        entity_wind_speed: sensor.olympicpark_wind_speed_kilometre
        entity_wind_gust: sensor.olympicpark_gust_speed_kilometre
        entity_humidity: sensor.olympicpark_humidity
        entity_apparent_temp: sensor.olympicpark_temp_feels_like
        entity_daily_summary: sensor.marsfield_extended_text_0
        entity_pop: sensor.marsfield_rain_chance_0
        entity_pop_intensity: sensor.olympicpark_rain_since_9am
        entity_possible_today: sensor.marsfield_rain_amount_range_0
        entity_pos_1: sensor.marsfield_rain_amount_range_1
        entity_pos_2: sensor.marsfield_rain_amount_range_2
        entity_pos_3: sensor.marsfield_rain_amount_range_3
        entity_pos_4: sensor.marsfield_rain_amount_range_4
        entity_pos_5: sensor.marsfield_rain_amount_range_5
        entity_pop_1: sensor.marsfield_rain_chance_1
        entity_pop_2: sensor.marsfield_rain_chance_2
        entity_pop_3: sensor.marsfield_rain_chance_3
        entity_pop_4: sensor.marsfield_rain_chance_4
        entity_pop_5: sensor.marsfield_rain_chance_5
        entity_current_text: sensor.bom_current_text
        entity_uv_alert: sensor.bom_uv_alert
        entity_fire_danger: sensor.bom_fire_danger
        entity_uv_alert_summary: sensor.uv_cat_formatted
        entity_fire_danger_summary: sensor.marsfield_fire_danger_0
        locale: en
        sunset: true
        static_icons: false
        old_icon: hybrid
        tooltip_bg_color: rgb( 75,155,239)
        tooltip_border_color: rgb(255,161,0)
        tooltip_border_width: 1
        tooltip_caret_size: 5
        tooltip_fg_color: '#fff'
        tooltip_left_offset: -12
        tooltip_width: 110
        tooltips: true
        old_daily_format: false
        time_format: 12
        show_beaufort: false
        refresh_interval: 60
        show_separator: false
        temp_top_margin: 0px
        temp_font_weight: 300
        temp_font_size: 4em
        temp_right_pos: 0.85em
        temp_uom_top_margin: '-12px'
        temp_uom_right_margin: 4px
        apparent_top_margin: 45px
        apparent_right_pos: 1em
        apparent_right_margin: 1em
        current_text_top_margin: 4.5em
        current_text_left_pos: 0px
        current_text_font_size: 1.5em
        current_text_alignment: center
        current_text_width: 100%
        current_data_top_margin: 10em
        large_icon_top_margin: '-3.2em'
        large_icon_left_position: 0px
        separator_top_margin: 6em
        summary_top_padding: 2em
        summary_font_size: 0.8em
        slot_l1: daytime_high
        slot_l2: daytime_low
        slot_l3: wind
        slot_l4: pressure
        slot_l5: sun_next
        slot_r1: pop
        slot_r2: humidity
        slot_r3: uv_summary
        slot_r4: fire_summary
        slot_r5: sun_following
        card_mod:
          style: |
            ha-card {
              width: 350px;
              max-width: 350px;
              height: 585px;
              max-height: 585px;
            }

ā€¦ but as soon as I click DONE the weather card disappears.

Does somebody have an idea why this happens? Are there cards which donā€™t work together with the layout card / grid layout?

Grid-layout.

I want to change background color in grid-areas based on screen size. I.e. I have a grid-area element for a sidemenu where I want to have different background on tablet and phone.

CSS should be capable to do this, in combination with mediaquery, I believe. Example copyed from grid-template - CSS: Cascading Style Sheets | MDN where grid areas have different background colors:

#page {
  display: grid;
  width: 100%;
  height: 200px;
  grid-template:
    [header-left] "head head" 30px [header-right]
    [main-left] "nav  main" 1fr [main-right]
    [footer-left] "nav  foot" 30px [footer-right]
    / 120px 1fr;
}

header {
  background-color: lime;
  grid-area: head;
}

nav {
  background-color: lightblue;
  grid-area: nav;
}

main {
  background-color: yellow;
  grid-area: main;
}

footer {
  background-color: red;
  grid-area: foot;
}

How do I do this???

Hey can someone help me here???

I have a background that scales perfectly on a desktop but it only displays partially and looks smaller on a tablet. This behaviour on a tablet ā€œappearsā€ to be linked to the layout card.

If i remove the references to the layout card the background scales across the whole screen

My theme code: (background.jpg is 1920x1200)

lovelace-background: 'center / cover repeat fixed url("/local/background.jpg")' 

The code in the dashboard:

views:
  - title: energy
    path: energy
    theme: new-theme
    type: custom:grid-layout
    badges: []
    cards:
      - type: custom:layout-card
        layout_type: grid
        panel: true
        layout_options:
          grid-template-columns: >-
            150px 150px 150px 150px 150px 150px 150px 150px 150px 150px 150px
            150px
          grid-template-rows: 100px
          grid-gap: 0px 0px
        cards:
          - type: custom:button-card
            show_name: true
            name: b1
            tap_action:
              action: navigate
              navigation_path: /dashboard-tablet1/general
              ...

tablet dimensions

the result:

Sorry for the late reply.
No I didnā€™t unfortunately, I just adapted it so it wouldnā€™t need to scroll

Hi,
I have tried to fake the energy dashboard layout but canā€™t get it right. Can anyone help me? I want to style it like this.

SkaĢˆrmavbild 2023-07-05 kl. 08.51.19

1 Like

Did you find any solution? As I am trying to do exactly the same, but didnā€™t succeed yet :slight_smile:

I did. The solution was simple.

1 Like

Many thanks! That fixed it :wink:

My layout card seems to render oddly when using my PC. It renders ok on a mobile view, but from chrome on my PC the sizing height is way off. It specifically seems to get out of proportion on desktop only when using apex-card. Anyone have any thoughts on this?

MOBILE VIEW

The layout setup i have is

grid-template-columns: 10% 10% 10% 10% 10% 10% 10% 10% 10% 10%
grid-template-rows: 30% 18% 18% 30%
grid-template-areas: |
  "ttg ttg ttg ttg ttg ttg ttg ttg ttg ttg"
  "shore shore shore shore shore ac ac ac ac ac"
  "dc dc dc battery battery battery battery solar solar solar"
  "chart chart chart chart chart chart chart chart chart chart"

And then, this is the desktop view:
DESKTOP VIEW

(Sorry for double post, but was limitted to the amount of photos i could embed)

can this be used to ensure all items scale to fit on screen without scrolling? I would like to cast a view and have everything visible at once. apologies if this has already been answered this is a long thread to scroll through.

why are my cards not side by side?

type: custom:layout-card
layout_type: custom:horizontal-layout
cards:
  - type: custom:atomic-calendar-revive
    name: Calendar Card
    enableModeChange: true
    entities:
      - entity: calendar.geburtstage
        name: Geburtstage
      - entity: calendar.abfall
        name: Abfall
      - entity: calendar.mil
        name: Mi
    showDeclined: true
    hideFinishedEvents: true
  - type: custom:atomic-calendar-revive
    name: Calendar Card
    enableModeChange: true
    entities:
      - entity: calendar.abfall
        name: Abfall
      - entity: calendar.geburtstage
        name: Geburtstage
      - entity: calendar.mi
        name: Mi
    defaultMode: Calendar
    showLoader: false
    hideDuplicates: false
    showLocation: false
  - type: entities
    entities:
      - sensor.ph_wert_12_stunden_min
      - sensor.ph_wert_12_stunden_max
      - sensor.orp_wert_12_stunden_min
layout:
  width: 400
  max_cols: 2

Use thisā€¦

view_layout:
 column: 1 

Then second card etc

view_layout:
 column: 2

hmm. no changesā€¦

looks like before

type: custom:layout-card
layout_type: custom:horizontal-layout
cards:
  - type: custom:atomic-calendar-revive
    view_layout:
      column: 1
    name: Calendar Card
    enableModeChange: true
    entities:
      - entity: calendar.abfall
        name: Abfall
      - entity: calendar.geburtstage
        name: Geburtstage
      - entity: calendar.mi
        name: Mi
    defaultMode: Calendar
    showLoader: false
    hideDuplicates: false
    showLocation: false
  - type: custom:atomic-calendar-revive
    name: Calendar Card
    view_layout:
      column: 2
    enableModeChange: true
    entities:
      - entity: calendar.geburtstage
        name: Geburtstage
      - entity: calendar.abfall
        name: Abfall
      - entity: calendar.mi
        name: Mi
    showDeclined: true
    hideFinishedEvents: true
  - type: entities
    view_layout:
      column: 2
    entities:
      - sensor.ph_wert_12_stunden_min
      - sensor.ph_wert_12_stunden_max
      - sensor.orp_wert_12_stunden_min
layout:
  width: 400
  max_cols: 2


You have to set it at each card where ya want itā€¦
and on total bottom of the cardā€¦
and not somewhere between
and if you use as example an veritical-stack card
then it goes on total bottom of the stack cardā€¦
and not needed to use on each card inside that stack card

soā€¦ card 1 will be in column 1
card 2 will be in column 2
etc