← Projects/Tutorials/CSS Animation 101
MyKeyZ Tutorial · Bewegung

CSS Animation 101

Alles bewegt sich, du entscheidest wie. Pure CSS, kein JavaScript, echter Wow-Effekt.

Einsteiger8 Kapitelca. 50 MinutenProjekt: animierte Profil-Card

Empfohlen nach CSS 101.

Kapitel 01

Transitions — sanfte Übergänge

BauplanWeich statt abrupt

transition macht den Wechsel zwischen zwei Zuständen flüssig.

Zustand A.btn, normal
Zustand B.btn:hover

Die Reihenfolge im Befehl: Eigenschaft, Dauer, Kurve, Verzögerung.

  • transition: background 0.3s ease
  • :hover

Der einfachste Einstieg in CSS-Motion: transition macht den Wechsel zwischen zwei Zuständen flüssig — statt abruptem Schnitt ein weiches Gleiten.

CSS
/* Ohne transition: abrupter Sprung */
.btn {
  background: #333;
}
.btn:hover {
  background: #fa5c7b;
}

/* Mit transition: sanfter Übergang */
.btn {
  background: #333;
  transition: background 0.3s ease;
  /*          ^Eigenschaft ^Dauer ^Kurve */
}
.btn:hover {
  background: #fa5c7b;
}

// Syntax

transition: [property] [duration] [timing-function] [delay]

transition: all 0.3s ease; — animiert ALLE änderbaren Eigenschaften
transition: color 0.2s, transform 0.4s ease-out; — mehrere, kommagetrennt

Was lässt sich per Transition animieren?

Fast alles Numerische: color, background, opacity, transform, width, height, padding, border-radius, box-shadow…

⚠ Performance

Animiere wenn möglich nur transform und opacity — diese laufen auf der GPU und sind butterweich. width, height, top, left triggern Layout-Neuberechnung = Ruckeln.

Kapitel 02

@keyframes — Animationen definieren

BauplanEine Choreographie in zwei Schritten

Zuerst mit @keyframes festlegen, was passiert. Dann mit animation einem Element zuweisen.

@keyframes meineFadewas bei 0 %, 50 %, 100 % passiert
CSS rechnet dazwischeninterpoliert den Rest
.elementanimation: meineFade 0.6s ease forwards
  • @keyframes
  • 0% 50% 100%
  • animation

Mit @keyframes definierst du eine Animations-Choreographie — du bestimmst was bei 0%, 50%, 100% passiert. CSS interpoliert den Rest automatisch.

CSS
/* 1. Animation definieren */
@keyframes meineFade {
  0%   { opacity: 0; transform: translateY(20px); }
  100% { opacity: 1; transform: translateY(0); }
}

/* 2. Animation anwenden */
.element {
  animation: meineFade 0.6s ease forwards;
  /*         ^Name     ^Dauer ^Kurve ^Endposition behalten */
}

Live-Demos: Die Grundbewegungen

fade
slide
spin
bounce
scale+rotate
CSS
/* Fade */
@keyframes fade { 0%,100% { opacity:1; } 50% { opacity:0.1; } }

/* Slide */
@keyframes slide { 0%,100% { transform: translateX(-30px); } 50% { transform: translateX(30px); } }

/* Spin */
@keyframes spin { to { transform: rotate(360deg); } }

/* Bounce */
@keyframes bounce {
  0%,100% { transform: translateY(0); }
  40%     { transform: translateY(-40px); }
  60%     { transform: translateY(-20px); }
}

/* Scale + Rotate */
@keyframes scaleRotate {
  0%,100% { transform: scale(1); }
  50%     { transform: scale(1.6) rotate(45deg); }
}

Kapitel 03

Animation Properties im Überblick

BauplanAcht Regler, eine Kurzform

Jede animation-…-Eigenschaft steuert einen Teil. Die Kurzform fasst sie zusammen.

was und wie lange
namewelche Keyframes
durationein Durchlauf
timing-functionKurve
wann und wie oft
delayVerzögerung
iteration-countinfinite
directionalternate
vorher, nachher, Pause
fill-modeforwards
play-statepaused
  • animation: name duration timing delay iteration direction fill-mode
Property Was sie macht Beispielwert
animation-name Welche @keyframes verwenden fadeIn
animation-duration Wie lange dauert ein Durchlauf 0.6s / 400ms
animation-timing-function Geschwindigkeitskurve ease / linear
animation-delay Verzögerung vor Start 0.2s
animation-iteration-count Wie oft wiederholen infinite / 3
animation-direction Richtung der Wiederholung normal / alternate
animation-fill-mode Zustand vor/nach Animation forwards / both
animation-play-state Pause/Play per CSS paused / running

