Reusing layout yaml code across all views

Hi all,

Does anyone know how to reuse layout yaml code across different views without having to copy and paste the full (in my case 39) lines of code?

I have the following code in my yaml code:

    layout:
      margin: 0
      grid-gap: 10px
      grid-template-columns: 200px repeat(3, 1fr) 0fr
      grid-template-rows: 55px repeat(3, fit-content(100%)) 55px
      grid-template-areas: |
        "sidebar header header header ."
        "sidebar info info info ."
        "sidebar left middle right ."
        "sidebar left2 middle2 right2 ."
        "servers servers people internet ."
      mediaquery:
        '(max-width: 650px)':
          grid-template-columns: auto
          grid-template-rows: 100%
          grid-template-areas: |
            "sidebar"
            "header"
            "info"
            "people"
            "middle"
            "left"
            "right"
            "left2"
            "middle2"
            "right2"
            "servers"
            "internet"
          '(max-width: 1600px)':
            grid-gap: 5px
            grid-template-columns: 100px repeat(3, 1fr) 0fr
            grid-template-rows: 40px repeat(3, min-content) 55px auto
            grid-template-areas: |
              "sidebar header header header ."
              "sidebar info info info ."
              "sidebar left middle right ."
              "sidebar left2 middle2 right2 ."
              ". servers people internet ."
              ". . . . ."

Ideally this would be reused across all views as i have a set layout that i’d like to use across all views. If i make a change, I would rather not have to amend this code across all views.

I have tried to use !include and split this into a different yaml file but it doesn’t appear to be formatting my cards correctly - however using the exact code in the main yaml file it does render correctly so I don’t think it is incorrect yaml.

Any help would be much appreciated.

James

Typically you can only reuse things with yaml mode & anchors. Otherwise it’s copy paste. There custom cards like decluttering card that also do this. But again, I don’t believe you can use that in the UI.

Yeah, i have had a look at decluttering cards but i don’t think works with the main layout part of the lovelace views.

I’ve not looked at anchors before - would that enable me to copy the above layout yaml and reuse it in other views within the same file?

Yes, if you put all of your yaml into a single file. But you cannot use the UI at all. It has to be 100% yaml only mode.

Is it about using a “custom:layout-card” ?

I’ve been building it all in YAML anyway, so not using the UI is not an issue.

So if i understand it right, would i just change the first “layout:” to “&layout:”

and then whenever i have a layout: for a different view further down the file change that to “*layout:” and it would then use the first section of code as below:

&layout:
      margin: 0
      grid-gap: 10px
      grid-template-columns: 200px repeat(3, 1fr) 0fr
      grid-template-rows: 55px repeat(3, fit-content(100%)) 55px
      grid-template-areas: |
        "sidebar header header header ."
        "sidebar info info info ."
        "sidebar left middle right ."
        "sidebar left2 middle2 right2 ."
        "servers servers people internet ."
      mediaquery:
        '(max-width: 650px)':
          grid-template-columns: auto
          grid-template-rows: 100%
          grid-template-areas: |
            "sidebar"
            "header"
            "info"
            "people"
            "middle"
            "left"
            "right"
            "left2"
            "middle2"
            "right2"
            "servers"
            "internet"
          '(max-width: 1600px)':
            grid-gap: 5px
            grid-template-columns: 100px repeat(3, 1fr) 0fr
            grid-template-rows: 40px repeat(3, min-content) 55px auto
            grid-template-areas: |
              "sidebar header header header ."
              "sidebar info info info ."
              "sidebar left middle right ."
              "sidebar left2 middle2 right2 ."
              ". servers people internet ."
              ". . . . ."

Can I have your full code please? I want to test your dashboard.

This is all i have at the moment - so please be aware it is unfinished. I am still building it out and trying to overcome the multi-view and layout templating.

resources:
  - url: /local/decluttering-card.js
    type: module
