Glassmorphism in Home Assistant — Das CSS, das wirklich funktioniert

Die sechs CSS-Konstanten, die ich auf allen Karten in drei HA-Dashboards verwende, plus Muster für Fortschrittsbalken, Kartenkarten und die Unterdrückung des ::before-Overlays im Frosted Glass Dark Theme.

#dashboard #design #card-mod #lovelace #home-assistant
13. Dezember 2024
Glassmorphism in Home Assistant — Das CSS, das wirklich funktioniert

Ich habe meine Home Assistant-Dashboards dreimal neu gebaut, bevor sie so aussahen, als würden sie zusammengehören. Die erste Version waren flache Karten. Okay. Die zweite hatte zu viele Farben. Die dritte landete bei Glassmorphism — halbtransparente Karten auf tiefem Marineblau — und die habe ich seitdem nicht mehr angetastet.

Was folgt ist das genaue CSS, mit Erklärungen zu den Stellen, die mich stolpern ließen.

Home Assistant Dashboard mit Glassmorphism-Karten auf dunkelblauem Hintergrund

Die sechs CSS-Konstanten für jede Glassmorphism-Karte

Jede äußere Karte verwendet exakt diese Werte. Keine Abweichung.

border-radius: 28px;
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(15px);
-webkit-backdrop-filter: blur(15px);
border: 1px solid rgba(255, 255, 255, 0.10);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);

Und die Zeile, die man verpasst, wenn niemand es einem sagt:

ha-card::before { display: none !important; }

Das Frosted Glass Dark Theme (im HACS unter Themes verfügbar, und mehrere ähnliche) injiziert ein ::before-Overlay auf jede ha-card. Unterdrückt man es nicht, liegt ein halbtransparentes Layer über dem eigenen Hintergrund. Das Symptom: die Karten sehen leicht falsch aus — leicht zu undurchsichtig, leicht in der Farbe verändert — und man findet nicht heraus warum. Ich suchte eine Weile an der falschen Stelle, bevor ich darauf kam.

Die äußere Karten-Vorlage

type: custom:stack-in-card
card_mod:
  style: |
    ha-card {
      background: rgba(255,255,255,0.05) !important;
      backdrop-filter: blur(15px) !important;
      -webkit-backdrop-filter: blur(15px) !important;
      border: 1px solid rgba(255,255,255,0.10) !important;
      box-shadow: 0 8px 32px rgba(0,0,0,0.3) !important;
      border-radius: 28px !important;
    }
    ha-card::before { display: none !important; }
cards:
  # Inhalt hier

custom:stack-in-card (HACS) ist die Umhüllung — card_mod (HACS) liefert die CSS-Injektion. Alle visuellen Styles leben hier. Innere Karten bekommen nichts davon.

Innere Karten — nur Transparenz

In die Glasumhüllung verschachtelte Karten sollen visuell verschwinden:

card_mod:
  style: |
    ha-card {
      background: transparent !important;
      box-shadow: none !important;
      border: none !important;
    }
    ha-card::before { display: none !important; }

Die ::before-Unterdrückung wird auch auf inneren Karten gebraucht. Das Theme wendet es überall an.

Zwischen inneren Karten nutze ich eine schwache Trennlinie:

border-bottom: 1px solid rgba(255, 255, 255, 0.06) !important;

Heller als man erwarten würde. Ist sie zu sichtbar, schneidet sie die Glasoberfläche. Bei 0,06 Deckkraft liest sie sich als Abschnittsbruch ohne Aufmerksamkeit zu erregen.

Fortschrittsbalken via ::after

::before ist für Theme-Unterdrückung belegt. ::after gehört dem Inhalt.

card_mod:
  style: |
    ha-card {
      overflow: hidden !important;
      position: relative !important;
    }
    ha-card::before { display: none !important; }
    ha-card::after {
      content: '' !important;
      position: absolute !important;
      left: 0; top: 0;
      width: {{ states('sensor.batteriestand') | int(0) }}% !important;
      height: 100% !important;
      background: linear-gradient(90deg,
        rgba(76, 175, 80, 0.18),
        rgba(129, 199, 132, 0.05)) !important;
      pointer-events: none !important;
    }

Der Verlauf verblasst nach rechts, sodass eine Karte bei 30% anders aussieht als eine bei 80% — auf eine Weise, die intuitiv lesbar ist. Ich verwende das für EV-Akku, Staubsauger-Akku und Mäher-Akku. Bei Wartungssensoren invertiere ich die Farblogik — nahe 0% bedeutet Warnung, also roter Verlauf.

Kartenkarten

Kartenkarten haben eigene Rendering-Regeln. Steckt man eine direkt in einen Glas-stack-in-card ohne Anpassung, stehen die quadratischen Ecken aus der abgerundeten Umhüllung heraus.

Die Lösung: overflow: hidden auf der äußeren Karte, border-radius: 0 auf der inneren Kartenkarte. Das Overflow des äußeren Containers übernimmt das Clipping.

type: custom:stack-in-card
card_mod:
  style: |
    ha-card {
      /* Standard-Glaswerte */
      overflow: hidden !important;
    }
    ha-card::before { display: none !important; }
cards:
  - type: custom:xiaomi-vacuum-map-card  # HACS
    entity: vacuum.robot
    card_mod:
      style: |
        ha-card {
          border-radius: 0 !important;
          box-shadow: none !important;
          border: none !important;
        }

Badge-Unterdrückung

Mushroom-Karten zeigen farbige Badges bei bestimmten Zuständen — das orange “nicht verfügbar” Badge bei einem offline Gerät ist der häufigste Störenfried.

card_mod:
  style:
    ".": |
      mushroom-badge-icon.unavailable {
        display: none !important;
      }

Der "."-Schlüssel ist der richtige für Mushroom-Karten in HA 2024+. Nicht ha-card, nicht der Komponentenname — ".". Ich testete deutlich zu viele andere Selektoren, bevor dieser funktionierte.

Visuelle Konsistenz in HA-Dashboards erreichen

YAML hat keine Variablen. Jede Karte mit Glasbehandlung bekommt ihre eigene Kopie der sechs CSS-Zeilen. Will man die Hintergrund-Deckkraft im ganzen Dashboard anpassen, ändert man sie an 25 Stellen.

Mein Workaround: eine lokale snippets.yaml-Datei mit der vollständigen äußeren Karten-Vorlage als Kommentarblock. Beim Erstellen neuer Karten von dort einfügen. Nicht elegant, aber wartbar.

Die richtige Lösung wären CSS Custom Properties im Theme — var(--glass-bg) einmal definiert, überall referenziert. Das funktioniert heute, wenn das Theme sie definiert. Diesen Schritt habe ich noch nicht gemacht.