// Shorthand

animation: name duration timing delay iteration direction fill-mode;

Beispiel: animation: fadeIn 0.5s ease 0.2s 1 normal forwards;

fill-mode — oft vergessen, immer wichtig

CSS
/* forwards = Element bleibt im Endzustand der Animation */
.card-einblenden {
  opacity: 0;
  animation: fadeInUp 0.6s ease forwards;
}
/* Ohne forwards: Element springt nach Ende wieder auf opacity:0 zurück! */

Kapitel 04

Timing Functions — die Seele der Animation

BauplanGleiche Strecke, anderes Gefühl

Die Timing Function bestimmt, wie sich eine Bewegung anfühlt.

BewegungWie soll sie wirken?
Wahl
linearmechanisch: Ladebalken, Spinner
ease-outkommt an: bremst sanft
ease-ingeht weg: wird schneller
steps(n)Sprünge: Pixel-Art, Typewriter
  • ease ease-in ease-out ease-in-out
  • cubic-bezier()
  • steps()

Die Timing Function entscheidet wie sich ein Objekt anfühlt. Gleiche Strecke, gleiche Zeit — aber komplett andere Wirkung:

Wert Charakter Ideal für
linear Konstante Geschwindigkeit, mechanisch Ladebalken, Spinner
ease Startet langsam, beschleunigt, bremst ab Allgemein, Default
ease-in Startet langsam, endet schnell Dinge die "weggehen"
ease-out Startet schnell, bremst sanft ab Dinge die "ankommen"
ease-in-out Wie ease, aber symmetrischer Loops, Hover-Effekte
cubic-bezier(x,y,x,y) Vollständige Kontrolle Bounce, Overshoot, Custom
steps(n) Sprünge statt Übergänge Pixel-Art, Typewriter
CSS
/* Bounce-Effekt via cubic-bezier */
animation: slideIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
/*                                   ↑ Wert > 1 = Overshoot = Federgefühl */

/* Typewriter via steps */
animation: typing 3s steps(30) infinite;

✅ Tipp

cubic-bezier.com — visueller Editor für eigene Kurven. Einfach reinspielen und den generierten Code kopieren!

Kapitel 05

Transform — bewegen, drehen, skalieren

BauplanBewegen, drehen, skalieren

transform ändert, wie ein Element aussieht, ohne das Layout zu verschieben.

translateverschieben
rotatedrehen
scalevergrössern, verkleinern

Die Reihenfolge zählt: translate rotate scale ergibt etwas anderes als scale rotate translate.

  • translateX translateY
  • rotate scale skewX

transform ist der beste Freund von CSS-Animationen — GPU-beschleunigt, kein Layout-Reflow, butterweich.

CSS
/* Verschieben */
transform: translateX(50px);
transform: translateY(-20px);
transform: translate(10px, -30px);

/* Skalieren */
transform: scale(1.5);       /* 150% Grösse */
transform: scaleX(2);        /* nur horizontal */

/* Drehen */
transform: rotate(45deg);
transform: rotate(-90deg);

/* Schräg stellen */
transform: skewX(15deg);

/* Kombinieren — Reihenfolge beachten! */
transform: translateY(-10px) rotate(5deg) scale(1.05);

⚠ Reihenfolge bei Transform!

translate rotate scale ≠ scale rotate translate — die Operationen beeinflussen sich gegenseitig. Als Faustregel: erst translate, dann rotate, dann scale.

transform-origin — Drehpunkt ändern

CSS
/* Standard: Mittelpunkt */
transform-origin: center;

/* Ecke als Drehpunkt (wie Kalender-Seite) */
transform-origin: top left;

/* Exakte Position */
transform-origin: 20px 80%;

Kapitel 06

Nützliche Animations-Patterns

BauplanBausteine zum Wiederverwenden

Bewährte Muster: kopieren, anpassen, kombinieren.

Muster
PulseAufmerksamkeit
TypewriterText erscheint
Staggernacheinander einblenden
Deine Seitemit eigenen Farben und Zeiten
  • @keyframes pulse-ring
  • steps()
  • animation-delay

Pulse — aufmerksamkeitsstarkes Pulsieren

pulse ring
Hello, World!
typewriter
stagger
CSS
/* PULSE RING */
@keyframes pulse-ring {
  0%   { box-shadow: 0 0 0 0 rgba(250,92,123,0.5); }
  70%  { box-shadow: 0 0 0 20px rgba(250,92,123,0); }
  100% { box-shadow: 0 0 0 0 rgba(250,92,123,0); }
}
.dot { animation: pulse-ring 1.5s ease-out infinite; }

