You can use the built in Lovelace entity button card: https://www.home-assistant.io/lovelace/entity-button/ and stack them horizontally and vertically. I wouldn’t recommend it though.
You get a better result with the custom tiles card for Lovelace: https://github.com/rodrigofragadf/lovelace-cards/tree/master/tiles-card
EDIT: I see that link is still getting a lot of hits. I no longer recommend the tiles card as it has been unsupported for quite some time. The custom button card is a much better option. Lovelace: Button card
e.g.
Here’s the config for that card to get you started:
card_settings:
background: var(--paper-card-background-color)
column_width: calc(97%/4)
columns: 4
row_height: 75px
title: TV
title_align: left
entities:
- column: 1
entity: script.lounge_tv_on
icon:
value: 'mdi:power-cycle'
label_sec:
value: 'On'
row: 1
- column: 2
entity: script.lounge_tv_off
icon:
value: 'mdi:power-off'
label_sec:
value: 'Off'
row: 1
- column: 1
entity: script.lounge_tv_input_tv
icon:
value: 'mdi:television-classic'
label_sec:
value: TV
row: 2
- column: 2
entity: script.lounge_tv_input_pc
icon:
value: 'mdi:desktop-classic'
label_sec:
value: PC
row: 2
- column: 3
entity: script.lounge_tv_input_kodi
icon:
value: 'mdi:kodi'
label_sec:
value: Kodi
row: 2
- column: 1
entity: script.lounge_tv_play
icon:
value: 'mdi:play'
row: 3
- column: 2
entity: script.lounge_tv_pause
icon:
value: 'mdi:pause'
row: 3
- column: 3
entity: script.lounge_tv_stop
icon:
value: 'mdi:stop'
row: 3
- column: 4
entity: script.lounge_tv_rec
icon:
color:
value: '#ff0000'
value: 'mdi:record'
row: 3
- column: 1
entity: script.lounge_tv_menu
icon:
value: 'mdi:menu'
label_sec:
value: Menu
row: 4
- column: 2
entity: script.lounge_tv_rew
icon:
value: 'mdi:rewind'
row: 4
- column: 3
entity: script.lounge_tv_ffwd
icon:
value: 'mdi:fast-forward'
row: 4
- column: 4
entity: script.lounge_tv_ch_up
icon:
value: 'mdi:arrow-up-bold-box-outline'
row: 4
- column: 1
entity: script.lounge_tv_option
icon:
value: 'mdi:playlist-edit'
label_sec:
value: Options
row: 5
- column: 2
entity: script.lounge_tv_skip_back
icon:
value: 'mdi:skip-previous'
row: 5
- column: 3
entity: script.lounge_tv_skip_fwd
icon:
value: 'mdi:skip-next'
row: 5
- column: 4
entity: script.lounge_tv_last_ch
icon:
value: 'mdi:arrow-left-bold-box-outline'
label_sec: Last CH
row: 5
- column: 1
entity: script.lounge_tv_guide
icon:
value: 'mdi:television-guide'
label_sec:
value: Guide
row: 6
- column: 2
entity: script.lounge_tv_info
icon:
value: 'mdi:information-outline'
label_sec:
value: Info
row: 6
- background:
value: '#2576da'
column: 3
entity: script.lounge_tv_up
icon:
value: 'mdi:arrow-up-bold-circle'
row: 6
- column: 4
entity: script.lounge_tv_ch_dn
icon:
value: 'mdi:arrow-down-bold-box-outline'
row: 6
- column: 1
entity: script.lounge_tv_media
icon:
value: 'mdi:folder-multiple-image'
label_sec:
value: Media
row: 7
- background:
value: '#2576da'
column: 2
entity: script.lounge_tv_left
icon:
value: 'mdi:arrow-left-bold-circle'
row: 7
- column: 3
entity: script.lounge_tv_ok
icon:
value: 'mdi:check-circle-outline'
row: 7
- background:
value: '#2576da'
column: 4
entity: script.lounge_tv_right
icon:
value: 'mdi:arrow-right-bold-circle'
row: 7
- column: 1
entity: script.lounge_tv_www
icon:
value: 'mdi:play-network'
label_sec: Internet
row: 8
- column: 2
entity: script.lounge_tv_return
icon:
value: 'mdi:backburger'
label_sec:
value: Return
row: 8
- background:
value: '#2576da'
column: 3
entity: script.lounge_tv_down
icon:
value: 'mdi:arrow-down-bold-circle'
row: 8
- column: 4
entity: script.lounge_tv_exit
icon:
value: 'mdi:backspace'
label_sec: Exit
row: 8
- column: 1
entity: script.lounge_tv_red
icon:
color: '#ff0000'
value: 'mdi:square'
row: 9
- column: 2
entity: script.lounge_tv_green
icon:
color: '#00ff00'
value: 'mdi:square'
row: 9
- column: 3
entity: script.lounge_tv_yellow
icon:
color: '#ffff00'
value: 'mdi:square'
row: 9
- column: 4
entity: script.lounge_tv_blue
icon:
color: '#0000ff'
value: 'mdi:square'
row: 9
global_settings:
border:
color:
value: black
radius: 5px
size: 3px
icon:
color:
value: white
label_sec:
color:
value: white
shadow: 'elevation: 6dp'
type: 'custom:tiles-card'
and an accompanying script example
lounge_tv_on:
sequence:
- service: remote.send_command
data:
entity_id: remote.lounge_tv
command: "ON"