Kategorie
Icons
Eigene Inline-SVG-Icons — keine Icon-Fonts, keine externen Dateien, kein CDN.
Alle nutzen currentColor, erben also Text-/Akzentfarbe, und skalieren über
width/height. Einheitlicher Linien-Stil
(viewBox 0 0 24 24, stroke-width 2, runde Enden).
Statisches Icon-Set (Linien)
Pol 2 · Klarheit
Anlass: Navigation, Kontakt, UI-Beschriftung
16 saubere Linien-Icons in einem Stil. Jedes ist Inline-SVG mit
stroke="currentColor" — Farbe steuert man über color bzw.
--akzent, die Größe über width/height. Eigenbau,
keine fremde Vorlage.
menu
close
chevron-down
arrow-right
check
phone
mail
map-pin
whatsapp
user
calendar
clock
search
external-link
star
info
<!-- Alle Icons: viewBox 0 0 24 24, stroke="currentColor", stroke-width 2, runde Enden. -->
<!-- Farbe via CSS color/--akzent, Größe via width/height am <svg>. -->
<!-- menu -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/>
</svg>
<!-- close -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/>
</svg>
<!-- chevron-down -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<polyline points="6 9 12 15 18 9"/>
</svg>
<!-- arrow-right -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<line x1="4" y1="12" x2="20" y2="12"/><polyline points="13 5 20 12 13 19"/>
</svg>
<!-- check -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<polyline points="4 12 10 18 20 6"/>
</svg>
<!-- phone -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<path d="M6.5 3h3l1.5 4-2 1.5a12 12 0 0 0 5 5l1.5-2 4 1.5v3a2 2 0 0 1-2.2 2A16 16 0 0 1 4.5 5.2 2 2 0 0 1 6.5 3z"/>
</svg>
<!-- mail -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<rect x="3" y="5" width="18" height="14" rx="2"/><polyline points="3 7 12 13 21 7"/>
</svg>
<!-- map-pin -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<path d="M12 21s-7-6.3-7-11a7 7 0 0 1 14 0c0 4.7-7 11-7 11z"/><circle cx="12" cy="10" r="2.5"/>
</svg>
<!-- whatsapp -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<path d="M3.5 20.5l1.4-4.3A8 8 0 1 1 8.3 19l-4.8 1.5z"/>
<path d="M8.8 9.4c.2-.5.4-.5.7-.5h.6c.2 0 .5 0 .7.5l.7 1.6c.1.3 0 .5-.1.7l-.5.6c-.2.2-.3.4-.1.7a6 6 0 0 0 2.6 2.3c.3.2.5.1.7-.1l.6-.7c.2-.2.4-.2.7-.1l1.6.8c.3.1.4.3.4.6 0 .8-.6 1.6-1.4 1.8-.7.2-1.6.2-3.6-.8a9 9 0 0 1-3.8-3.8c-.9-1.8-.8-2.7-.5-3.4z"/>
</svg>
<!-- user -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<circle cx="12" cy="8" r="4"/><path d="M4 21v-1a6 6 0 0 1 6-6h4a6 6 0 0 1 6 6v1"/>
</svg>
<!-- calendar -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<rect x="3" y="5" width="18" height="16" rx="2"/><line x1="3" y1="9" x2="21" y2="9"/>
<line x1="8" y1="3" x2="8" y2="6"/><line x1="16" y1="3" x2="16" y2="6"/>
</svg>
<!-- clock -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 16 14"/>
</svg>
<!-- search -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<circle cx="11" cy="11" r="7"/><line x1="16" y1="16" x2="21" y2="21"/>
</svg>
<!-- external-link -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<path d="M14 4h6v6"/><line x1="20" y1="4" x2="11" y2="13"/>
<path d="M18 14v4a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4"/>
</svg>
<!-- star -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<polygon points="12 3 14.6 8.5 20.5 9.3 16.2 13.4 17.3 19.3 12 16.5 6.7 19.3 7.8 13.4 3.5 9.3 9.4 8.5 12 3"/>
</svg>
<!-- info -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24">
<circle cx="12" cy="12" r="9"/><line x1="12" y1="11" x2="12" y2="16"/><line x1="12" y1="8" x2="12" y2="8"/>
</svg>
Hamburger → X-Morph
Pol 1 · Craft
Anlass: Mobile-Menü-Schalter
Drei Striche, die per .open zum X morphen — nur
transform/opacity. Klick schaltet um; reagiert auch auf
Tastatur-Fokus. aria-expanded wird mitgeführt.
<button class="fx-burger" type="button" aria-label="Menü öffnen" aria-expanded="false">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
<line class="bar top" x1="4" y1="7" x2="20" y2="7"/>
<line class="bar mid" x1="4" y1="12" x2="20" y2="12"/>
<line class="bar bot" x1="4" y1="17" x2="20" y2="17"/>
</svg>
</button>
<style>
.fx-burger{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:#f4f4f5}
.fx-burger:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-burger svg{width:22px;height:22px}
.fx-burger .bar{transition:transform .3s ease,opacity .2s ease;transform-origin:center}
.fx-burger.open .top{transform:translateY(5px) rotate(45deg)}
.fx-burger.open .mid{opacity:0}
.fx-burger.open .bot{transform:translateY(-5px) rotate(-45deg)}
@media (prefers-reduced-motion:reduce){.fx-burger .bar{transition:none}}
</style>
<script>
document.querySelector('.fx-burger').addEventListener('click', (e) => {
const b = e.currentTarget;
const open = b.classList.toggle('open');
b.setAttribute('aria-expanded', open);
b.setAttribute('aria-label', open ? 'Menü schließen' : 'Menü öffnen');
});
</script>
Spinner (Lade-Anzeige)
Pol 1 · Craft
Anlass: Ladezustand, Buttons
Ein gedämpfter Ring plus ein rotierender Bogen. Dreht endlos über
transform:rotate; bei reduzierter Bewegung steht er still.
<svg class="fx-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" role="img" aria-label="Lädt">
<circle class="track" cx="12" cy="12" r="9"/>
<path class="arc" d="M21 12a9 9 0 0 0-9-9"/>
</svg>
<style>
.fx-spin{width:26px;height:26px;color:var(--akzent,#7c87ff)}
.fx-spin .track{opacity:.2}
.fx-spin .arc{transform-origin:center;animation:fxSpin 1s linear infinite}
@keyframes fxSpin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.fx-spin .arc{animation:none}}
</style>
Chevron-Schubs bei Hover
Pol 1 · Craft
Anlass: Akkordeon, „mehr"-Hinweis
Der Pfeil rutscht beim Hover/Fokus kurz nach unten — ein Mikro-Hinweis,
dass sich etwas ausklappen lässt. Nur transform.
<button class="fx-chev" type="button" aria-label="Aufklappen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"/>
</svg>
</button>
<style>
.fx-chev{width:44px;height:44px;border-radius:10px;cursor:pointer;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:#f4f4f5}
.fx-chev:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-chev svg{width:22px;height:22px;transition:transform .25s ease}
.fx-chev:hover svg,.fx-chev:focus-visible svg{transform:translateY(3px)}
@media (prefers-reduced-motion:reduce){.fx-chev svg{transition:none}}
</style>
Glocke mit Ring-Schwingen
Pol 1 · Craft
Anlass: Benachrichtigungen
Beim Hover/Fokus schwingt die Glocke einmalig aus und pendelt sich aus
(gedämpfte Rotation). Spielerisch, daher sparsam einsetzen.
<button class="fx-bell" type="button" aria-label="Benachrichtigungen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M6 9a6 6 0 0 1 12 0c0 5 2 6 2 6H4s2-1 2-6z"/>
<path d="M10 19a2 2 0 0 0 4 0"/>
</svg>
</button>
<style>
.fx-bell{width:44px;height:44px;border-radius:10px;cursor:pointer;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:#f4f4f5}
.fx-bell:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-bell svg{width:22px;height:22px;transform-origin:top center}
.fx-bell:hover svg,.fx-bell:focus-visible svg{animation:fxRing .7s ease-in-out}
@keyframes fxRing{0%,100%{transform:rotate(0)}15%{transform:rotate(14deg)}
30%{transform:rotate(-11deg)}45%{transform:rotate(8deg)}60%{transform:rotate(-5deg)}75%{transform:rotate(2deg)}}
@media (prefers-reduced-motion:reduce){.fx-bell:hover svg,.fx-bell:focus-visible svg{animation:none}}
</style>
Herz-Beat (Puls)
Pol 1 · Craft
Anlass: Favorit / Like
Beim Hover/Fokus pulsiert das Herz im Beat-Rhythmus (Skalierung). Nur
transform:scale; im Ruhezustand still.
<button class="fx-heart" type="button" aria-label="Zu Favoriten">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 20s-7-4.4-9.2-8.6A4.8 4.8 0 0 1 12 6a4.8 4.8 0 0 1 9.2 5.4C19 15.6 12 20 12 20z"/>
</svg>
</button>
<style>
.fx-heart{width:44px;height:44px;border-radius:10px;cursor:pointer;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:var(--akzent,#7c87ff)}
.fx-heart:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-heart svg{width:22px;height:22px;transform-origin:center}
.fx-heart:hover svg,.fx-heart:focus-visible svg{animation:fxBeat .9s ease-in-out infinite}
@keyframes fxBeat{0%,100%{transform:scale(1)}20%{transform:scale(1.18)}40%{transform:scale(.96)}60%{transform:scale(1.08)}}
@media (prefers-reduced-motion:reduce){.fx-heart:hover svg,.fx-heart:focus-visible svg{animation:none}}
</style>
Checkmark-Draw
Pol 1 · Craft
Anlass: Erfolg / abgeschlossen
Das Häkchen zeichnet sich beim Hover/Fokus selbst — über
stroke-dasharray/stroke-dashoffset. Schön als Bestätigung,
z. B. nach dem Abschicken eines Formulars.
<button class="fx-check" type="button" aria-label="Erledigt">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline class="mark" points="4 12 10 18 20 6"/>
</svg>
</button>
<style>
.fx-check{width:44px;height:44px;border-radius:10px;cursor:pointer;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:var(--akzent,#7c87ff)}
.fx-check:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-check svg{width:24px;height:24px}
.fx-check .mark{stroke-dasharray:24;stroke-dashoffset:24;transition:stroke-dashoffset .45s ease}
.fx-check:hover .mark,.fx-check:focus-visible .mark{stroke-dashoffset:0}
@media (prefers-reduced-motion:reduce){
.fx-check .mark{transition:none;stroke-dashoffset:0}
}
</style>
Pulse-Dot (Status-Punkt)
Pol 1 · Craft
Anlass: „Online", Live-Status
Ein Punkt mit ausstrahlendem Ring — typisch für „live" oder „verfügbar".
Der Ring skaliert nach außen und blendet aus; bei reduzierter Bewegung bleibt nur der
ruhige Punkt.
<span class="fx-dot" role="img" aria-label="Status: online">
<span class="ring"></span>
<span class="core"></span>
</span>
<style>
.fx-dot{position:relative;display:inline-block;width:14px;height:14px}
.fx-dot .core{position:absolute;inset:0;border-radius:50%;background:var(--akzent,#7c87ff)}
.fx-dot .ring{position:absolute;inset:0;border-radius:50%;background:var(--akzent,#7c87ff);
opacity:.6;animation:fxPulse 1.8s ease-out infinite}
@keyframes fxPulse{0%{transform:scale(1);opacity:.6}100%{transform:scale(2.6);opacity:0}}
@media (prefers-reduced-motion:reduce){.fx-dot .ring{animation:none;opacity:0}}
</style>
Chevron-Rotation (animiert)
Pol 1 · Craft
Anlass: Micro-Interaktion / Buttons
Der Pfeil dreht sich beim Hover/Fokus um 180° — zeigt an, dass sich ein
Bereich auf- und zuklappen lässt. Nur transform:rotate. Anders als der
Chevron-Schubs oben (der nur nach unten stupst), dreht dieser komplett. Vorbild:
animate-ui „Icons".
<button class="fx-chevrot" type="button" aria-label="Aufklappen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"/>
</svg>
</button>
<style>
.fx-chevrot{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:#f4f4f5}
.fx-chevrot:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-chevrot svg{width:22px;height:22px;transition:transform .3s ease}
.fx-chevrot:hover svg,.fx-chevrot:focus-visible svg{transform:rotate(180deg)}
@media (prefers-reduced-motion:reduce){
.fx-chevrot svg{transition:none}
.fx-chevrot:hover svg,.fx-chevrot:focus-visible svg{transform:none}
}
</style>
Pfeil-Wandern (animiert)
Pol 1 · Craft
Anlass: Micro-Interaktion / Buttons
Beim Hover/Fokus wandert der Pfeil kurz in seine Richtung und kehrt zurück
— ein Mikro-Hinweis „hier geht es weiter". Ideal in Text-Links und „Mehr erfahren"-Buttons.
Nur transform:translateX. Vorbild: animate-ui „Icons".
<button class="fx-arrow" type="button" aria-label="Weiter">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="4" y1="12" x2="20" y2="12"/><polyline points="13 5 20 12 13 19"/>
</svg>
</button>
<style>
.fx-arrow{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:#f4f4f5}
.fx-arrow:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-arrow svg{width:22px;height:22px}
.fx-arrow:hover svg,.fx-arrow:focus-visible svg{animation:fxArrowGo .5s ease}
@keyframes fxArrowGo{0%{transform:translateX(0)}45%{transform:translateX(5px)}100%{transform:translateX(0)}}
@media (prefers-reduced-motion:reduce){
.fx-arrow:hover svg,.fx-arrow:focus-visible svg{animation:none}
}
</style>
Plus → X (45°-Dreh, animiert)
Pol 1 · Craft
Anlass: Micro-Interaktion / Buttons
Ein Plus, das sich beim Hover/Fokus um 45° dreht und so zum Schließen-X wird
— typisch für „hinzufügen / wieder schließen"-Schalter. Ein einziges Icon, kein Umbau des
Markups. Nur transform:rotate. Vorbild: animate-ui „Icons".
<button class="fx-plus" type="button" aria-label="Hinzufügen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>
</svg>
</button>
<style>
.fx-plus{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:#f4f4f5}
.fx-plus:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-plus svg{width:22px;height:22px;transition:transform .3s ease}
.fx-plus:hover svg,.fx-plus:focus-visible svg{transform:rotate(45deg)}
@media (prefers-reduced-motion:reduce){
.fx-plus svg{transition:none}
.fx-plus:hover svg,.fx-plus:focus-visible svg{transform:none}
}
</style>
Herz-Füllung (animiert)
Pol 1 · Craft
Anlass: Micro-Interaktion / Buttons
Beim Hover/Fokus füllt sich das Herz in der Akzentfarbe und wächst leicht —
klar als „gemerkt / geliked". Anders als der Herz-Beat oben (der nur pulsiert) wechselt
dieses von Umriss zu Füllung. Übergang auf fill und transform.
Vorbild: animate-ui „Icons".
<button class="fx-fill" type="button" aria-label="Merken">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path class="shape" d="M12 20s-7-4.4-9.2-8.6A4.8 4.8 0 0 1 12 6a4.8 4.8 0 0 1 9.2 5.4C19 15.6 12 20 12 20z"/>
</svg>
</button>
<style>
.fx-fill{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:var(--akzent,#7c87ff)}
.fx-fill:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-fill svg{width:22px;height:22px}
.fx-fill svg .shape{fill:transparent;transition:fill .35s ease,transform .35s ease;transform-origin:center}
.fx-fill:hover svg .shape,.fx-fill:focus-visible svg .shape{fill:currentColor;transform:scale(1.08)}
@media (prefers-reduced-motion:reduce){
.fx-fill svg .shape{transition:fill .35s ease}
.fx-fill:hover svg .shape,.fx-fill:focus-visible svg .shape{transform:none}
}
</style>
Stern-Füllung (animiert)
Pol 1 · Craft
Anlass: Micro-Interaktion / Buttons
Wie das Herz, aber für Bewertungen und Lesezeichen: Der Stern füllt sich
beim Hover/Fokus in der Akzentfarbe und wächst kurz — als „angezwinkert / markiert".
Gleiche Füll-Mechanik (.fx-fill). Vorbild: animate-ui „Icons".
<button class="fx-fill" type="button" aria-label="Bewerten">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polygon class="shape" points="12 3 14.6 8.5 20.5 9.3 16.2 13.4 17.3 19.3 12 16.5 6.7 19.3 7.8 13.4 3.5 9.3 9.4 8.5 12 3"/>
</svg>
</button>
<style>
/* nutzt dieselbe .fx-fill-Mechanik wie das Herz oben:
Umriss -> Füllung in Akzentfarbe + leichtes Wachsen. */
.fx-fill{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:var(--akzent,#7c87ff)}
.fx-fill:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-fill svg{width:22px;height:22px}
.fx-fill svg .shape{fill:transparent;transition:fill .35s ease,transform .35s ease;transform-origin:center}
.fx-fill:hover svg .shape,.fx-fill:focus-visible svg .shape{fill:currentColor;transform:scale(1.08)}
@media (prefers-reduced-motion:reduce){
.fx-fill svg .shape{transition:fill .35s ease}
.fx-fill:hover svg .shape,.fx-fill:focus-visible svg .shape{transform:none}
}
</style>
Download (Pfeil nach unten, animiert)
Pol 1 · Craft
Anlass: Micro-Interaktion / Buttons
Beim Hover/Fokus lässt der Pfeil kurz nach unten in die Ablage „fallen" —
verdeutlicht die Download-Geste. Nur der Pfeil animiert (transform:translateY),
die Ablage-Linie bleibt ruhig. Vorbild: animate-ui „Icons".
<button class="fx-dl" type="button" aria-label="Herunterladen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/>
<g class="dl-arrow"><line x1="12" y1="4" x2="12" y2="15"/><polyline points="7 10 12 15 17 10"/></g>
</svg>
</button>
<style>
.fx-dl{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:#f4f4f5}
.fx-dl:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-dl svg{width:22px;height:22px}
.fx-dl svg .dl-arrow{transition:transform .3s ease}
.fx-dl:hover svg .dl-arrow,.fx-dl:focus-visible svg .dl-arrow{animation:fxDrop .55s ease}
@keyframes fxDrop{0%{transform:translateY(-3px);opacity:.4}55%{transform:translateY(2px);opacity:1}100%{transform:translateY(0)}}
@media (prefers-reduced-motion:reduce){
.fx-dl svg .dl-arrow{transition:none}
.fx-dl:hover svg .dl-arrow,.fx-dl:focus-visible svg .dl-arrow{animation:none}
}
</style>
Suche/Lupe-Wackeln (animiert)
Pol 1 · Craft
Anlass: Micro-Interaktion / Buttons
Beim Hover/Fokus kippt die Lupe kurz hin und her, als würde jemand suchen —
lädt zum Antippen des Suchfelds ein. Dreht um den Linsen-Mittelpunkt
(transform-origin gesetzt). Vorbild: animate-ui „Icons".
<button class="fx-mag" type="button" aria-label="Suche">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="7"/><line x1="16" y1="16" x2="21" y2="21"/>
</svg>
</button>
<style>
.fx-mag{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:#f4f4f5}
.fx-mag:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-mag svg{width:22px;height:22px;transform-origin:9px 9px}
.fx-mag:hover svg,.fx-mag:focus-visible svg{animation:fxWiggle .6s ease}
@keyframes fxWiggle{0%,100%{transform:rotate(0)}25%{transform:rotate(-12deg)}50%{transform:rotate(9deg)}75%{transform:rotate(-4deg)}}
@media (prefers-reduced-motion:reduce){
.fx-mag:hover svg,.fx-mag:focus-visible svg{animation:none}
}
</style>
Warenkorb-Rollen (animiert)
Pol 1 · Craft
Anlass: Micro-Interaktion / Buttons
Beim Hover/Fokus rollt der Korb kurz an und zurück — ein spielerischer
Hinweis „in den Warenkorb". Nur transform:translateX. Sparsam einsetzen,
passt zu Shop-CTAs. Vorbild: animate-ui „Icons".
<button class="fx-cart" type="button" aria-label="In den Warenkorb">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="9" cy="20" r="1.5"/><circle cx="18" cy="20" r="1.5"/>
<path d="M2 3h2l2.4 12.2a1.5 1.5 0 0 0 1.5 1.2h9.1a1.5 1.5 0 0 0 1.5-1.2L21 7H5.2"/>
</svg>
</button>
<style>
.fx-cart{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:#f4f4f5}
.fx-cart:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-cart svg{width:22px;height:22px}
.fx-cart:hover svg,.fx-cart:focus-visible svg{animation:fxRoll .6s ease}
@keyframes fxRoll{0%{transform:translateX(-4px)}60%{transform:translateX(3px)}100%{transform:translateX(0)}}
@media (prefers-reduced-motion:reduce){
.fx-cart:hover svg,.fx-cart:focus-visible svg{animation:none}
}
</style>
Play → Pause (Zustands-Morph, klickbar)
Pol 1 · Craft
Anlass: Audio-/Video-Steuerung, Slider-Autoplay
Klick schaltet zwischen Dreieck und zwei Balken um — die Formen liegen
deckungsgleich übereinander und blenden per opacity/scale weich
ineinander (keine d-Animation, läuft auch in Safari). aria-pressed
führt den Zustand mit. Anders als „Plus → X" oben (Rotation): hier wechselt die Form
komplett. Eigenbau, Muster inspiriert von animierten Icon-Sets.
<button class="fx-play" type="button" aria-label="Abspielen" aria-pressed="false">
<svg viewBox="0 0 24 24" fill="none">
<g class="g-play"><polygon class="shp" points="8 5 19 12 8 19"/></g>
<g class="g-pause">
<rect class="shp" x="6" y="5" width="4" height="14" rx="1"/>
<rect class="shp" x="14" y="5" width="4" height="14" rx="1"/>
</g>
</svg>
</button>
<style>
.fx-play{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:var(--akzent,#7c87ff)}
.fx-play:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-play svg{width:22px;height:22px}
.fx-play .shp{fill:currentColor;transform-origin:center;
transition:opacity .28s ease,transform .32s cubic-bezier(.4,0,.2,1)}
/* Play-Dreieck und Pause-Balken liegen deckungsgleich; Zustand blendet um */
.fx-play .g-play{opacity:1;transform:scale(1)}
.fx-play .g-pause{opacity:0;transform:scale(.55)}
.fx-play.playing .g-play{opacity:0;transform:scale(.55)}
.fx-play.playing .g-pause{opacity:1;transform:scale(1)}
@media (prefers-reduced-motion:reduce){.fx-play .shp{transition:none}}
</style>
<script>
document.querySelectorAll('.fx-play').forEach(function(b){
b.addEventListener('click',function(){
var on=b.classList.toggle('playing');
b.setAttribute('aria-pressed',on);
b.setAttribute('aria-label',on?'Pausieren':'Abspielen');
});
});
</script>
Menü → Zurück-Pfeil (Hover-Morph)
Pol 1 · Craft
Anlass: mobile Navigation, Drawer-Auslöser
Beim Hover/Fokus falten sich die drei Menü-Striche zu einem Zurück-Pfeil:
die äußeren Linien kippen und verkürzen sich zur Pfeilspitze, die mittlere schrumpft leicht
zum Schaft. Rein per transform, kein Markup-Umbau — anders als der
„Hamburger → X"-Morph oben (der zum X wird). Eigenbau.
<button class="fx-back" type="button" aria-label="Zurück">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
<line class="ln l-top" x1="4" y1="7" x2="20" y2="7"/>
<line class="ln l-mid" x1="4" y1="12" x2="20" y2="12"/>
<line class="ln l-bot" x1="4" y1="17" x2="20" y2="17"/>
</svg>
</button>
<style>
.fx-back{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:#f4f4f5}
.fx-back:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-back svg{width:22px;height:22px}
.fx-back .ln{transition:transform .35s cubic-bezier(.4,0,.2,1);transform-origin:center}
.fx-back:hover .l-top,.fx-back:focus-visible .l-top{transform:translate(-4px,5px) rotate(-45deg) scaleX(.55)}
.fx-back:hover .l-bot,.fx-back:focus-visible .l-bot{transform:translate(-4px,-5px) rotate(45deg) scaleX(.55)}
.fx-back:hover .l-mid,.fx-back:focus-visible .l-mid{transform:scaleX(.9)}
@media (prefers-reduced-motion:reduce){.fx-back .ln{transition:none}}
</style>
Kopieren → Erledigt (Klick-Erfolg mit Draw-on)
Pol 2 · Klarheit
Anlass: „Code kopieren", „Link kopieren"
Klick wechselt das Kopieren-Symbol gegen ein sich selbst zeichnendes Häkchen
(stroke-dashoffset) und blendet kurz „Kopiert" ein; nach zwei Sekunden springt
alles zurück. Beide Symbole liegen per grid übereinander und werden über
opacity/scale getauscht. Anders als „Checkmark-Draw" oben (nur
Hover-Demo): hier echter, rücksetzender Klick-Zustand. Eigenbau.
<button class="fx-copy" type="button">
<span class="ico">
<svg class="i-copy" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
</svg>
<svg class="i-done" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline class="mark" points="4 12 10 18 20 6"/>
</svg>
</span>
<span class="lbl">Kopieren</span>
</button>
<style>
.fx-copy{display:inline-flex;align-items:center;gap:.5rem;padding:.6rem 1rem;border-radius:10px;cursor:pointer;
background:#17171b;border:1px solid #26262c;color:#e9e9ee;font-size:.9rem;font-weight:600;
transition:border-color .25s ease,color .25s ease}
.fx-copy:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-copy svg{width:18px;height:18px;flex:0 0 auto}
.fx-copy .ico{display:grid}
.fx-copy .i-copy,.fx-copy .i-done{grid-area:1/1;transition:opacity .25s ease,transform .25s ease}
.fx-copy .i-done{opacity:0;transform:scale(.6);color:var(--akzent,#7c87ff)}
.fx-copy .i-done .mark{stroke-dasharray:22;stroke-dashoffset:22;transition:stroke-dashoffset .45s ease .05s}
.fx-copy.done{color:var(--akzent,#7c87ff);border-color:var(--akzent,#7c87ff)}
.fx-copy.done .i-copy{opacity:0;transform:scale(.6)}
.fx-copy.done .i-done{opacity:1;transform:scale(1)}
.fx-copy.done .i-done .mark{stroke-dashoffset:0}
@media (prefers-reduced-motion:reduce){
.fx-copy,.fx-copy .i-copy,.fx-copy .i-done,.fx-copy .i-done .mark{transition:none}
}
</style>
<script>
document.querySelectorAll('.fx-copy').forEach(function(b){
var lbl=b.querySelector('.lbl'), base=lbl?lbl.textContent:'', t;
b.addEventListener('click',function(){
b.classList.add('done');
if(lbl) lbl.textContent='Kopiert';
clearTimeout(t);
t=setTimeout(function(){
b.classList.remove('done');
if(lbl) lbl.textContent=base;
},2000);
/* Echtes Kopieren optional: navigator.clipboard.writeText('…') */
});
});
</script>
Sonne ↔ Mond (Theme-Toggle-Morph)
Pol 1 · Craft
Anlass: Hell-/Dunkel-Umschalter
Klick verwandelt die Sonne in einen Mond: die Strahlen ziehen sich zusammen
und blenden aus, während ein zweiter, hintergrundfarbener Kreis in die Scheibe schiebt und die
Sichel „ausbeißt". Rein per transform. aria-pressed trägt den Zustand.
Der ausbeißende Kreis nutzt die Flächenfarbe #17171b — beim Einbau an den echten
Hintergrund anpassen. Eigenbau.
<button class="fx-sun" type="button" aria-label="Dunkelmodus einschalten" aria-pressed="false">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<g class="rays">
<line x1="12" y1="1.5" x2="12" y2="4"/><line x1="12" y1="20" x2="12" y2="22.5"/>
<line x1="1.5" y1="12" x2="4" y2="12"/><line x1="20" y1="12" x2="22.5" y2="12"/>
<line x1="4.4" y1="4.4" x2="6.2" y2="6.2"/><line x1="17.8" y1="17.8" x2="19.6" y2="19.6"/>
<line x1="4.4" y1="19.6" x2="6.2" y2="17.8"/><line x1="17.8" y1="6.2" x2="19.6" y2="4.4"/>
</g>
<circle class="core" cx="12" cy="12" r="5" fill="currentColor" stroke="none"/>
<circle class="bite" cx="12" cy="12" r="5" stroke="none"/>
</svg>
</button>
<style>
.fx-sun{width:44px;height:44px;border-radius:10px;cursor:pointer;padding:0;
display:inline-flex;align-items:center;justify-content:center;
background:#17171b;border:1px solid #26262c;color:var(--akzent,#7c87ff)}
.fx-sun:focus-visible{outline:2px solid var(--akzent,#7c87ff);outline-offset:2px}
.fx-sun svg{width:22px;height:22px}
.fx-sun .core{transition:transform .4s cubic-bezier(.4,0,.2,1)}
.fx-sun .rays line{transform-origin:12px 12px;transition:transform .4s ease,opacity .3s ease}
/* Mond-Sichel: zweiter, flächenfarbener Kreis schiebt in den Kern */
.fx-sun .bite{fill:#17171b;transform:translateX(9px);transition:transform .4s cubic-bezier(.4,0,.2,1)}
.fx-sun.moon .core{transform:scale(1.05)}
.fx-sun.moon .rays line{transform:scale(.3);opacity:0}
.fx-sun.moon .bite{transform:translateX(0)}
@media (prefers-reduced-motion:reduce){
.fx-sun .core,.fx-sun .rays line,.fx-sun .bite{transition:none}
}
</style>
<script>
document.querySelectorAll('.fx-sun').forEach(function(b){
b.addEventListener('click',function(){
var on=b.classList.toggle('moon');
b.setAttribute('aria-pressed',on);
b.setAttribute('aria-label',on?'Hellmodus einschalten':'Dunkelmodus einschalten');
});
});
</script>