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

Thanks @boheme61,

This eventually did the job:

view_layout:
  grid-area: "lights"
cards:
  - view_layout:
      grid-area: "keukenh"
    type: conditional
    conditions:
      - condition: "numeric_state"
        entity: sensor.lights_on_in_the_kitchen
        above: 0

    card:
      type: "custom:button-card"
      template: "card_title"
      name: "Keuken"

  - view_layout:
      grid-area: "keuken1"
    type: "custom:mod-card"
    style:
      hui-horizontal-stack-card$: |
        #root {
          flex-wrap: wrap;
        }
        #root > hui-conditional-card {
          min-width: 174px;
          max-width: 174px;
          padding-block-end: 12px;
        }
    card:
      type: horizontal-stack
      cards:          
        - type: conditional
          conditions:
            - condition: state
              entity: light.keukenblok
              state: "on"
          card:
            type: "custom:button-card"
            template: card_light
            entity: light.keukenblok
            variables:
              ulm_card_light_icon: "mdi:lightbulb-fluorescent-tube"
              ulm_card_light_enable_color: true
              ulm_card_light_force_background_color: true
        ā€¦

Hi layout-card gurus

How do I I get these columns to justify into the center of the screen? So far everything justifies left. Do I really have to calculate 100% and then put in gap cards either side for padding???

type: custom:layout-card
layout_type: grid
layout_options:
  grid-template-columns: 3% 12% 12% 12% 12% 12% 3%
  grid-template-rows: auto
  grid-gap: 0px 0px
cards:...

Hi all,

I have the same problem of @domain_int .
Now itā€™s been about three days and canā€™t figure out why everything justified on the left instead of center.
Following my code:

type: custom:layout-card
layout_type: grid
layout_options:
  grid-template-columns: 500px 500px
  grid-template-rows: auto
  justify-content: center
  grid-template-areas: |
    "risorse storage"
    "informazioni informazioni"
    "pulsanti pulsanti"
  mediaquery:
    "(max-width: 650px)":
      grid-template-columns: 100%
      grid-template-areas: |
        "risorse"
        "storage"
        "informazioni"
        "pulsanti"
cards: ...

I also tried using ā€œplace-itemsā€ and allign-items", without success.

Thanks in advance

easiest way is to define columns either side of your content. Then you can define these as a % or ā€˜autoā€™.

Look at the below:

grid-template-columns: auto 500px 500px auto
grid-template-rows: auto
grid-template-areas: |
  ". risorse storage ."
  ". informazioni informazioni ."
  ". pulsanti pulsanti ."
mediaquery:
  "(max-width: 650px)":
    grid-template-columns: 100%
    grid-template-areas: |
      "risorse"
      "storage"
      "informazioni"
      "pulsanti"

Hi,

Thanks for the advise.
Unfortunately, ad you can see itā€™s not working using 2 empty columns:

Also tries using percentage:

grid-template-columns: 35% 15% 15% 35%
grid-template-rows: auto
grid-template-areas: |
  ". risorse storage ."
  ". informazioni informazioni ."
  ". pulsanti pulsanti ."
mediaquery:
  "(max-width: 650px)":
    grid-template-columns: 100%
    grid-template-areas: |
      "risorse"
      "storage"
      "informazioni"
      "pulsanti"

So the ā€œjustifyā€ option doesnā€™t work?

Thanks

are you adding the view_layout on each card to tell it which grid cell to be within?

for e.g on your resources grid cards:

view_layout:
  grid-area: risorse

Yep on each stack i added the correct view:

cards:
   - type: horizontal-stack
     view_layout:
       grid-area: risorse
     cards:
      - type: custom:mini-graph-card
        card_mod:
         class: hki
        entities: etc...

Strange - open up developer tools on your browser and look at the layout tab - will help see whats going on.

