> ## Documentation Index
> Fetch the complete documentation index at: https://docs.daylightcalendar.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Event Styles: Custom Colors and Icons for Calendar Events

> Use event_styles rules to apply colors, icons, opacity, and hide overrides to Home Assistant calendar events matched by title, calendar, location, or date.

The `event_styles` configuration lets you define a list of rules that change how individual events look on your calendar. Each rule specifies which events to target through a `match` object and how to style them through a `style` object. When multiple rules match the same event, conflicts are resolved per style property: the matching rule with the highest `priority` for that property wins. This makes it easy to build layered styling — for example, dimming all past events while still highlighting specific recurring ones at a higher priority.

## Rule Structure

Each entry in `event_styles` is a rule with the following top-level keys:

* **`match`** — describes which events the rule applies to. `when` is accepted as an alias.
* **`style`** — describes how matching events should look
* **`priority`** — optional integer (default `0`) that controls which rule wins when multiple rules set the same style property
* **`id`** — optional string identifier. Auto-generated (`event-style-1`, `event-style-2`, …) if omitted.

<Tip>
  `event_styles`, `day_styles`, and `day_badges` all share the same advanced match schema. Anything you learn here applies to the other two rule types.
</Tip>

<Tip>
  For one-off, per-device recoloring — for example, giving a single event a distinctive color on the family dashboard without changing the calendar — use the [Custom Color](/configuration/event-management#custom-event-colors) action in the event detail modal instead of `event_styles`. Modal overrides win over the `color` / `background_color` set here, but do not affect other style properties.
</Tip>

## Advanced match schema

The `match` object supports two scopes and the standard logical operators:

* **`match.event`** — event-scoped conditions (title, calendar, all\_day, etc.). For `event_styles`, fields written at the top level of `match` are implicitly treated as event conditions, so `match: { title: 'standup' }` and `match: { event: { title: 'standup' } }` are equivalent.
* **`match.day`** — day-scoped conditions (`today`, `weekend`, `has_event`, …). See [Day match fields](/advanced/day-styles#day-match-fields) for the full list. Useful when you want a rule to fire only on certain dates, e.g. weekdays.
* **`match.any` / `match.all` / `match.and` / `match.not`** — combine nested match blocks with OR / AND / NOT logic.

### Example: match a calendar only on weekdays

```yaml theme={null}
event_styles:
  - match:
      event:
        calendar: calendar.work
      day:
        weekday: true
    style:
      color: '#1565C0'
      font_color: '#ffffff'
```

## Event match fields

Use one or more of the following fields inside `match` (or `match.event`) to filter by event properties. By default, an event must satisfy **all** specified fields to be considered a match. For OR / NOT logic, use the [logical operators](#logical-operators) below.

<ParamField path="match.calendar" type="string">
  The entity ID of a specific Home Assistant calendar. Only events from that calendar entity will match. Aliases: `calendar_entity`, `entity_id`, `entity`.
</ParamField>

<ParamField path="match.title" type="string">
  A substring to look for in the event title. The match is case-insensitive. You can also pass a regex pattern wrapped in forward slashes, e.g. `/standup/i`. Alias: `title_contains: foo` is equivalent to `title: 'contains:foo'`.
</ParamField>

<ParamField path="match.summary" type="string">
  Alias for `match.title`. Both names map to the event summary field. Use whichever feels more natural. Alias: `summary_contains`.
</ParamField>

<ParamField path="match.description" type="string">
  A substring to look for in the event description field. Alias: `description_contains`.
</ParamField>

<ParamField path="match.location" type="string">
  A substring to look for in the event location field. Alias: `location_contains`.
</ParamField>

<ParamField path="match.all_day" type="boolean">
  When `true`, only matches all-day events. When `false`, only matches timed events. Alias: `all_day_event`.
</ParamField>

<ParamField path="match.past" type="boolean">
  When `true`, only matches events whose end time is in the past. When `false`, only matches events that are not yet past.
</ParamField>

## Logical Operators

For compound rules, `match` accepts three logical operator keys. Each operator takes either a single sub-condition object or an array of sub-condition objects, and sub-conditions use the same match-field syntax as a top-level `match` block — including nested operators.

<ParamField path="match.any" type="array">
  OR logic. The rule matches when **at least one** of the listed sub-conditions matches.
</ParamField>

<ParamField path="match.all" type="array">
  AND logic. The rule matches when **all** listed sub-conditions match. Same as combining fields at the top level, but useful when nesting inside `any` or `not`.
</ParamField>

<ParamField path="match.and" type="array">
  Alias for `match.all`.
</ParamField>

<ParamField path="match.not" type="object | array">
  NOT logic. The rule matches when the listed sub-condition (or none of the listed sub-conditions) matches.
</ParamField>

### Example: events on the work OR personal calendar

```yaml theme={null}
event_styles:
  - match:
      any:
        - calendar: calendar.work
        - calendar: calendar.personal
    style:
      opacity: 0.6
```

### Example: all-day events that are NOT in the past

```yaml theme={null}
event_styles:
  - match:
      all_day: true
      not:
        past: true
    style:
      color: '#1565C0'
      font_color: '#ffffff'
```

## Style Fields

The `style` object accepts the following properties to control how matched events are rendered.

<ParamField path="style.color" type="string">
  Alias for `style.background_color`. Hex color string (e.g. `'#1565C0'`) applied to the event's background or bar color.
</ParamField>

<ParamField path="style.background_color" type="string">
  Hex color string applied to the event's background or bar color. Equivalent to `style.color`.
</ParamField>

<ParamField path="style.font_color" type="string">
  Hex color string applied to the event's text. Use this to ensure readable contrast when you change the background color.
</ParamField>

<ParamField path="style.opacity" type="number">
  A number between `0` and `1` that controls the event's transparency. Use `0.4` to visually mute events without hiding them entirely.
</ParamField>

<ParamField path="style.filter" type="string">
  A CSS filter string applied to the event element. For example, `grayscale(100%)` removes all color from matching events.
</ParamField>

<ParamField path="style.icon" type="string">
  An MDI icon name (e.g. `mdi:repeat`) to attach to matching events. Combine with `icon_position` to control placement.
</ParamField>

<ParamField path="style.icon_position" default="before_title" type="string">
  Controls where the icon is rendered. Use `before_title` to place it inline before the event title, or `corner` to display it as a small overlay in the corner of the event chip.
</ParamField>

<ParamField path="style.icon_color" type="string">
  Hex color string applied to the matched style icon. Defaults to the event's text color.
</ParamField>

<ParamField path="style.icon_size" type="string | number">
  Overrides the icon size. Accepts a number (interpreted as pixels) or any CSS length string such as `'14px'` or `'1.1em'`.
</ParamField>

<ParamField path="style.hide" type="boolean">
  When `true`, matching events are completely removed from the calendar view. Hidden events are not counted toward day event totals.
</ParamField>

<ParamField path="style.hide_time" type="boolean">
  When `true`, suppresses the time label on matching events even if times would otherwise be shown.
</ParamField>

<ParamField path="style.show_time" type="boolean">
  When `true`, forces the time label to render on matching events even if it would otherwise be hidden (for example, by `hide_times_for_calendars`).
</ParamField>

<ParamField path="style.hide_event_calendar_bubble" type="boolean">
  When `true`, hides the small calendar-color dot on matching events. Useful when you've added a custom `icon` and don't want the default indicator competing with it.
</ParamField>

<ParamField path="style.show_event_location" type="boolean">
  Per-rule override of the global `show_event_location` setting. Set to `true` to force locations on for matching events, or `false` to hide them on matching events only.
</ParamField>

<ParamField path="style.use_short_location" type="boolean">
  Per-rule override of the global `use_short_location` setting.
</ParamField>

<ParamField path="style.event_font_size" type="string | number">
  Per-rule override of the event title font size. Accepts a number (pixels) or CSS length string.
</ParamField>

<ParamField path="style.event_time_font_size" type="string | number">
  Per-rule override of the event time font size. Accepts a number (pixels) or CSS length string.
</ParamField>

<ParamField path="style.event_location_font_size" type="string | number">
  Per-rule override of the event location font size. Accepts a number (pixels) or CSS length string.
</ParamField>

<ParamField path="style.event_title_prefix" type="string">
  Per-rule override of the global `event_title_prefix` mode. Accepted values: `none`, `badge_icon`, `friendly_name`.
</ParamField>

## Priority

<ParamField path="priority" default="0" type="integer">
  When two or more rules match the same event, conflicts are resolved **per style property**. For each property, the rule with the highest `priority` wins. If priorities are equal, the rule defined earlier in the list wins. Properties that aren't set by the winning rule fall through to the next matching rule, so styles from different rules can compose on the same event.
</ParamField>

<Tip>
  Use `priority` to layer general rules with specific overrides. For example, set a low-priority rule that dims all past events, then add a high-priority rule that keeps a specific calendar's events fully visible regardless.
</Tip>

## Examples

### Color all events from a work calendar

This rule applies a deep blue background and white text to every event from `calendar.work`.

```yaml theme={null}
event_styles:
  - match:
      calendar: calendar.work
    style:
      color: '#1565C0'
      font_color: '#ffffff'
```

### Hide events titled "Free"

This rule completely removes any event whose title contains the word "Free" from the calendar view.

```yaml theme={null}
event_styles:
  - match:
      title: 'Free'
    style:
      hide: true
```

### Add a corner icon to a specific calendar's events

This rule stamps a briefcase icon in the corner of every event from `calendar.work`. A `priority` of `5` ensures it takes precedence over lower-priority color rules.

```yaml theme={null}
event_styles:
  - match:
      calendar: calendar.work
    style:
      icon: mdi:briefcase
      icon_position: corner
    priority: 5
```

### Mute all-day events with opacity

This rule reduces the opacity of all-day events to `0.4`, visually de-emphasizing them without hiding them.

```yaml theme={null}
event_styles:
  - match:
      all_day: true
    style:
      opacity: 0.4
    priority: 1
```

### Dim past events

This rule applies a grayscale filter and reduced opacity to any event that has already passed, giving the calendar a clear visual split between past and upcoming.

```yaml theme={null}
event_styles:
  - match:
      past: true
    style:
      filter: 'grayscale(100%)'
      opacity: 0.5
    priority: 1
```

### Combine multiple match conditions

You can narrow a rule by specifying more than one match field at the same time. This rule applies a grayscale filter only to past all-day events from a specific calendar.

```yaml theme={null}
event_styles:
  - match:
      calendar: calendar.holidays
      all_day: true
      past: true
    style:
      filter: 'grayscale(100%)'
      opacity: 0.5
    priority: 2
```

<Note>
  All style values are sanitized before they are applied to the DOM. Attempting to inject HTML or JavaScript through a `color`, `filter`, or other style field will be stripped out automatically.
</Note>
