DEV Community

Nevik Schmidt
Nevik Schmidt

Posted on

CSS Glassmorphism + Animated Mesh Gradient: So baust du moderne Hero-Sections

CSS Glassmorphism + Animated Mesh Gradient: So baust du moderne Hero-Sections

Eine Hero-Section ist der erste Eindruck, den Besucher von deiner Website bekommen. Wenn sie langweilig aussieht, springen Nutzer ab, bevor sie überhaupt den Scroll-Down-Animationen eine Chance geben. In diesem Tutorial zeige ich dir, wie du mit reinem CSS eine moderne, beeindruckende Hero-Section mit Glassmorphism und animiertem Mesh-Gradient baust — genau das Design-System, das ich auf strom.nevik.de einsetze.

👉 Live-Beispiel ansehen: strom.nevik.de


Das Endziel

Bevor wir in den Code gehen, hier was wir bauen:

  • Einen animierten Mesh-Gradient als Hintergrund, der sanft fließt und pulsiert
  • Eine Glassmorphism-Karte im Vordergrund, die wie geschliffenes Glas wirkt
  • Scroll-Reveal-Animationen, die Inhalte beim Scrollen einblenden
  • Responsives Layout, das auf Mobilgeräten genauso gut aussieht

Keine JavaScript-Animations-Library, keine Build-Tools. Nur modernes CSS.


Teil 1: Der animierte Mesh-Gradient-Hintergrund

Klassische CSS-Gradients sind linear oder radial — das sieht schnell flach aus. Ein Mesh-Gradient kombiniert mehrere Radial-Gradients zu einem fließenden, organischen Muster. Den kennst du vielleicht von Apple's Marketing-Seiten oder Stripe.com.

Die Herausforderung: CSS hat keinen nativen Mesh-Gradient (noch nicht flächendeckend). Aber wir können ihn mit gestapelten Radial-Gradients und Animationen simulieren.

HTML-Struktur

<div class="hero">
  <div class="mesh-gradient"></div>

  <div class="hero-content">
    <div class="glass-card">
      <h1>Strompreis in Echtzeit</h1>
      <p>Transparente Daten für Deutschland</p>
      <a href="#calculator" class="cta-button">Jetzt berechnen</a>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

CSS: Der Mesh-Gradient

.mesh-gradient {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  z-index: 0;

  /* Drei gestapelte Radial-Gradients = Mesh-Effekt */
  background: 
    radial-gradient(
      circle at 20% 30%,
      rgba(99, 102, 241, 0.55) 0%,
      transparent 50%
    ),
    radial-gradient(
      circle at 80% 20%,
      rgba(236, 72, 153, 0.45) 0%,
      transparent 50%
    ),
    radial-gradient(
      circle at 50% 80%,
      rgba(34, 211, 238, 0.5) 0%,
      transparent 50%
    );

  background-color: #0f172a; /* dunkler Base-Layer */
  animation: meshFlow 18s ease-in-out infinite;
}

@keyframes meshFlow {
  0%, 100% {
    transform: scale(1) rotate(0deg);
  }
  33% {
    transform: scale(1.1) rotate(2deg);
  }
  66% {
    transform: scale(1.05) rotate(-2deg);
  }
}

/* Mesh-Pulse-Overlay für zusätzliche Tiefe */
.mesh-gradient::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: radial-gradient(
    circle at var(--mouse-x, 50%) var(--mouse-y, 50%),
    rgba(255, 255, 255, 0.08) 0%,
    transparent 40%
  );
  animation: pulse 6s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 0.6; }
  50% { opacity: 1; }
}
Enter fullscreen mode Exit fullscreen mode

Der Trick ist, drei Radial-Gradients mit unterschiedlichen Positionen und Farben zu kombinieren. Die @keyframes-Animation verschiebt die Positionen sanft, wodurch ein fließender, organischer Eindruck entsteht.

Wichtig: Die background-color als dunkler Base-Layer ist entscheidend — ohne sie sehen die radialen Lichtpunkte auf weißem Hintergrund schwach aus.


Teil 2: Die Glassmorphism-Karte

Glassmorphism ist ein Design-Trend, der seit 2020 überall auftaucht — von macOS Big Sur bis zu iOS. Die Illusion von "frosted glass" entsteht durch drei CSS-Eigenschaften:

  1. backdrop-filter: blur() — der wichtigste Teil
  2. Halbtransparenter Hintergrundrgba() mit niedrigem Alpha-Wert
  3. Subtiler Rand — ein heller, halbtransparenter Rahmen

CSS für die Glass-Karte

.glass-card {
  position: relative;
  z-index: 2;

  padding: 3rem 2.5rem;
  border-radius: 24px;
  max-width: 600px;

  /* Glassmorphism-Kern */
  background: rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);

  /* Gläserner Rand */
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: 
    0 8px 32px rgba(0, 0, 0, 0.3),
    inset 0 1px 0 rgba(255, 255, 255, 0.15);
}