/* TYPEWRITER */
@keyframes typing { 0%,5% { width:0 } 50%,95% { width: 200px } }
@keyframes blink  { 50% { border-color: transparent; } }
.text {
  overflow: hidden; white-space: nowrap;
  width: 0; border-right: 2px solid currentColor;
  animation: typing 3s steps(20) infinite, blink .7s step-end infinite;
}

/* STAGGER — Kinder verzögert einblenden */
.list-item { opacity: 0; animation: fadeIn 0.4s ease forwards; }
.list-item:nth-child(1) { animation-delay: 0.1s; }
.list-item:nth-child(2) { animation-delay: 0.2s; }
.list-item:nth-child(3) { animation-delay: 0.3s; }
/* ... oder mit CSS Custom Properties für n Elemente */

Hover-Lift — Card hebt sich beim Hover

CSS
.card {
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
  transform: translateY(-6px);
  box-shadow: 0 20px 40px rgba(0,0,0,0.3);
}

Shimmer / Skeleton Loading

CSS
@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position:  200% 0; }
}
.skeleton {
  background: linear-gradient(90deg,
    #1f1f23 25%, #2e2e35 50%, #1f1f23 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 6px;
}

Kapitel 07

PROJEKT: Deine animierte Profil-Card

BauplanProjekt: animierte Profil-Card

Fünf Effekte in einer Datei, nur CSS, ohne JavaScript.

animated-card.htmleine Datei
Effekte
EinblendenStagger beim Laden
AvatarPulse-Ring
HoverCard hebt sich, Button glänzt
Badgepulsiert dauerhaft
  • animated-card.html
  • Browser
MyFirst Animated Card

Du baust eine vollständig animierte Profil-Card — nur mit CSS, kein JavaScript. Page-Load Animation, Hover-Effekte, Pulse-Badge, alles.

  • Card blendet beim Laden ein (stagger)
  • Avatar mit Pulse-Ring-Animation
  • Hover hebt die Card an (lift)
  • Button mit Shine-Effekt beim Hover
  • Badge pulsiert dauerhaft

Erstelle eine Datei animated-card.html und füge den kompletten Code ein:

HTML
<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <title>Meine Animated Card</title>
  <style>
    /* ── RESET & BASE ── */
    * { margin:0; padding:0; box-sizing:border-box; }
    body {
      min-height: 100vh;
      background: #0a0a0f;
      display: flex;
      align-items: center;
      justify-content: center;
      font-family: system-ui, sans-serif;
    }

    /* ── EINBLEND-ANIMATION ── */
    @keyframes fadeUp {
      from { opacity: 0; transform: translateY(30px); }
      to   { opacity: 1; transform: translateY(0); }
    }

    /* ── CARD ── */
    .card {
      background: #18181b;
      border: 1px solid #2e2e35;
      border-radius: 20px;
      padding: 36px 32px;
      width: 300px;
      text-align: center;
      transition: transform 0.35s cubic-bezier(0.34,1.56,0.64,1),
                  box-shadow 0.35s ease;

      /* Stagger: Card selbst einblenden */
      opacity: 0;
      animation: fadeUp 0.6s ease 0.1s forwards;
    }
    .card:hover {
      transform: translateY(-10px);
      box-shadow: 0 30px 60px rgba(0,0,0,0.5);
    }

    /* ── AVATAR mit PULSE ── */
    @keyframes pulse-ring {
      0%   { box-shadow: 0 0 0 0 rgba(250,92,123,0.6); }
      70%  { box-shadow: 0 0 0 14px rgba(250,92,123,0); }
      100% { box-shadow: 0 0 0 0 rgba(250,92,123,0); }
    }
    .avatar-wrap {
      display: inline-block;
      margin-bottom: 20px;
      opacity: 0;
      animation: fadeUp 0.6s ease 0.25s forwards;
    }
    .avatar {
      width: 80px; height: 80px;
      border-radius: 50%;
      background: linear-gradient(135deg, #fa5c7b, #a78bfa);
      display: flex; align-items: center; justify-content: center;
      font-size: 2rem;
      animation: pulse-ring 2s ease-out infinite;
    }

    /* ── NAME & BIO ── */
    .name {
      font-size: 1.3rem;
      font-weight: 700;
      color: #f4f4f5;
      margin-bottom: 6px;
      opacity: 0;
      animation: fadeUp 0.6s ease 0.35s forwards;
    }
    .bio {
      font-size: 0.88rem;
      color: #71717a;
      margin-bottom: 20px;
      opacity: 0;
      animation: fadeUp 0.6s ease 0.45s forwards;
    }

    /* ── BADGE ── */
    @keyframes badge-pulse {
      0%,100% { opacity: 1; }
      50%     { opacity: 0.5; }
    }
    .badge {
      display: inline-flex; align-items: center; gap: 6px;
      background: rgba(250,92,123,0.15);
      border: 1px solid rgba(250,92,123,0.4);
      color: #fa5c7b;
      padding: 4px 12px;
      border-radius: 50px;
      font-size: 0.78rem;
      margin-bottom: 24px;
      opacity: 0;
      animation: fadeUp 0.6s ease 0.5s forwards;
    }
    .badge-dot {
      width: 6px; height: 6px;
      background: #fa5c7b;
      border-radius: 50%;
      animation: badge-pulse 1.2s ease infinite;
    }

    /* ── BUTTON mit SHINE ── */
    @keyframes shine {
      from { left: -100%; }
      to   { left: 150%; }
    }
    .btn {
      display: block;
      background: #fa5c7b;
      color: #fff;
      border: none;
      padding: 12px 28px;
      border-radius: 10px;
      font-size: 0.9rem;
      font-weight: 600;
      cursor: pointer;
      position: relative;
      overflow: hidden;
      transition: transform 0.2s ease, background 0.2s;
      opacity: 0;
      animation: fadeUp 0.6s ease 0.6s forwards;
    }
    .btn::after {
      content: '';
      position: absolute;
      top: -50%; left: -100%;
      width: 60%; height: 200%;
      background: rgba(255,255,255,0.25);
      transform: skewX(-20deg);
      transition: none;
    }
    .btn:hover::after {
      animation: shine 0.5s ease;
    }
    .btn:hover {
      background: #e04460;
      transform: scale(1.03);
    }

    /* ── STATS ── */
    .stats {
      display: flex;
      justify-content: space-around;
      margin-top: 24px;
      padding-top: 20px;
      border-top: 1px solid #2e2e35;
      opacity: 0;
      animation: fadeUp 0.6s ease 0.7s forwards;
    }
    .stat-value { font-size: 1.2rem; font-weight: 700; color: #f4f4f5; }
    .stat-label { font-size: 0.72rem; color: #71717a; margin-top: 2px; }
  </style>
</head>
<body>

  <div class="card">

    <div class="avatar-wrap">
      <div class="avatar">🚀</div>
    </div>

    <div class="name">Dein Name</div>
    <div class="bio">CSS Animator · Creative Coder</div>

    <div class="badge">
      <span class="badge-dot"></span>
      Online
    </div>

    <button class="btn">Profil ansehen →</button>

    <div class="stats">
      <div>
        <div class="stat-value">42</div>
        <div class="stat-label">Projekte</div>
      </div>
      <div>
        <div class="stat-value">128</div>
        <div class="stat-label">Followers</div>
      </div>
      <div>
        <div class="stat-value">7</div>
        <div class="stat-label">Awards</div>
      </div>
    </div>

  </div>

</body>
</html>

Das Aha-Moment

Öffne die Datei im Browser — jedes Element blendet mit Verzögerung ein, der Avatar pulsiert, die Card hebt sich beim Hover, der Button leuchtet auf. Alles pure CSS, zero JavaScript. Das ist die Kraft von @keyframes + transitions kombiniert!

Bonus-Challenges

Wenn du Lust hast, probiere diese Erweiterungen:

Kapitel 08

Cheatsheet

BauplanWelches Werkzeug wann?

Der Spickzettel unten, als Wegweiser.

Deine BewegungWas soll passieren?
Antwort
Bei Hover von A nach Btransition
Eigener Ablauf, auch ohne Hover@keyframes + animation
Position, Drehung, Grössetransform

Transitions

transition: all .3s ease
Alles animieren
transition: color .2s, transform .4s
Mehrere Properties
transition: transform .3s ease-out
Nur transform (GPU)

@keyframes Grundmuster

from {} to {}
Einfacher A→B Übergang
0% {} 50% {} 100% {}
Mehrere Zwischenpunkte

animation Shorthand

animation: name .6s ease forwards
Einmalig, Endzustand halten
animation: spin 1s linear infinite
Endlos drehen
animation: pulse 2s ease-out infinite
Endlos pulsieren
animation-delay: .2s
Verzögerung
animation-direction: alternate
Hin und zurück
animation-play-state: paused
Pause via CSS/JS

Transform-Toolbox

translateX/Y(px)
Verschieben (GPU!)
scale(1.5)
Skalieren (GPU!)
rotate(45deg)
Drehen
skewX(15deg)
Schräg stellen