This is a full Lovelace view config you can try:

  - title: grid testing
    path: grid-testing
    type: custom:grid-layout
    layout:
      grid-template-columns: auto 500px 500px auto
      grid-template-rows: auto
      grid-template-areas: |
        ". test1 test1 ."
        ". test3 test4 ."
        ". test5 test5 ."
      mediaquery:
        '(max-width: 650px)':
          grid-template-columns: 100%
          grid-template-areas: |
            "test1"
            "test3"
            "test4"
            "test5"
    badges: []
    cards:
      - square: true
        type: grid
        cards:
          - type: custom:mini-graph-card
            entities:
              - sensor.time
          - type: custom:mini-graph-card
            entities:
              - sensor.time
          - type: custom:mini-graph-card
            entities:
              - sensor.time
          - type: custom:mini-graph-card
            entities:
              - sensor.time
        columns: 2
        view_layout:
          grid-area: test3
      - square: true
        type: grid
        cards:
          - type: custom:mini-graph-card
            entities:
              - sensor.time
          - type: custom:mini-graph-card
            entities:
              - sensor.time
          - type: custom:mini-graph-card
            entities:
              - sensor.time
          - type: custom:mini-graph-card
            entities:
              - sensor.time
        columns: 2
        view_layout:
          grid-area: test4
      - square: false
        type: grid
        cards:
          - show_name: true
            show_icon: true
            type: button
            entity: sun.sun
            tap_action:
              action: none
          - show_name: true
            show_icon: true
            type: button
            entity: sun.sun
            tap_action:
              action: none
          - show_name: true
            show_icon: true
            type: button
            entity: sun.sun
            tap_action:
              action: none
          - show_name: true
            show_icon: true
            type: button
            entity: sun.sun
            tap_action:
              action: none
          - show_name: true
            show_icon: true
            type: button
            entity: sun.sun
            tap_action:
              action: none
          - show_name: true
            show_icon: true
            type: button
            entity: sun.sun
            tap_action:
              action: none
        view_layout:
          grid-area: test1
      - type: entities
        entities:
          - entity: sun.sun
          - entity: sun.sun
          - entity: sun.sun
        title: Information
        view_layout:
          grid-area: test5

Hello community, I need your help:
I would like to create a dashboard and just canā€™t manage to create a suitable layout. It should mainly consist of custom:butto-cards. Most of them are squares with sides of the same length. Others are bit bigger and some also as rectangles, in double length.

Here is an image I created with an image editor of how I would like the layout to look:


(Donā€™t be surprised, these are all screenshots from 4 or 5 cards, which I have only duplicated, as this is purely about the layout. Later I want to replace these cards with others, in the same design, but with smarter features, like color and logo based weather states, entity status based on colors, and so on.)

I first tried to work with grid-cards. 5 pieces one below the other with 8 columns each. Then I tried various layouts with the layout card. But no matter what I do, the bottom rows of cards are always too deep, so I have to scroll down. but I want to be able to see the entire view on the tablet display.
Here is an example with a grid layout with 5 grid cards one below the other:

grid-template-columns: auto
grid-template-rows: auto
grid-template-areas: |
  "a a a a a a a a"
  "b b b b b b b b"
  "c c c c c c c c"
  "d d d d d d d d"
  "e e e e e e e e"

with this code it looks like this:

Ive also tried to create a place for each card to set:

grid-template-columns: repeat(8)
grid-template-rows: auto
grid-template-areas: |
  "a b c d e f g h"
  "i j k l m n o p"
  "q r s t u v w y"
  "a1 b1 c1 d1 e1 f1 g1 h1"
  "i1 j1 k1 l1 m1 n1 o1 p1"

With this code it looks like this:

However, you can see that the bottom fifth row disappears and I have to scroll to see it

To spare you all my failed attempts, Iā€™ll ask you a simple question: Whatā€™s the best way to proceed? Do I already specify my layout in the dashboard page setting? or would I rather split all rows into individual layout cards?

What am I doing wrong?

If I can solve this problem with your help, you will make someone very happy on his way to his dashboard of his dreams =)

Thank you!!

Hi,

This is how it look using developer tools:

As you can see everything is justified on the left, instead of the center of the screen.
Also, when using other options like ā€œjustifyā€ or ā€œplace-itemsā€, these are not displayed in the browser.
When using vertical stack, the justify option appears.
e.g using vertical:

cards:
  - type: vertical-stack
    cards:
      - type: horizontal-stack
        cards:
          - type: custom:mini-graph-card
            card_mod:
              class: hki
            entities: etc...

Iā€™m playing with this now. definitely possible and I have almost got it working.

Getting that grid is simple, reflowing each card when changing viewport is a little tricky! (aka use it on both tablet and phone etc.)

I will let you know once Iā€™ve got something good to share!

Unfinished auto-flow:

ScreenRecording2024-01-07at20.12.19-ezgif.com-video-to-gif-converter

1 Like

change your columns to 50% instead of 500px.

grid-template-columns: 50% 50%

That looks absolutely awesome. Be sure to let me know when youā€™ve made it. Youā€™ve already put a huge smile on my face :slight_smile:
And I thought Iā€™d have to make a separate mobile dashboard with a layout like this. Thatā€™s great

If that makes it a little easier for you: it doesnā€™t have to have exactly this number of squares and rectangles with sides twice as long. If it makes things easier for you with one or two more ā€œdoublesā€, thatā€™s fine too. they can certainly be filled with useful entities

