💡 UI eXtension - Add CSS styles to (almost) any part of the Home Assistant UI

Chrome inspector bug. Safari shows correctly - a rare win for Safari :rofl:

I note Chrome shows correctly on Computed tab.

Wow. Thank you. Didn’t expect that, because the purple is the HA default and I wouldn’t understand, from where the expector gets that if set differently in theme.

I will have a look in another browser as well.

1 Like

:mega: UIX 8.3.0 Released :light_bulb:

UIX Styling inclusions:

  • Allowing styling of app container in Frontend. UIX styling is not injected to app itself, only the Frontend wrapping ha-panel-app allowing for styling header and an overlay.
  • UIX action locked_action. Uses same locks and code_dialog config of Forge lock spark.

The rest of the release is Forge and Broker related.

1 Like

:megaphone: UIX 8.4.0-beta.1 available :light_bulb:

Styling of app panel frames :partying_face:

Available by popular demand styling of App panel frames (iFrames).

To note:

  • This is an experiment feature so you need to turn on in UIX integration settings.
  • Custom panel and app panel frames now share a single uixFrame injected runtime which is a cut down version of the regular uix runtime. The injection can only take place in same origin frames, which is usually the case for custom panels like HACS and always the case for ingress hosted App panels. NOTE: Cross origin hosted frames are not supported as the main UIX runtime has no way to inject into the iFrame.
  • Two methods applied:
    1. If the framework of the frame is Lit, regular UIX shadowRoot theming can be applied.
    2. If the framework of the frame is not Lit (or regular HTML), any string (or .:) styles are rendered into an adopted stylesheet on document root.

Chekc DOCS for more information.

1 Like

:megaphone: UIX 8.4.0-beta.2 available :light_bulb:

Loading of fonts via uix-fonts theme variable

See DOCS for more information. Loading of fonts supported in main page and loaded custom/app panels loaded as frames.

1 Like

I’m currently setting up my dashboard from scratch.
I’ve given a lot of thought to which cards I should use. After reading up on UIX and seeing what’s possible with it, it really seems like the Holy Grail.
I wonder why none of the big Home Assistant YouTubers have made tutorials for UIX yet? Forge is amazing! I can only imagine how much time and effort went into this project.
I just wanted to say thank you.

1 Like

Thanks for the feedback. One big area for improvement is UI editing of Forged elements. See Manage foundry forges via UI? · Lint-Free-Technology/uix · Discussion #492 · GitHub which is proposal to both allow a layered config approach, separating element config and templates, which then allows to add UI editing.

2 Likes

Yeah, saw that already. Will card-mod-studio then become obsolete?

No, -studio is about generating UIX yaml in a visual way for well known DOM of stock cards. (Summary from my quick perusal just now)

The proposal I linked is about using Forge while not blocking the visual card editor for the forged element.

:megaphone: UIX 8.4.0-beta.5 available :light_bulb:

New popover UIX Action . See DOCS

Thanks to @VietNgoc for the request that I have been able to implement after some time.

Form spark also in the works to complement this so you can Forge a form on a popover

Form on Forged element in popover - sneak peak

Oct-02-2026 21-52-31

type: button
name: Popover
show_icon: false
tap_action:
  action: fire-dom-event
  uix:
    action: popover
    data:
      buttons:
        primary:
          label: Send
          end_icon: mdi:send
          tap_action:
            action: fire-dom-event
            uix:
              action: javascript
              data:
                variables:
                  source: contact-form
                code: >
                  console.info(`Submitted: Message: ${variables.message},
                  Priority: ${variables.priority} from ${variables.source}`);
      uix:
        style: |
          .uix-popover-card {
            --ha-card-border-width: 0px;
            --ha-card-background: none;
            --uix-form-padding: 0px;
            --ha-radio-option-active-color: red;
          }
      card:
        type: custom:uix-forge
        forge:
          mold: card
          sparks:
            - type: form
              density: dense
              schema:
                - name: message
                  label: Message
                  selector:
                    text: {}
                - name: priority
                  label: Priority
                  default: normal
                  selector:
                    select:
                      options:
                        - normal
                        - urgent