decluttering_templates: !include decluttering_templates.yaml

views:
  - title: Home
    type: custom:grid-layout
    path: home
    icon: mdi:home-assistant
    layout:
      margin: 0
      grid-gap: 10px
      grid-template-columns: 200px repeat(3, 1fr) 0fr
      grid-template-rows: 55px repeat(3, fit-content(100%)) 55px
      grid-template-areas: |
        "sidebar header header header ."
        "sidebar info info info ."
        "sidebar left middle right ."
        "sidebar left2 middle2 right2 ."
        "servers servers people internet ."
      mediaquery:
        '(max-width: 650px)':
          grid-template-columns: auto
          grid-template-rows: 100%
          grid-template-areas: |
            "sidebar"
            "header"
            "info"
            "people"
            "middle"
            "left"
            "right"
            "left2"
            "middle2"
            "right2"
            "servers"
            "internet"
          '(max-width: 2600px)':
            grid-gap: 5px
            grid-template-columns: 100px repeat(3, 1fr) 0fr
            grid-template-rows: 40px repeat(3, min-content) 55px auto
            grid-template-areas: |
              "sidebar header header header ."
              "sidebar info info info ."
              "sidebar left middle right ."
              "sidebar left2 middle2 right2 ."
              ". servers people internet ."
              ". . . . ."
    cards:
        
      - type: custom:decluttering-card ### Sidebar ###
        template: sidebar_template
        view_layout:
          grid-area: sidebar
      - type: custom:decluttering-card ### Header ###
        template: header_template
        view_layout:
          grid-area: header
      - type: custom:decluttering-card ### Info ###
        template: info_template
        view_layout:
          grid-area: info



      - type: vertical-stack
        cards:
          - show_name: true
            show_icon: true
            type: button
            tap_action:
              action: navigate
              navigation_path: home-assistant
            icon: mdi:home-assistant
            show_state: true
            icon_height: 35px
            name: Home Assistant Status
          - show_name: true
            show_icon: true
            type: button
            tap_action:
              action: navigate
              navigation_path: home-lights
            icon: mdi:home-lightbulb
            show_state: true
            icon_height: 35px
            name: Lights
        view_layout:
          grid-area: left
      - type: vertical-stack
        cards:
          - initial_view: dayGridDay
            type: calendar
            entities:
              - calendar.home_home
              - calendar.bins_bins
              - calendar.uk_holidays
        view_layout:
          grid-area: middle
      - type: vertical-stack
        cards:
          - type: conditional
            conditions:
              - entity: switch.pi_hole
                state_not: unavailable
            card:
              show_name: true
              show_icon: true
              type: button
              tap_action:
                action: call-service
                service: pi_hole.disable
                data:
                  duration: '00:05:00'
                target:
                  entity_id:
                    - switch.pi_hole
                    - switch.pi_hole_mac_mini
              entity: switch.pi_hole
              name: TrueNAS Pihole blocking is
              hold_action:
                action: none
              show_state: true
              icon_height: 50px
          - type: conditional
            conditions:
              - entity: switch.pi_hole_mac_mini
                state_not: unavailable
            card:
              show_name: true
              show_icon: true
              type: button
              tap_action:
                action: call-service
                service: pi_hole.disable
                data:
                  duration: '00:05:00'
                target:
                  entity_id:
                    - switch.pi_hole_mac_mini
                    - switch.pi_hole
              entity: switch.pi_hole_mac_mini
              name: Mac Mini Pihole blocking is
              hold_action:
                action: none
              show_state: true
              icon_height: 50px
          - show_name: true
            show_icon: true
            show_state: true
            type: glance
            entities:
              - entity: switch.pi_hole
              - entity: switch.pi_hole_mac_mini
            state_color: true
        view_layout:
          grid-area: right

      
      - type: custom:decluttering-card ### Footer Server ###
        template: server_footer_template
        view_layout:
          grid-area: servers
      - type: custom:decluttering-card ### Footer People ###
        template: people_footer_template
        view_layout:
          grid-area: people
      - type: custom:decluttering-card ### Footer Internet ###
        template: internet_footer_template
        view_layout:
          grid-area: internet
  - title: Rooms
    type: custom:grid-layout
    path: rooms
    icon: mdi:room-service
    subview: true
    layout:
      margin: 0
      grid-gap: 10px
      grid-template-columns: 200px repeat(3, 1fr) 0fr
      grid-template-rows: 55px repeat(3, fit-content(100%)) 55px
      grid-template-areas: |
        "sidebar header header header ."
        "sidebar info info info ."
        "sidebar left middle right ."
        "sidebar left2 middle2 right2 ."
        "servers servers people internet ."
      mediaquery:
        '(max-width: 650px)':
          grid-template-columns: auto
          grid-template-rows: 100%
          grid-template-areas: |
            "sidebar"
            "header"
            "info"
            "people"
            "middle"
            "left"
            "right"
            "left2"
            "middle2"
            "right2"
            "servers"
            "internet"
          '(max-width: 2600px)':
            grid-gap: 5px
            grid-template-columns: 100px repeat(3, 1fr) 0fr
            grid-template-rows: 40px repeat(3, min-content) 55px auto
            grid-template-areas: |
              "sidebar header header header ."
              "sidebar info info info ."
              "sidebar left middle right ."
              "sidebar left2 middle2 right2 ."
              ". servers people internet ."
              ". . . . ."
    cards:
        
      - type: custom:decluttering-card ### Sidebar ###
        template: sidebar_template
        view_layout:
          grid-area: sidebar
      - type: custom:decluttering-card ### Header ###
        template: header_template
        view_layout:
          grid-area: header
      - type: custom:decluttering-card ### Info ###
        template: info_template
        view_layout:
          grid-area: info

      - type: vertical-stack
        cards:
          - type: custom:room-card
            title: Kitchen
            rows:
              - entities:
                  - entity: light.kitchen
                    name: Kitchen Lights
                    tap_action:
                      action: toggle
                  - entity: switch.signify_netherlands_b_v_lom009_switch
                    show_icon: true
                    name: Pixel Tablet
                    state_color: true
                    icon: mdi:tablet
                    tap_action:
                      action: toggle
              - entities:
                  - entity: sensor.kitchen_illuminance
                    show_name: true
                    name: Lux
                    show_state: true
                  - entity: sensor.kitchen_temperature
                    show_name: true
                    name: Temperature
                    show_state: true
                  - entity: sensor.kitchen_humidity
                    show_name: true
                    name: Humidity
                    show_state: true
            info_entities:
              - entity: binary_sensor.kitchen_presence_group
                show_icon: true
                hide_if:
                  conditions:
                    - condition: equals
                      entity: binary_sensor.kitchen_presence_group
                      value: 'off'
              - entity: binary_sensor.kitchen_door_sensor_open
                show_icon: true
                icon:
                  state_on: mdi:door-open
                  state_off: mdi:door-closed
            cards:
              - type: climate-card
                entity: climate.kitchen_radiator
                show_states:
                  - heat
                name: Radiator
                title: Kitchen
                control:
                  _headings: true
                  _icons: true
                  _names: true
                  hvac:
                    heat:
                      icon: mdi:fire
                      name: 'On'
                    'off':
                      icon: mdi:power
                      name: 'Off'
              - type: picture-entity
                hide_unavailable: true
                show_state: false
                show_name: false
                camera_view: auto
                camera_image: camera.camera_hub_g3_e60b
                entity: camera.camera_hub_g3_e60b
                layout:
                  step: row
                control: true
                header: false
                hide_if:
                  conditions:
                    - condition: not
                      value: idle
          - type: custom:room-card
            title: Lean-To
            rows: null
            info_entities:
              - entity: binary_sensor.lean_to_camera_motion_detected
                show_icon: true
                hide_if:
                  conditions:
                    - condition: equals
                      entity: binary_sensor.lean_to_camera_motion_detected
                      value: 'off'
            cards:
              - type: picture-entity
                hide_unavailable: true
                show_state: false
                show_name: false
                camera_view: auto
                camera_image: camera.lean_to_camera
                entity: camera.lean_to_camera
                layout:
                  step: row
                control: true
                header: false
                hide_if:
                  conditions:
                    - condition: not
                      value: idle
        view_layout:
          grid-area: left2
      - type: vertical-stack
        cards:
          - type: custom:room-card
            title: Bedroom
            rows:
              - entities:
                  - entity: light.bedroom
                    name: Bedroom Lights
                    tap_action:
                      action: toggle
              - entities:
                  - entity: sensor.bedroom_illuminance
                    show_name: true
                    name: Lux
                    show_state: true
                  - entity: sensor.bedroom_temperature
                    show_name: true
                    name: Temperature
                    show_state: true
                  - entity: sensor.bedroom_humidity
                    show_name: true
                    name: Humidity
                    show_state: true
            info_entities:
              - entity: binary_sensor.bedroom_presence_group
                show_icon: true
                hide_if:
                  conditions:
                    - condition: equals
                      entity: binary_sensor.bedroom_presence_group
                      value: 'off'
            cards:
              - type: climate-card
                entity: climate.bedroom_radiator
                show_states:
                  - heat
                name: Radiator
                title: Bedroom
                control:
                  _headings: true
                  _icons: true
                  _names: true
                  hvac:
                    heat:
                      icon: mdi:fire
                      name: 'On'
                    'off':
                      icon: mdi:power
                      name: 'Off'
        view_layout:
          grid-area: middle
      - type: vertical-stack
        cards:
          - type: custom:room-card
            title: Hallway
            rows:
              - entities:
                  - entity: light.hallway
                    name: Hallway Lights
                    tap_action:
                      action: toggle
                  - entity: switch.ts011f_hallway_switch_left
                    show_icon: true
                    name: Yale Module
                    state_color: true
                    tap_action:
                      action: more-info
            info_entities:
              - entity: binary_sensor.ewelink_ms01_hallway_motion
                show_icon: true
                hide_if:
                  conditions:
                    - condition: equals
                      entity: binary_sensor.ewelink_ms01_hallway_motion
                      value: 'off'
              - entity: binary_sensor.front_door_open
                show_icon: true
                icon:
                  state_on: mdi:door-open
                  state_off: mdi:door-closed
            cards:
              - type: climate-card
                entity: climate.smart_thermostat
                show_states:
                  - heat
                name: Thermostat
                title: Hallway
                control:
                  _headings: true
                  _icons: true
                  _names: true
                  hvac:
                    heat:
                      icon: mdi:fire
                      name: 'On'
                    'off':
                      icon: mdi:power
                      name: 'Off'
              - type: picture-entity
                hide_unavailable: true
                show_state: false
                show_name: false
                camera_view: auto
                camera_image: camera.doorbell
                entity: camera.doorbell
                layout:
                  step: row
                control: true
                header: false
                hide_if:
                  conditions:
                    - condition: not
                      value: idle
        view_layout:
          grid-area: middle2
      - type: vertical-stack
        cards:
          - type: custom:room-card
            title: Office
            rows:
              - entities:
                  - entity: light.office
                    name: Office Lights
                    tap_action:
                      action: toggle
                  - entity: cover.office_curtains
                    show_icon: true
                    name: Curtains
                    state_color: true
                    icon: mdi:curtains
                    tap_action:
                      action: toggle
              - entities:
                  - entity: sensor.office_temperature
                    show_name: true
                    name: Temperature
                    show_state: true
                  - entity: sensor.office_humidity
                    show_name: true
                    name: Humidity
                    show_state: true
            info_entities:
              - entity: binary_sensor.office_presence_group
                show_icon: true
                state_color: true
                hide_if:
                  conditions:
                    - condition: equals
                      entity: binary_sensor.office_presence_group
                      value: 'off'
            cards:
              - type: climate-card
                entity: climate.office_radiator
                show_states:
                  - heat
                name: Radiator
                title: Office
                control:
                  _headings: true
                  _icons: true
                  _names: true
                  hvac:
                    heat:
                      icon: mdi:fire
                      name: 'On'
                    'off':
                      icon: mdi:power
                      name: 'Off'
        view_layout:
          grid-area: right2
      - type: vertical-stack
        cards:
          - type: custom:room-card
            title: Living Room
            rows:
              - entities:
                  - entity: light.living_room
                    name: Living Room Lights
                    tap_action:
                      action: navigate
                      path: living_room
                  - entity: cover.ts0601_living_room_blinds
                    show_icon: true
                    name: Blinds
                    state_color: true
                    icon: mdi:blinds-vertical
                    tap_action:
                      action: toggle
            info_entities:
              - entity: sensor.living_room_illuminance
                show_name: true
                name: Lux
                show_state: true
              - entity: sensor.living_room_temperature
                show_name: true
                name: Temperature
                show_state: true
              - entity: sensor.living_room_humidity
                show_name: true
                name: Humidity
                show_state: true
              - entity: binary_sensor.living_room_presence_group
                show_icon: true
                hide_if:
                  conditions:
                    - condition: equals
                      entity: binary_sensor.living_room_presence_group
                      value: 'off'
            cards:
              - type: climate-card
                entity: climate.living_room_radiator
                show_states:
                  - heat
                name: Radiator
                title: Living Room
                control:
                  _icons: true
                  _headings: true
                  _names: true
                  hvac:
                    heat:
                      icon: mdi:fire
                      name: 'On'
                    'off':
                      icon: mdi:power
                      name: 'Off'
        view_layout:
          grid-area: left
      - type: vertical-stack
        cards:
          - type: custom:room-card
            title: Bathroom
            rows:
              - entities:
                  - entity: light.bathroom_lights
                    name: Bathroom Lights
                    tap_action:
                      action: toggle
              - entities:
                  - entity: sensor.lumi_lumi_motion_ac02_illuminance
                    show_name: true
                    name: Lux
                    show_state: true
                  - entity: sensor.bathroom_temperature
                    show_name: true
                    name: Temperature
                    show_state: true
                  - entity: sensor.bathroom_humidity
                    show_name: true
                    name: Humidity
                    show_state: true
            info_entities:
              - entity: binary_sensor.lumi_lumi_motion_ac02_motion
                show_icon: true
                hide_if:
                  conditions:
                    - condition: equals
                      entity: binary_sensor.lumi_lumi_motion_ac02_motion
                      value: 'off'
            cards:
              - type: climate-card
                entity: climate.bathroom_radiator
                show_states:
                  - heat
                name: Radiator
                title: bathroom
                control:
                  _headings: true
                  _icons: true
                  _names: true
                  hvac:
                    heat:
                      icon: mdi:fire
                      name: 'On'
                    'off':
                      icon: mdi:power
                      name: 'Off'
        view_layout:
          grid-area: right

      
      - type: custom:decluttering-card ### Footer Server ###
        template: server_footer_template
        view_layout:
          grid-area: servers
      - type: custom:decluttering-card ### Footer People ###
        template: people_footer_template
        view_layout:
          grid-area: people
      - type: custom:decluttering-card ### Footer Internet ###
        template: internet_footer_template
        view_layout:
          grid-area: internet

no,

layout: &my_layout
  ... contents ...

and using it

layout: *my_layout

Thanks @petro this is exactly what i was after. It would be great if this worked in the same way as the decluttering cards so you could use the layout across different yaml files for each view within a dashboard but it still saves a lot of time!