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

Hi, Iā€™m new to CSS grid, so still learningā€¦

How do I now centre the grid within the available space in the card (red rectangle in image)

I managed to do it with gap cards and more columns, but the code was messy and Iā€™m sure thereā€™s an easier, cleaner way to do it.

Thanks!

layout_type: grid
layout:
  grid-template-columns: 100px 100px 100px
  grid-template-rows: auto
  grid-template-areas: |
    "title title title"
cards:
  - type: markdown
    content: Sky Q Upstairs
    view_layout:
      grid-area: title
    card_mod:
      style: |
        ha-card {
          text-align: center;
        {
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:rewind
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: rewind
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:play-pause
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: play
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:fast-forward
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: forward
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:exit-to-app
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: dismiss
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:chevron-up
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: up
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:home
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: home
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:chevron-left
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: left
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:circle-medium
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: select
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:chevron-right
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: right
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:chevron-up-circle-outline
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: channelup
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:chevron-down
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: down
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:information-outline
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: i
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:chevron-down-circle-outline
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: channeldown
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:record-rec
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: record
        media_content_type: skyq
  - type: custom:button-card
    aspect_ratio: 1/1
    icon: mdi:help-circle-outline
    tap_action:
      action: call-service
      service: media_player.play_media
      service_data:
        entity_id: media_player.sky_upstairs
        media_content_id: help
        media_content_type: skyq
  - type: custom:gap-card
  - type: custom:gap-card
columns: 7 

I want to create a view that looks like the picture above and I have struggled with layout-card, grid-card and different kind of combinations of horizontal- and vertical stacks but failed miserably. Any chance that this could be done with layout-card? I want the cards to fill the entire view

Grateful for all help I can get :pray:

Iā€™ve tested this, and it will distribute the cards on the screen how you want:

title: Test
icon: mdi:home-assistant
path: test
type: custom:grid-layout
layout:
  grid-template-columns: 20% 20% 20% 20% 20%
  grid-template-rows: auto ## or 4 if you want to be strict about it 
  grid-template-areas: |
    "buttons1 buttons1 buttons1 buttons1 buttons1"
    "r2button1 picture1 picture1 picture1 r2button2"
    "r3button1 picture1 picture1 picture1 r3button2"
    "buttons2 buttons2 buttons2 buttons2 buttons2"
cards:

## Row1
  - type: horizontal-stack
    view_layout:
      grid-area: buttons1
    cards:
      - type: button
        entity: XXXX
      - type: button
        entity: XXXX
      - type: button
        entity: XXXX
      - type: button
        entity: XXXX
      - type: button
        entity: XXXX

## Row2
  - type: horizontal-stack
    view_layout:
      grid-area: r2button1
    cards:
      - type: button
        entity: XXXX

  - type: picture-glance
    view_layout:
      grid-area: picture1
    entity: XXXX
    state_image: 
	  - XXXX
    entities:
      - XXXX

  - type: horizontal-stack
    view_layout:
      grid-area: r2button2
    cards:
      - type: button
        entity: XXXX

## Row3
  - type: horizontal-stack
    view_layout:
      grid-area: r3button1
    cards:
      - type: button
        entity: XXXX


  - type: horizontal-stack
    view_layout:
      grid-area: r3button2
    cards:
      - type: button
        entity: XXXX

## Row4
  - type: horizontal-stack
    view_layout:
      grid-area: buttons2
    cards:
      - type: button
        entity: XXXX
      - type: button
        entity: XXXX
      - type: button
        entity: XXXX
      - type: button
        entity: XXXX
      - type: button
        entity: XXXX

Iā€™ve used horizontal-stack cards around the buttons to ensure they fill 100% of the row height. And this is where you might meet your first hurdle - your graphic assumes that the default button height is 50% of the picture-glance height, which is not the case. Therefore, with this layout, the buttons on rows 3 + 4 will be taller than the buttons on rows 1 + 4.

Assuming you are working with a screen with a fixed height and width e/g a tablet, you can play around with Thomas Lovenā€™s custom card-mod to specify a height in pixels for the cards on rows 2 + 3, but this will not likely work well on a layout that needs to be responsive.

Anyway, hope this can get you going at least. Others might chip in if my code has obvious flaws or ways it could be improved.

2 Likes

Thank you very much, that worked like a charm!

I just need to tweak the heights of the button cards or add one more card on each side to match the height of the picture-glance card

Thank you @reste_narquois , that is very helpful.

Trying to build off of your template I have gotten stuck.

I thought I had it figured, but the height of my buttons in my second vertical stack is not automatically adjusted to fill the outer horizontal stack.
image

Did I do something wrong in the grid-template? To me it should be ā€œsimplyā€ two vertical stacks in one horizontal stack and the buttons in the second vertical-stack should be strechted evenly to fill the second column.

type: custom:layout-card
layout_type: custom:grid-layout
layout:
  grid-template-columns: 70% 30%
  grid-template-rows: auto
  grid-template-areas: |
    "position1 position2"
cards:
  - type: vertical-stack
    view-layout:
      grid-area: position1
    cards:
      - type: custom:slider-entity-row
        entity: climate.eq_3_living_room
        name: Living Room
        min: 4.5
        max: 23
        step: 0.5
        hide_state: false
        icon: mdi:fire
      - type: custom:apexcharts-card
        layout: minimal
        graph_span: 24h
        experimental:
          color_threshold: true
        update_interval: 10 s
        now:
          show: false
          color: red
          label: Now
        yaxis:
          - show: false
            max: 20
            min: 0
        header:
          title: Living Room Temperature
          show: false
          show_states: true
          colorize_states: true
        apex_config:
          grid:
            show: false
          chart:
            height: 200px
        series:
          - entity: sensor.eq_3_temperature_lr
            stroke_width: 2
            group_by:
              func: last
            fill_raw: zero
            color_threshold:
              - value: 4.5
                color: blue
              - value: 16
                color: yellow
              - value: 18
                color: orange
              - value: 20
                color: red
            type: line
            opacity: 1
  - type: vertical-stack
    view-layout:
      grid-area: position2
    cards:
      - type: custom:button-card
        entity: climate.eq_3_living_room
        name: 'Off'
        show_name: true
        show_icon: false
        show_state: false
        state:
          - operator: template
            value: '[[[ return entity.attributes.temperature == 4.5; ]]]'
            color: rgb(255, 0, 0)
        tap_action:
          action: call-service
          service: climate.set_temperature
          service_data:
            temperature: 4.5
            entity_id: climate.eq_3_living_room
      - type: custom:button-card
        entity: climate.eq_3_living_room
        name: 18 Ā°C
        show_name: true
        show_icon: false
        show_state: false
        state:
          - operator: template
            value: '[[[ return entity.attributes.temperature == 18; ]]]'
            color: rgb(255, 0, 0)
        tap_action:
          action: call-service
          service: climate.set_temperature
          service_data:
            temperature: 18
            entity_id: climate.eq_3_living_room
      - type: custom:button-card
        entity: climate.eq_3_living_room
        name: 20 Ā°C
        show_name: true
        show_icon: false
        show_state: false
        state:
          - operator: template
            value: '[[[ return entity.attributes.temperature == 20; ]]]'
            color: rgb(255, 0, 0)
        tap_action:
          action: call-service
          service: climate.set_temperature
          service_data:
            temperature: 20
            entity_id: climate.eq_3_living_room

I am curious, is it possible to use badges with any layout?
Tried this example - no badges:

title: test-2
path: test-test-2
panel: false
badges:
  - entity: input_boolean.test_boolean
type: custom:masonry-layout
cards: []

Same for vertical, horizontal.
Works only if the type: line is commented.
Panel mode = false.
It is not that I cannot live w/o badges - just for testingā€¦

Update 08.12.21:
There is a Github issue for this:

Hello

Iā€™m trying to get the image from the cameras side by side in a horizontal view but i still without success as you can check in the picture bellow

The ideia a card that ocupe to 2 of the 3 columns in the lovelace with this and not as in the picture ā€¦

Can anyone please let me know what i have to do in order to solve this ?

Thank you

Can you add this and show how it looks?

Edit Dashboard then add

aspect_ratio: .5/1

Hereā€¦

Not sure if this is what you wanted :thinking: but it looks like this on my end.

Thanks, but that makes all cards on that row huge and cover the whole screen, pushing the entire second row out at the bottom.

Hello

Iā€™m able now to have the imagens side by side

But not stretched in the card in big as I pretend ā€¦

The code:

type: horizontal-stack
cards:
  - type: custom:layout-card
    layout_type: custom:horizontal-layout
    title: Reolink
    cards:
      - type: horizontal-stack
        cards:
          - type: custom:button-card
            place-items: start stretch
            aspect_ratio: 2/1
            show_live_stream: true
            title: Reolink
            entity: camera.reolink01
            show_name: false
            styles:
              icon:
                - width: 100%
                - margin-left: 0%
          - type: custom:button-card
            aspect_ratio: 2/1
            show_live_stream: true
            title: Reolink
            entity: camera.reolink01
            show_name: false
            styles:
              icon:
                - width: 100%
                - margin-left: 0%

Thank you for any help in order to solve this

Hello,

I removed the layout-card from HACS and rebooted HA but when I create a new view I can see from the drop down menu that the mansory (layout-card), as well as the grid (layout-card) etc. are still present.

Does it mean that layout-card is still present/installed somehow?

If so, how can I completely uninstall it?

Thank you

Hi,

Iā€™m trying to unevenly distribute the cards in the view.

Letā€™s say 1 card filling the whole first row, 2 cards 60% 40% in the second row and 3 cards with the same width in the third one.

To try to achieve it Iā€™ve done the following

  • Create a view with grid as type
  • Added the following in options
grid-template-columns: 50px auto 50px
grid-template-rows: auto
grid-template-areas: |
  "main"
  • Created a new grid card with this configuration:
type: grid
columns: 1
title: OPNSense
cards:
  - type: entities
    state_color: true
    entities:
      - entity: binary_sensor.opnsense_pending_notices_present
      - entity: sensor.opnsense_system_boottime
      - entity: sensor.opnsense_cpu_load_average_one_minute
      ...... extra entities ......
square: false
view_layout:
  grid-area: main
  grid-column-start: 2
  grid-column-end: auto
  grid-row-start: 2
  grid-row-end: 3

And this is what I get

It uses the whole width of the main area; I tried to duplicate the card and see if the width reduces to 50% but it does not work, the new card just comes on top of the original one

Iā€™ve tried also to add this code at the end of the grid card (I tried with px values, percentage values and using :host instead of ha-card) but it does nothing

card_mod:
  style: |
    ha-card {
      width: 50%;
    }

Regards

Can you please clarify: do you wish your grid arrangement to apply to the whole dashboard? (for which you would use the custom layout card).

Or do you just want the grid to take up just part of the dashboard? (for which I guess you might use a grid card).

Iā€™m not sure Iā€™m clear what you are aiming to achieve by combining the twoā€¦

Hi @CDRX2 (or anyone else lol)
Iā€™m trying to do a similar sidebar and have some cards set up using the !include like you have.
But Iā€™ve found if I make changes in any of the Yaml files and save, it never updates on the dashboard thatā€™s even on the main Lovelace Yaml file or any of the !include cards even with a force refresh
Only way Iā€™ve found to work is change the name slightly of the Yaml file save then rename it back and it loads the changes on a refresh.
Anyone any tips as I canā€™t use it like that.
Thanks

Hi!
What do you mean when you say force refresh? In order to reload, going into the three dots menu at the top right and selecting refresh has always worked for me.

Refreshing the page via the browser will not, however.

Hi good morning,

What Iā€™m trying to achieve is something like the picture below; basically a non-homogeneous card distribution; I would like to be able to have rows with one card, with two cards at 50% with two cards at 70/30%, three cards ā€¦

image

Regards

1 Like

Hi thanks for the reply.
Yeah I meant Using the F5 key to refresh the browser.
Iā€™ve not actually tried using the refresh from there Iā€™ll do then when I get home from work thanks.
Are you willing to share your code for the sidebar part ?
Iā€™m trying to work out how to do the background and other bits as mine just look like buttons next to each other as it is now but really a sidebar so would be great to see some working code.
Thanks

Yup, F5 wonā€™t reload your code.

Iā€™ll PM you my sidebar code, too long to post here.

1 Like

Ah, ok.

The first 2 rows would be pretty straightforward without using any custom cards, but the third row makes it slightly more complicated as youā€™ve found.

Given that you have row 2 split 50/50, and row 3 split across what looks like 20/35/45, Iā€™ve effectively worked from the need to split your grid into 20 column units to cover both scenarios.

My suggested code is therefore a little unwieldy and probably not what someone who knows CSS much better than me would do, but this produces something like what your picture shows I think:

## lovelace_test.yaml
title: Test
type: custom:grid-layout
layout:
  # 20 equal columns, each taking up 1/20th of the width
  grid-template-columns: repeat(20, 1fr)
  grid-template-rows: auto
cards:

#Row 1
  - type: horizontal-stack
    view_layout:
    # start and end point for card across all the columns
      grid-column-start: 1
      grid-column-end: end
    cards:
      - type: xxxx

#Row 2
  - type: horizontal-stack
    view_layout:
      # start and end point for card across first half of the available columns
      grid-column-start: 1
      grid-column-end: 11
    cards:
      - type: xxxx
  - type: horizontal-stack
    view_layout:
      # start and end point for card across second half of the available columns
      grid-column-start: 11
      grid-column-end: end
    cards:
      - type: xxxx

#Row 3
  - type: horizontal-stack
    view_layout:
      # 4 columns = 4fr
      grid-column-start: 1
      grid-column-end: 5
    cards:
      - type: xxxx
  - type: horizontal-stack
    view_layout:
     # 7 columns = 7fr
      grid-column-start: 5
      grid-column-end: 12
    cards:
      - type: xxxx
  - type: horizontal-stack
    view_layout:
     # 9 columns = 9fr
      grid-column-start: 12
      grid-column-end: end
    cards:
      - type: xxxx

[The advantage of using horizontal-stack cards like this is that you can easily sub-divide them into equally spaced cards should you wish for e.g a row of buttons].

Hope this is enough to get you started at least e.g for adding a row with a 70/30 split (which you didnā€™t include in your picture).

1 Like

Hi reste_narquois,

Yes, this has helped me a lot :slightly_smiling_face:

Regards