/* Glanz-Effekt oben links (wie echte Glasreflexion) */
.glass-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 50%;
  border-radius: 24px 24px 0 0;
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.15) 0%,
    transparent 60%
  );
  pointer-events: none;
}

.glass-card h1 {
  color: #ffffff;
  font-size: clamp(2rem, 5vw, 3.5rem);
  font-weight: 700;
  margin-bottom: 1rem;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.glass-card p {
  color: rgba(255, 255, 255, 0.8);
  font-size: clamp(1rem, 2.5vw, 1.25rem);
  margin-bottom: 2rem;
  line-height: 1.6;
}
Enter fullscreen mode Exit fullscreen mode

Warum backdrop-filter: saturate(180%)?

Nur blur() allein lässt das Glas oft grau und matschig wirken. Die zusätzliche saturate()-Erhöhung verstärkt die Farben dahinter — das Glas wirkt lebendiger und edler. Das ist ein Detail, das viele Glassmorphism-Tutorials vergessen.


Teil 3: Die CTA-Button mit Hover-Effekten

Ein guter CTA-Button muss sich "klickbar" anfühlen. Das erreichen wir mit einem Glow-Effekt und sanften Übergängen.

.cta-button {
  display: inline-block;
  padding: 1rem 2.5rem;
  border-radius: 999px;

  background: linear-gradient(
    135deg,
    #6366f1 0%,
    #ec4899 100%
  );
  color: white;
  font-weight: 600;
  font-size: 1.125rem;
  text-decoration: none;
  letter-spacing: 0.02em;

  border: none;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

  /* Glow */
  box-shadow: 
    0 4px 20px rgba(99, 102, 241, 0.5),
    0 0 0 0 rgba(99, 102, 241, 0.7);
}

.cta-button:hover {
  transform: translateY(-2px);
  box-shadow: 
    0 8px 30px rgba(99, 102, 241, 0.6),
    0 0 0 4px rgba(99, 102, 241, 0.2);
}

.cta-button:active {
  transform: translateY(0);
}

/* Für Tastatur-Nutzer: sichtbarer Focus-Ring */
.cta-button:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 4px;
}
Enter fullscreen mode Exit fullscreen mode

Die box-shadow mit 0 0 0 0 rgba(...) beim Default-State wird beim Hover zu 0 0 0 4px rgba(...). Das erzeugt den typischen "Ausstrahlungs"-Effekt.


Teil 4: Scroll-Reveal-Animationen

Inhalte sollten nicht einfach da sein — sie sollten erscheinen, wenn der Nutzer sie sieht. Das nennt man "Scroll Reveal". Und das geht ohne JavaScript-Library, mit der modernen Intersection Observer API.

HTML vorbereiten

<section class="feature reveal">
  <h2>Echtzeit-Daten</h2>
  <p>...</p>
</section>

<section class="feature reveal">
  <h2>Vollständige Transparenz</h2>
  <p>...</p>
</section>
Enter fullscreen mode Exit fullscreen mode

CSS: Der Hidden-State

.reveal {
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 0.8s ease, transform 0.8s ease;
}

.reveal.visible {
  opacity: 1;
  transform: translateY(0);
}
Enter fullscreen mode Exit fullscreen mode

JavaScript: Intersection Observer

Das ist das einzige JavaScript, das wir brauchen — und es sind nur 15 Zeilen:

const observer = new IntersectionObserver(
  (entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        entry.target.classList.add('visible');
        observer.unobserve(entry.target); // nur einmal animieren
      }
    });
  },
  {
    threshold: 0.15, // bei 15% Sichtbarkeit auslösen
    rootMargin: '0px 0px -50px 0px' // etwas früher auslösen
  }
);

document.querySelectorAll('.reveal').forEach((el) => {
  observer.observe(el);
});
Enter fullscreen mode Exit fullscreen mode

Die Magie: threshold: 0.15 bedeutet, dass die Animation startet, wenn 15% des Elements sichtbar sind — also etwas bevor es vollständig im Viewport ist. Das fühlt sich natürlicher an.


Teil 5: Responsivität ohne Media-Query-Wahnsinn

Anstatt dutzende Media Queries zu schreiben, nutzen wir moderne CSS-Features, die sich automatisch anpassen.

Fluid Typography mit clamp()

.glass-card h1 {
  font-size: clamp(2rem, 5vw, 3.5rem);
}

.glass-card p {
  font-size: clamp(1rem, 2.5vw, 1.25rem);
}
Enter fullscreen mode Exit fullscreen mode

clamp(min, preferred, max) skaliert die Schriftgröße fließend zwischen Mindest- und Maximalwert, basierend auf der Viewport-Breite. Keine Media Queries nötig.