4 Likes

Hello,

I’m using my customized theme in dark mode.
Since a few HA versions, map cards in dark mode are realy realy dark and with uncontrasted colors (my opinion).

Is there a way to force all the UI map cards in light mode (especialy when showing the user more info panel) ?

Yes, with UIX Broker. See below…

First to mention that for map cards you can set directly, including a new user style available in 2026.10.0b0. The PR that enabled the user style also enabled style tokens, but you would need to research more for what a light style uses and then set them directly. See the PR for more info including the bit on —ha-color-map-* tokens.

The UIX Broker way is to directly set theme mode and style on all map cards and more-info containing maps. Use the following 2 interactions.

These are adapted for what I supplied to @Mariusthvdb who also uses a JavaScript directive first to set a theme mode.

The first interaction works to set theme mode and style on map card (hui-map-card), which also has buttons outside ha-map which are either white or black based on theme mode.

The second interaction works to set theme mode on ha-map used in more-info and acts directly on ha-map.

  - realm: browser
    listen:
      - uix-applied
      - uix-theme-update
    anchor: "hui-map-card <$$ target"
    reentrant: false
    rules:
      - hui-map-card
    directives:
      - type: property
        set: _config.theme_mode
        value: "light” # or dark
      - type: property
        set: _config.map_style
        value: "toner" # see map card doco for styles
      - type: call
        rules:
          - "{.requestUpdate}"
        method: "requestUpdate"
        args:
          - "hass"

  - realm: browser
    reentrant: false
    listen:
      - uix-applied
      - uix-theme-update
    anchor: "<$ target"
    rules:
      - ha-more-info-dialog
    directives:
      - type: property
        anchor: "$ ha-more-info-info $$ ha-map"
        set: themeMode
        value: "light"
      - type: property
        anchor: "$ ha-more-info-info $$ ha-map"
        set: mapStyle
        value: "toner"

2 Likes

As of 2026.10 you can set new Map theme tokens for many individual map properties

Have a look a that, you might be able to do natively in Frontend, and not use UIX for that

Where is the difference to what Darryn alread posted?

Nowhere.
I just missed that, and jumped in at the tag of my handle.

:megaphone: 8.4.0-beta.7 available :light_bulb:

:rocket: New Feature

Form spark - See DOCS. Form spark is compatible with new popover and also existing UIX actions javascript and event, as well as sending to backend server scripts.

:megaphone: UIX 8.4.0 Released :light_bulb: :partying_face:

Styling related features:

  • Load document fonts via uix-fonts theme variable.
  • Apply --uix-image-for-<entity_id> overrides to Map panel overview tabs
  • Add popover UIX Action
  • Add internal frame runtime (uixFrame) and replace custom-panel loader. Allows styling inside iFrames loaded by ha-panel-custom and ha-panel-app
  • Update map entity-picture styling so styling --uix-image-for-<entity_id> does not race with the markers which are always recreated in the new bubble clusters in Home Assistant 2026.10.0
2 Likes

So I finally made the switch to UIX and 99% of my dashboard was unaffected!

I can’t figure out how to fix this part though which uses “custom:mod-card”, that is the only thing that broke for me

Not gonna share the full code only the part thats broken cuz AI hasn’t been helpful lol

type: custom:mod-card
card_mod:
  style:
    mushroom-chips-card$: |
      .chip-container {
        background: var(--card-background-color) !important;
        backdrop-filter: var(--ha-card-backdrop-filter) !important;
        -webkit-backdrop-filter: var(--ha-card-backdrop-filter) !important;
        box-shadow: var(--ha-card-box-shadow) !important;
        border: none !important;
        border-radius: 40px !important;
        padding: 0 6px !important;
        display: flex !important;
        flex-direction: row !important;
        flex-wrap: nowrap !important;
        height: 46px !important; 
        align-items: center !important;
        justify-content: center !important;
        gap: 16px !important;
        box-sizing: border-box !important;
        width: max-content !important;
        margin: 0 !important;
      }
    .: |
      ha-card {
        position: fixed !important;
        top: calc(env(safe-area-inset-top, 0px) + 8px) !important;
        right: 16px !important;
        z-index: 999 !important;
        background: transparent !important;
        background-color: transparent !important;
        box-shadow: none !important;
        border: none !important;
        overflow: visible !important;
        margin: 0 !important; 
      }
