Mastering YAML: The Language of Home Automation (And Why It Hates Tabs)

By The Maker Team December 02, 2025
Mastering YAML: The Language of Home Automation (And Why It Hates Tabs)
In this Syntax Guide:
  • The Golden Rule: Spaces vs. Tabs (The #1 Error)
  • The Structure: Keys, Values, and Lists
  • Deep Dive: Deconstructing a complex Home Assistant Card
  • Tools: How to stop making syntax errors

If you are getting into Docker, ESPHome, or Home Assistant, you are going to spend a lot of time looking at YAML files.

YAML (YAML Ain't Markup Language) is designed to be human-readable. It doesn't use curly braces {} like JSON or tags <> like HTML. instead, it uses Indentation to define structure.

This makes it look clean, but it makes it incredibly unforgiving. One invisible character can break your entire smart home. Here is how to master the invisible.


Rule 1: The "Tab" is Forbidden

This is the single most common reason beginners fail.

CRITICAL WARNING
YAML does not understand Tabs.
If you press the "Tab" key on your keyboard and your text editor inserts a generic Tab character, your configuration will fail to load. You must use Spaces.

The Standard: Use 2 Spaces for every level of indentation.

The Fix: You don't actually have to hit the spacebar twice. In VS Code (or any good code editor), go to settings and enable "Insert Spaces". This forces the Tab key to insert 2 space characters instead of a Tab character.


Rule 2: The Structure (The Ladder)

Think of YAML as a ladder. Things that are indented "under" a key belong to that key.

  • Key-Value: name: Livingroom Slider
  • Lists: Denoted by a dash (-). This is a collection of items.
  • Multi-Line Strings: Denoted by a pipe (|). This allows you to write code blocks (like JavaScript) inside the YAML.

Real World Example: The Custom Button Card

Let's look at a real, complex dashboard card submitted by a "Great Meets" community member. This card combines a Title, a Grid, and a Battery Monitor all in one.

Pay attention to the Indentation Ladder:

type: vertical-stack
cards:
  # This is the first item in the list (The Title)
  - text: Door Status
    type: custom:text-divider-row

  # This is the second item (The Grid)
  - square: false
    columns: 3
    type: grid
    cards:
      # Inside the grid, we start a NEW list of cards
      - aspect_ratio: 1.9/1.7
        name: Livingroom Slider
        entity: binary_sensor.livingroom_slider_opening_2
        state:
          # Defining what the button looks like when OFF
          - color: rgb(32,32,32)
            icon: mdi:door-sliding-lock
            value: "off"
          # Defining what it looks like when ON
          - color: rgb(128,0,0)
            icon: mdi:door-sliding-open
            value: "on"
            styles:
              icon:
                - animation: blink 2s ease infinite
        
        # COMPLEX SECTION: Custom CSS Styling
        styles:
          card:
            - padding: 1%
          custom_fields:
            battery:
              - position: absolute
              - right: 2%
              - top: 2%
        
        # JAVASCRIPT TEMPLATING
        # Notice the "|" symbol? That allows the multi-line JS block below.
        custom_fields:
          battery: |
            [[[
              let battery = parseInt(states["sensor.livingroom_slider_battery_2"]?.state) || 0;
              let icon = "mdi:battery";
              let color = "#00cc00"; 

              if (battery >= 95) { icon = "mdi:battery"; color = "#009900"; }
              else if (battery < 15) { icon = "mdi:battery-10"; color = "#cc0000"; }
              
              return `<ha-icon icon="${icon}" style="color: ${color};"></ha-icon>`;
            ]]]
        type: custom:button-card

Notice how `styles:` is indented under `cards:`? If you moved `styles:` back two spaces to the left, the YAML parser would think you are trying to apply styles to the Grid, not the Button, and the code would fail.


3. Common Gotchas

The Colon Space

Wrong: name:Livingroom

Right: name: Livingroom

YAML requires a space after the colon. Without it, the system thinks it is a string, not a key-value pair.

The "Multi-Line" Pipe

When you see battery: |, that Pipe symbol tells YAML: "Everything below this, as long as it is indented, is just one big block of text."

This is crucial for inserting JavaScript or HTML into your Home Assistant cards.


Conclusion: Get a Linter

You do not have to memorize this. The best thing you can do is install Visual Studio Code with the "Home Assistant Config Helper" extension.

It will highlight your indentation errors in red before you even try to save the file. It turns a frustrating guessing game into a simple checklist.

Share Your Dashboards!

That custom battery card code above is awesome. Do you have a complex dashboard layout you are proud of? Copy your YAML and paste it into the Home Automation forum to inspire others.


Share Your Code ?