Container Queries für echte Komponenten-Responsivität

.hero-content {
  container-type: inline-size;
}

@container (min-width: 600px) {
  .glass-card {
    padding: 4rem 3.5rem;
  }
}
Enter fullscreen mode Exit fullscreen mode

Container Queries reagieren auf die Größe des Containers, nicht des Viewports. Das ist ein Game-Changer für wiederverwendbare Komponenten.


Teil 6: Performance und Browser-Support

So schön Glassmorphism aussieht — es kann Performance-Probleme verursachen. Hier sind die wichtigen Punkte:

1. will-change für komplexe Animationen

.mesh-gradient {
  will-change: transform, background-position;
}
Enter fullscreen mode Exit fullscreen mode

Das sagt dem Browser: "Diese Eigenschaften werden sich ändern, bereite dich vor." Der Browser lagert die Rendering-Schicht auf die GPU aus.

2. prefers-reduced-motion respektieren

Nicht jeder möchte Animationen. Respektiere die Systemeinstellung:

@media (prefers-reduced-motion: reduce) {
  .mesh-gradient,
  .mesh-gradient::before,
  .cta-button {
    animation: none;
    transition: none;
  }

  .reveal {
    opacity: 1;
    transform: none;
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Browser-Support für backdrop-filter

backdrop-filter wird von allen modernen Browsern unterstützt, aber Safari benötigt den -webkit--Präfix. Für ältere Browser (die es nicht unterstützen) sollte der Hintergrund nicht komplett transparent sein — sonst ist der Text unleserlich.

.glass-card {
  /* Fallback für Browser ohne backdrop-filter */
  background: rgba(255, 255, 255, 0.15);

  /* Progressive Enhancement */
  @supports (backdrop-filter: blur(20px)) {
    background: rgba(255, 255, 255, 0.08);
    backdrop-filter: blur(20px) saturate(180%);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
  }
}
Enter fullscreen mode Exit fullscreen mode

Das vollständige Design-System

Alle Snippets zusammen ergeben das Design-System, das ich auf strom.nevik.de einsetze:

Komponente CSS-Technik
Hintergrund Animierter Mesh-Gradient (3 Radial-Gradients + keyframes)
Karten Glassmorphism (backdrop-filter + saturate + Glanz-Overlay)
Buttons Gradient + Glow-Shadow + translateY-Hover
Animationen Intersection Observer + CSS-Transitions
Typografie Fluid clamp()-Schriftgrößen
Responsivität Container Queries + Media Queries (Fallback)
Accessibility prefers-reduced-motion, focus-visible

Color Palettes für verschiedene Stimmungen

Das Mesh-Gradient-Konzept funktioniert mit jeder Farbpalette. Hier sind drei Varianten, die du direkt übernehmen kannst:

Cyberpunk (lila / pink / cyan)

--mesh-1: rgba(99, 102, 241, 0.55);   /* Indigo */
--mesh-2: rgba(236, 72, 153, 0.45);   /* Pink */
--mesh-3: rgba(34, 211, 238, 0.5);    /* Cyan */
--base: #0f172a;                       /* Dark Slate */
Enter fullscreen mode Exit fullscreen mode

Sunset (orange / rot / lila)

--mesh-1: rgba(251, 146, 60, 0.5);    /* Orange */
--mesh-2: rgba(239, 68, 68, 0.45);    /* Red */
--mesh-3: rgba(168, 85, 247, 0.4);    /* Purple */
--base: #1e1b4b;                       /* Indigo Dark */
Enter fullscreen mode Exit fullscreen mode

Ocean (blau / türkis / grün)

--mesh-1: rgba(59, 130, 246, 0.5);    /* Blue */
--mesh-2: rgba(20, 184, 166, 0.45);   /* Teal */
--mesh-3: rgba(16, 185, 129, 0.4);    /* Green */
--base: #0c4a6e;                       /* Sky Dark */
Enter fullscreen mode Exit fullscreen mode

Wechsle einfach die CSS Custom Properties aus, und deine Hero-Section hat sofort eine andere Stimmung — ohne die Struktur zu ändern.


Maus-Tracking: Der interaktive Glow

Ein weiteres Detail, das die Hero-Section von strom.nevik.de besonders macht: Der Hintergrund-Glow folgt dem Mauszeiger. Das geht mit nur 10 Zeilen JavaScript:

const mesh = document.querySelector('.mesh-gradient');

document.addEventListener('mousemove', (e) => {
  const x = (e.clientX / window.innerWidth) * 100;
  const y = (e.clientY / window.innerHeight) * 100;

  mesh.style.setProperty('--mouse-x', `${x}%`);
  mesh.style.setProperty('--mouse-y', `${y}%`);
});
Enter fullscreen mode Exit fullscreen mode

Die CSS-Variablen --mouse-x und --mouse-y, die wir bereits im ::before-Pseudo-Element definiert haben, steuern die Position des radialen Highlights. Ein winziges Detail, das die Seite lebendig wirken lässt.


Der komplette Code

Hier ist die Zusammenfassung aller Bausteine als Copy-Paste-Vorlage:

<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Modern Hero Section</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }

    body {
      font-family: system-ui, -apple-system, sans-serif;
      background: #0f172a;
      color: #fff;
      min-height: 100vh;
    }

    .hero {
      position: relative;
      min-height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 2rem;
    }

    .mesh-gradient {
      position: absolute;
      inset: 0;
      z-index: 0;
      background:
        radial-gradient(circle at 20% 30%, rgba(99, 102, 241, 0.55), transparent 50%),
        radial-gradient(circle at 80% 20%, rgba(236, 72, 153, 0.45), transparent 50%),
        radial-gradient(circle at 50% 80%, rgba(34, 211, 238, 0.5), transparent 50%);
      background-color: #0f172a;
      animation: meshFlow 18s ease-in-out infinite;
    }

    @keyframes meshFlow {
      0%, 100% { transform: scale(1) rotate(0deg); }
      33% { transform: scale(1.1) rotate(2deg); }
      66% { transform: scale(1.05) rotate(-2deg); }
    }

    .glass-card {
      position: relative;
      z-index: 2;
      padding: 3rem 2.5rem;
      border-radius: 24px;
      max-width: 600px;
      background: rgba(255, 255, 255, 0.08);
      backdrop-filter: blur(20px) saturate(180%);
      -webkit-backdrop-filter: blur(20px) saturate(180%);
      border: 1px solid rgba(255, 255, 255, 0.18);
      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
      text-align: center;
    }

    .glass-card h1 {
      font-size: clamp(2rem, 5vw, 3.5rem);
      margin-bottom: 1rem;
      letter-spacing: -0.02em;
    }

    .cta-button {
      display: inline-block;
      margin-top: 1.5rem;
      padding: 1rem 2.5rem;
      border-radius: 999px;
      background: linear-gradient(135deg, #6366f1, #ec4899);
      color: white;
      font-weight: 600;
      text-decoration: none;
      transition: transform 0.3s, box-shadow 0.3s;
      box-shadow: 0 4px 20px rgba(99, 102, 241, 0.5);
    }

    .cta-button:hover {
      transform: translateY(-2px);
      box-shadow: 0 8px 30px rgba(99, 102, 241, 0.6);
    }
  </style>
</head>
<body>
  <div class="hero">
    <div class="mesh-gradient"></div>
    <div class="glass-card">
      <h1>Strompreis in Echtzeit</h1>
      <p>Transparente Daten für Deutschland</p>
      <a href="#" class="cta-button">Jetzt berechnen</a>
    </div>
  </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Speichere das als .html-Datei und öffne es im Browser. Du hast sofort eine moderne, beeindruckende Hero-Section — ohne jegliche Build-Tools oder Dependencies.


Accessibility nicht vergessen

Eine schöne Website, die niemand bedienen kann, ist wertlos. Achte auf diese Punkte:

  • Kontrast: Der Text auf der Glass-Karte muss mindestens WCAG AA (4.5:1) Kontrast haben. Auf dunklem Mesh-Background ist weißer Text meistens sicher.
  • Fokus-Indikatoren: Nutze :focus-visible für sichtbare Tastatur-Navigation (wie im CTA-Button oben gezeigt).
  • prefers-reduced-motion: Respektiere Nutzer, die keine Animationen möchten (oben implementiert).
  • Semantisches HTML: <section>, <h1>, <a> statt div-Suppe — gut für Screenreader und SEO.

Fazit

Moderne Hero-Sections brauchen keine schweren JavaScript-Frameworks. Mit reinem CSS und ein paar cleveren Techniken erreichst du beeindruckende Ergebnisse:

  • Mesh-Gradient: Gestapelte Radial-Gradients + Keyframe-Animation
  • Glassmorphism: backdrop-filter: blur() saturate() + halbtransparenter Rand
  • Scroll Reveal: Intersection Observer + CSS-Transitions
  • Fluid Typography: clamp() statt Media Queries
  • Interaktivität: Maus-Tracking über CSS Custom Properties

Das gesamte Design-System läuft in jedem modernen Browser, ohne Dependencies und ohne Build-Tools. Schau dir das Live-Beispiel an, um den Effekt in Aktion zu sehen:

🔗 Live-Demo: strom.nevik.de

🔗 Strompreis-Rechner mit dem Design

Kopiere die Code-Snippets, passe die Farben an dein Branding an und baue deine eigene beeindruckende Hero-Section. Wenn du Fragen hast oder deine Version zeigen willst, schreib gerne einen Kommentar!

Top comments (0)