card:
  type: custom:mushroom-chips-card
  alignment: center
  chips:
    - type: conditional
      conditions:
        - condition: user
          users:
            - bcb3f19ab921436b8f0678c28a123dd3
            - 07d2750343ff472d96d13c6ab604decc
            - 07d2750343ff472d96d13c6ab604decc
            - 07d2750343ff472d96d13c6ab604decc
            - 07d2750343ff472d96d13c6ab604decc
        - condition: screen
          media_query: '(min-width: 768px)'
      chip:
        type: template
        icon: mdi:pencil
        icon_color: green
        tap_action:
          action: navigate
          navigation_path: /lovelace/home?edit=1
    - type: template
      entity: group.cam_notifications
      tap_action:
        action: navigate
        navigation_path: '#notificationhistory'
      icon: |-
        {{ 'mdi:bell' if is_state('group.cam_notifications', 'on') else
        'mdi:bell-outline' }}
      card_mod:
        style: |
          ha-card {
            --chip-background: var(--nav-background) !important;
            background: var(--nav-background) !important;
            box-shadow: var(--ha-card-box-shadow) !important;
            border: none !important;
            position: relative !important;
            flex-shrink: 0 !important;
          }
          ha-card:active {
            transform: scale(0.92);
            transition: 0.1s;
          }
          ha-card::before {
            content: '';
            position: absolute;
            top: 0px;
            right: 0px; 
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background-color: var(--color-red) !important;
            display: {% if is_state('group.cam_notifications', 'off') %}block{% else %}none{% endif %};
            z-index: 2;
            box-shadow: 0 0 0 2px var(--nav-background);
          }
    - type: menu
      card_mod:
        style: |
          ha-card {
            --chip-background: var(--nav-background) !important;
            background: var(--nav-background) !important;
            box-shadow: var(--ha-card-box-shadow) !important;
            border: none !important;
            position: relative !important;
            flex-shrink: 0 !important;
          }
          ha-card:active {
            transform: scale(0.92);
            transition: 0.1s;
          }
    - type: template
      hold_action:
        action: navigate
        navigation_path: /lovelace/test
      tap_action:
        action: navigate
        navigation_path: '#settings'
      icon: |-
        {% set person = states.person | selectattr('state', 'eq', 'home') |
        selectattr('name', 'eq', user) | list | first | default(None) %} {%
        if person is not none %}
          mdi:account
        {% else %}
          mdi:account-alert
        {% endif %}
      picture: '{{ state_attr(''person.'' ~ user, ''entity_picture'') }}'
      card_mod:
        style: |
          ha-card {
            background: none !important;
            box-shadow: 0 4px 12px rgba(0,0,0,0.2) !important;
            border: 3px solid var(--accent-color) !important;
            padding: 0 !important;
            --chip-height: 54px !important; 
            width: 54px !important; 
            border-radius: 50% !important;
            margin-right: -4px !important; 
            flex-shrink: 0 !important;
            overflow: hidden !important;
          }
          ha-card:active {
            transform: scale(0.92);
            transition: 0.1s;
          }
          mushroom-shape-avatar, .picture, img, hui-image {
            width: 100% !important;
            height: 100% !important;
            margin: 0 !important;
            border-radius: 50% !important;
            object-fit: cover !important;
          }

Does the error show anything more in edit mode?

Nope, maybe it was a cache issue cuz strangley I just noticed it is working now randomly. If it breaks again I’ll tell you but the editor was actually just blank for this card only when it was broken btw.

1 Like