Hey Thanks @sebbaT for the idea. Works well for my situation.

@Simob_98 - try thisā€¦ I tried all permutations of grid CSS properties - most dont seem to do anything but align-content: stretch seems to have fixed my issue for the moment, Im sure I will find something else that isnt justified properly in my dashboard and have to have another go at it.

cards:
  - type: custom:layout-card
    layout_type: grid
    layout_options:
      grid-template-columns: auto 15% 15% 15% 15% 15% auto
      grid-template-rows: auto
      grid-gap: 0px 0px
      align-content: stretch
    cards:
      ...

When it comes to your Cards/grid extends below you available, view-size, so you get scroll, can only be ā€œsolvedā€ with specify your vIew-size ( Resolution ) which you donā€™t specify, so kind of hard to help you with that , and same as Simob_98 you seems to think itā€™s enough to show half the required code, and pix/screenshots.

So maybe you just get half the ā€œanswerā€.

a1 a2 a3 a3 a4 a5 a6 a7
b1 b1 b3 b4 b5 b6 b7 b7
b1 b1 c3 c4 c5 c5 c6 c7
b1 b1 d3 d3 d5 d6 d7 d7
e1 e1 d3 d3 e5 e5 d7 d7

b1 = vertical-stack/grid for your condition cards
d3 = same, but the square
e1 = MainFloor lights on

The rest you have to guess your self :wink:

1 Like

okay so was easier than I thought - there is better ways but Iā€™m limited by layout-card currently.

This will automatically flow your cards into the grid and create rows when the columns reach a defined size.

You do not need to give your cards heights or widths as they should fill the cell.

Single square cards will autofill.

If you want a card to take up two columns (like your image) add:

aspect_ratio: 2/1 ##for custom:button-card
view_layout:
  grid-column: span 2

If you want a card to take up two columns and two rows (like your image) add:

aspect_ratio: 1/1 ##for custom:button-card
view_layout:
  grid-column: span 2
  grid-row: span 2

Youā€™ll need to use card-mod with custom:button-card to get them to behave and fill the cells:

card_mod:
  style: |
    :host {
      height: 100% !important;
      width: 100% !important;
      max-width: 100% !important;
      margin: 0 !important;
      position: unset !important;
      display: grid !important;
      }

This is a full working Lovelace dashboard to play with:

views:
  - title: Bento Grid
    path: bentogrid
    panel: false
    type: custom:grid-layout
    layout:
      place-items: stretch stretch
      height: 1fr
      min-height: 1fr
      margin: 0
      card_margin: 0
      padding: 25px
      grid-template-columns: repeat(auto-fit, minmax(max(110px,10vw), 2fr))
      grid-gap: 10px
      grid-auto-rows: 1fr
    icon: mdi:music
    badges: []
    cards:
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        aspect_ratio: 2/1
        view_layout:
          grid-column: span 2
        styles:
          card:
            - border-radius: 10px
            - background-color: green
        card_mod:
          style: |
            :host {
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        view_layout: null
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        aspect_ratio: 2/1
        view_layout:
          grid-column: span 2
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        view_layout:
          grid-column: span 2
          grid-row: span 3
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        view_layout:
          grid-row: span 2
          grid-column: span 2
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }
      - type: custom:button-card
        styles:
          card:
            - border-radius: 10px
            - height: 100%
            - background-color: green
        card_mod:
          style: |
            :host {
              height: 100% !important;
              width: 100% !important;
              max-width: 100% !important;
              margin: 0 !important;
              position: unset !important;
              display: grid !important;
              }

1 Like

Hmmmm, Very unpredictable behavior, have you tried reducing your browser width ? ā€¦ 8-7-6-5-4-3-2 columns ?

Yes, itā€™s entirely predictable behaviour with CSS grid. The order of cards should be configured to actually make sense (this is just random testing).

But this layout will auto flow cards based on a fixed 1/1 grid and gives the OP the ability to create the dashboard that he showed in their photo.

bentogridtest-ezgif.com-video-to-gif-converter

If You with OP, mean Still ill , it seems like he want to priorities Column 1 , but again itā€™s very hard to know as it not very clear , beside the Size and approx placement , which will Fluctuate wildly on your model , thatā€™s where the view-layout grid-area , for the Layout-card-View comes in handy.

view_layout:
       grid-area:

I donā€™t know where you found your example , Mix of Grid-Layout And Custom button-card syntax , but i donā€™t get the impression that you have any control where your cards ends up, beside the fixed initial order your write the cards , and some half-random defined , shuffle around through all available columns