Collage-/Scrapbook-Layout
Hero eines Hallenser Flussvereins: Fotos, Polaroid, Sammelprotokoll, Notiz und Freisteller liegen gedreht auf einem verdeckten 12×12-Raster, lassen sich ziehen und wechseln per Flip zwischen Klebebuch, Ausschnitten und Pinnwand.
Bilder, Freisteller, Sticker, handschriftliche Notizen, Klebeband und Papier liegen überlappend und leicht gedreht übereinander. Das Arrangement folgt verdeckt einem Raster (z. B. 12 × 12), wirkt aber zufällig. Teile lassen sich ziehen oder bewegen sich mit unterschiedlicher Parallaxe. Beim Hover hebt sich ein Teil an: mehr Schatten, Drehung zurück auf 0.
Wirkt handgemacht, persönlich und analog. Ein Gegenpol zu glatten Template- und KI-Ästhetiken, der zum Spielen einlädt.
Wann einsetzen
Persönliche Portfolios, Kreative, Food, Reise, Mode, Kulturprojekte, Vereine, Kampagnen und Über-mich-Bereiche.
Wann nicht
Seriöse B2B-Kontexte, informationsdichte Seiten und Projekte ohne eigenes Material.
Varianten
- Cutout-Collage mit clip-path-Polygonen
- Ziehbare Pinnwand
- Sticker und Notizen über Fotos
- Gescannte Papiertexturen und Klebeband
- Reise-Collage als ganze Seite
Umsetzung
12 × 12-Raster (grid-template-columns und grid-template-rows: repeat(12, 1fr)), Teile überlappend per grid-area platziert, Ebenen über z-index. Freisteller per clip-path: polygon() in Prozent, damit sie mitskalieren. Drehung über eine CSS-Variable --r (etwa −6° bis 6°). Ziehen mit GSAP Draggable oder Pointer Events; die Lage nur bewusst speichern. Freisteller als WebP oder AVIF mit Alpha bzw. PNG; Schatten mit drop-shadow statt box-shadow, damit er der Form folgt. Ziehen und Drehen auf ein inneres und ein äußeres Element verteilen, sonst überschreiben sich die Transforms. Zufall aus CSS: random() ist seit Chrome 156 stabil (20.10.2026), Firefox fehlt noch. Für ein leichtes Zittern je Teil etwa rotate: calc(var(--r) + random(element-scoped, -2deg, 2deg)) in @supports (rotate: random(element-scoped, -2deg, 2deg)), sonst bleibt --r. Die Grundlage bleibt eine feste, gestaltete Drehung je Teil: Zufall bei Lage oder starker Drehung bricht das verdeckte Raster, und die Collage sähe bei jedem Besuch anders aus.
Robust umsetzen
Telefon. Weniger Teile und eine eigene Hochformat-Komposition mit eigenen Grid-Bereichen. Ziehen nur, wenn es das Scrollen nicht blockiert.
Ohne Bewegung. Keine Parallaxe, die Teile stehen still.
Barrierefrei. Dekorative Teile mit aria-hidden ausblenden und den Inhalt der Collage in einem Text beschreiben. Ziehen darf nicht die einzige Bedienung sein. Die Lesereihenfolge der Texte festlegen.
Code
<!DOCTYPE html>
<!--
Collage-/Scrapbook-Layout
Fundus · Hero & Section-Layouts · https://cecodesign.de/lab/fundus/hero-layouts/collage-scrapbook/
Eigenständige Datei. Bilder liegen hier unter bilder/ – eigene einsetzen.
-->
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Collage-/Scrapbook-Layout · Fundus-Demo</title>
<script>document.documentElement.classList.add('js');if(matchMedia('(prefers-reduced-motion: reduce)').matches)document.documentElement.classList.add('reduziert')</script>
<style>
@font-face { font-family: 'Big Shoulders'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/big-shoulders:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 100 900; font-display: swap; }
@font-face { font-family: 'Archivo'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/archivo:vf@latest/latin-full-normal.woff2') format('woff2-variations'); font-weight: 100 900; font-stretch: 62% 125%; font-display: swap; }
@font-face { font-family: 'Caveat'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/caveat@latest/latin-600-normal.woff2') format('woff2'); font-weight: 600; font-display: swap; }
:root {
/* Flussbande Halle e.V.: tiefer Markenton (Saale-Blau), helle Flächen derselben Farbe, Gelb nur für Spenden */
--marke: #002e6d; --marke-tief: #00224f; --hell: #edf5fa; --grau: #dfdfd7; --tinte: #222520; --papier: #fbfaf6;
--wasser: #8dbbe0; --gruen: #3f6b4a; --signal: #ffca0a;
/* Große Zustandswechsel: easeInOutCubic (gemessen bei Ocean Cleanup), Interaktion 200 ms */
--kurve: cubic-bezier(0.645, 0.045, 0.355, 1);
--gross: 800ms;
--ui: 200ms;
}
* { box-sizing: border-box; margin: 0; }
html { background: var(--marke); color: var(--tinte); font-family: 'Archivo', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
body { min-height: 100svh; overflow-x: clip; }
a { color: inherit; }
button { font: inherit; color: inherit; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; color: CanvasText; background: Canvas; }
/* ---------- Kopf ---------- */
.kopf { position: relative; z-index: 20; display: flex; align-items: center; justify-content: space-between; gap: 20px; max-width: 1360px; margin: 0 auto; padding: 18px clamp(16px, 3vw, 40px); color: #fff; }
.marke { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; }
.marke svg { width: 38px; height: 38px; flex: none; }
.marke b { font: 800 26px/0.9 'Big Shoulders', sans-serif; text-transform: uppercase; letter-spacing: .01em; display: block; }
.marke small { font-size: 12px; opacity: .72; letter-spacing: .02em; }
.nav { display: flex; align-items: center; gap: clamp(14px, 2vw, 30px); font-size: 15px; font-weight: 500; }
.nav a { text-decoration: none; opacity: .85; transition: opacity var(--ui) var(--kurve); }
.nav a:hover { opacity: 1; }
.spenden { display: inline-flex; align-items: center; height: 44px; padding: 0 20px; border-radius: 999px; background: var(--signal); color: var(--tinte) !important; opacity: 1 !important; font-weight: 600; font-size: 16px; text-decoration: none; transition: background-color 150ms linear; }
.spenden:hover { background: #ffd643; }
:focus-visible { outline: 3px solid var(--signal); outline-offset: 3px; }
/* ---------- Held mit Collage ---------- */
.held { position: relative; max-width: 1360px; margin: 0 auto; padding: 0 clamp(16px, 3vw, 40px) 40px; min-height: calc(100svh - 80px); display: grid; }
.text { position: relative; z-index: 6; grid-area: 1 / 1; align-self: center; width: min(calc(41.66% - 28px), 600px); padding: 20px 0 56px; color: #fff; display: grid; gap: 22px; justify-items: start; pointer-events: none; }
.text a, .text p { pointer-events: auto; }
.dach { font-size: 14px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--wasser); }
h1 { font: 800 clamp(2.75rem, 1.6rem + 5vw, 6rem)/.95 'Big Shoulders', sans-serif; text-transform: uppercase; letter-spacing: .005em; text-wrap: balance; }
h1 span { color: var(--wasser); }
.text__lauf { max-width: 44ch; font-size: 1.0625rem; line-height: 1.6; color: rgba(255, 255, 255, .86); text-wrap: pretty; }
.ctas { display: flex; flex-wrap: wrap; gap: 12px; }
.knopf { display: inline-flex; align-items: center; height: 48px; padding: 0 22px; border-radius: 999px; font-weight: 600; font-size: 16px; text-decoration: none; border: 1.5px solid rgba(255, 255, 255, .5); color: #fff; transition: border-color var(--ui) var(--kurve), background-color var(--ui) var(--kurve); }
.knopf:hover { border-color: #fff; background: rgba(255, 255, 255, .06); }
.zahlen { display: flex; gap: clamp(18px, 3vw, 40px); margin-top: 8px; padding-top: 18px; border-top: 1px solid rgba(255, 255, 255, .2); }
.zahlen div { display: grid; gap: 4px; }
.zahlen b { font: 800 clamp(1.9rem, 1.3rem + 1.6vw, 2.75rem)/1 'Big Shoulders', sans-serif; font-variant-numeric: tabular-nums; }
.zahlen span { font-size: 13px; color: rgba(255, 255, 255, .72); }
.stand { font-size: 12px; color: rgba(255, 255, 255, .55); }
/* ---------- Die Collage: verdecktes 12×12-Raster ---------- */
.collage { grid-area: 1 / 1; position: relative; z-index: 2; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); grid-template-rows: repeat(12, minmax(0, 1fr)); gap: 0; min-height: 640px; }
.stueck { position: relative; min-width: 0; min-height: 0; touch-action: none; }
.blatt { position: absolute; inset: 0; rotate: var(--r, 0deg); filter: drop-shadow(0 2px 2px rgba(0, 20, 50, .25)) drop-shadow(0 14px 22px rgba(0, 20, 50, .3)); transition: rotate var(--gross) var(--kurve), translate var(--ui) var(--kurve), filter var(--ui) var(--kurve); cursor: grab; }
.blatt:active { cursor: grabbing; }
/* Hover hebt an und dreht zurück auf 0 */
@media (hover: hover) {
.stueck:hover .blatt { rotate: 0deg; translate: 0 -5px; filter: drop-shadow(0 4px 4px rgba(0, 20, 50, .22)) drop-shadow(0 26px 34px rgba(0, 20, 50, .38)); transition: rotate var(--ui) var(--kurve), translate var(--ui) var(--kurve), filter var(--ui) var(--kurve); }
}
.stueck.gehoben .blatt { rotate: 0deg; translate: 0 -5px; filter: drop-shadow(0 4px 4px rgba(0, 20, 50, .22)) drop-shadow(0 26px 34px rgba(0, 20, 50, .38)); transition: rotate var(--ui) var(--kurve), translate var(--ui) var(--kurve), filter var(--ui) var(--kurve); }
.bild { position: absolute; inset: 0; overflow: hidden; transition: clip-path var(--gross) var(--kurve); }
.bild svg { width: 100%; height: 100%; display: block; }
/* Fotos, Polaroid und Karte behalten ihr Seitenverhältnis; die Breite kommt aus dem Raster */
.foto .blatt, .polaroid .blatt, .karte .blatt { bottom: auto; aspect-ratio: var(--ar); }
.foto { --ar: 400 / 290; } .polaroid { --ar: 260 / 316; } .karte { --ar: 220 / 260; }
/* Papier-Objekte */
.foto .bild { background: var(--hell); border: 7px solid var(--papier); }
.polaroid .bild { background: var(--papier); padding: 9px 9px 0; display: grid; grid-template-rows: 1fr auto; }
.polaroid .bild svg { height: 100%; min-height: 0; }
.polaroid .hand { padding: 8px 6px 10px; font-size: clamp(16px, 1.3vw, 20px); line-height: 1; color: var(--marke); text-align: center; text-wrap: balance; }
.hand { font-family: 'Caveat', cursive; font-weight: 600; }
.notiz .bild { background: #d3e8f6; padding: 16px 16px 12px; color: var(--marke); font-size: clamp(18px, 1.55vw, 24px); line-height: 1.05; background-image: linear-gradient(transparent calc(100% - 1px), rgba(0, 46, 109, .14) 0); background-size: 100% 1.05em; background-position: 0 14px; }
.notiz .bild::after { content: ""; position: absolute; right: 0; bottom: 0; width: 28px; height: 28px; background: linear-gradient(135deg, #b9d5ea 50%, transparent 50%); }
.zettel .bild { background: var(--papier); padding: 16px 16px 26px; font-stretch: 75%; font-size: clamp(11px, .9vw, 13px); line-height: 1.5; color: var(--tinte); font-variant-numeric: tabular-nums; clip-path: polygon(0 0, 100% 0, 100% 96%, 95% 100%, 90% 96%, 85% 100%, 80% 96%, 75% 100%, 70% 96%, 65% 100%, 60% 96%, 55% 100%, 50% 96%, 45% 100%, 40% 96%, 35% 100%, 30% 96%, 25% 100%, 20% 96%, 15% 100%, 10% 96%, 5% 100%, 0 96%); }
.zettel h3 { font: 800 clamp(15px, 1.3vw, 19px)/1 'Big Shoulders', sans-serif; letter-spacing: .04em; text-transform: uppercase; margin-bottom: 4px; }
.zettel dl { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 8px; margin-top: 8px; }
.zettel dt { display: flex; white-space: nowrap; }
/* Punktleiste schneidet sich selbst ab (flex: 1, min-width: 0), der Name bleibt immer ganz sichtbar */
.zettel dt::after { content: "........................................"; flex: 1 1 0; min-width: 0; overflow: hidden; margin-left: .3em; color: rgba(34, 37, 32, .4); }
.zettel .summe { border-top: 1px dashed rgba(34, 37, 32, .5); margin-top: 4px; padding-top: 4px; font-weight: 700; }
.zettel .stempel { position: absolute; left: 30%; bottom: 1%; width: 40%; rotate: -14deg; mix-blend-mode: multiply; opacity: .82; }
.sticker .bild, .ausschnitt .bild { overflow: visible; }
.karte .bild { background: #f6f9fb; border: 6px solid var(--papier); }
/* Klebeband (Klebebuch) und Pins (Pinnwand) */
.band { position: absolute; z-index: 2; width: 38%; max-width: 120px; height: 26px; left: 50%; top: -12px; translate: -50% 0; rotate: var(--br, -4deg); background: rgba(237, 245, 250, .62); box-shadow: 0 1px 2px rgba(0, 20, 50, .12); clip-path: polygon(2% 8%, 8% 0, 14% 10%, 22% 2%, 30% 9%, 38% 0, 48% 8%, 58% 1%, 68% 9%, 78% 0, 88% 9%, 96% 2%, 100% 12%, 98% 88%, 92% 100%, 84% 90%, 74% 99%, 64% 91%, 54% 100%, 44% 92%, 34% 100%, 24% 91%, 14% 99%, 6% 90%, 0 96%); transition: opacity var(--gross) var(--kurve); }
.pin { position: absolute; z-index: 3; left: 50%; top: 4px; width: 16px; height: 16px; margin-left: -8px; border-radius: 50%; background: radial-gradient(circle at 35% 30%, #fff 0 12%, #e9eef3 13%, #9fb3c4 70%); box-shadow: 0 3px 4px rgba(0, 20, 50, .45); opacity: 0; transition: opacity var(--gross) var(--kurve); }
.v-pinn .pin { opacity: 1; }
.v-pinn .band, .v-schnitt .band { opacity: 0; }
/* ---------- Varianten: Platz im 12×12-Raster und Drehung ---------- */
/* Klebebuch */
.v-klebe .s-foto { grid-area: 1 / 7 / 7 / 12; --r: -2.5deg; }
.v-klebe .s-karte { grid-area: 1 / 11 / 5 / 13; --r: 4deg; }
.v-klebe .s-sticker { grid-area: 6 / 6 / 8 / 7; --r: -10deg; }
.v-klebe .s-polaroid { grid-area: 5 / 10 / 11 / 13; --r: 5deg; }
.v-klebe .s-zettel { grid-area: 7 / 6 / 13 / 8; --r: -4deg; }
.v-klebe .s-notiz { grid-area: 7 / 8 / 10 / 10; --r: 3deg; }
.v-klebe .s-stiefel { grid-area: 9 / 9 / 13 / 11; --r: -8deg; }
.v-klebe .s-steckling{ grid-area: 10 / 12 / 13 / 13; --r: 10deg; }
/* Ausschnitte: Freisteller per clip-path, enger und größer */
.v-schnitt .s-foto { grid-area: 1 / 7 / 8 / 13; --r: 1.5deg; }
.v-schnitt .s-steckling{ grid-area: 1 / 12 / 4 / 13; --r: -14deg; }
.v-schnitt .s-sticker { grid-area: 1 / 6 / 3 / 7; --r: 8deg; }
.v-schnitt .s-polaroid { grid-area: 6 / 6 / 11 / 9; --r: -5deg; }
.v-schnitt .s-zettel { grid-area: 8 / 9 / 13 / 11; --r: 3deg; }
.v-schnitt .s-notiz { grid-area: 7 / 11 / 10 / 13; --r: 4deg; }
.v-schnitt .s-karte { grid-area: 9 / 11 / 12 / 13; --r: -3deg; }
.v-schnitt .s-stiefel { grid-area: 10 / 6 / 13 / 8; --r: -9deg; }
.v-schnitt .foto .bild { border: 0; clip-path: polygon(0 6%, 9% 1%, 17% 4%, 26% 0, 37% 5%, 49% 1%, 58% 4%, 70% 0, 81% 3%, 92% 0, 100% 5%, 98% 21%, 100% 37%, 97% 52%, 100% 69%, 98% 86%, 100% 100%, 86% 97%, 73% 100%, 61% 96%, 48% 100%, 34% 97%, 22% 100%, 10% 96%, 0 99%, 2% 82%, 0 64%, 3% 47%, 0 30%, 2% 16%); }
.v-schnitt .polaroid .bild { background: transparent; padding: 0; clip-path: polygon(6% 24%, 30% 16%, 58% 20%, 84% 12%, 99% 22%, 96% 48%, 100% 70%, 84% 88%, 56% 84%, 28% 90%, 4% 78%, 8% 52%); }
.v-schnitt .polaroid .hand { display: none; }
.v-schnitt .karte .bild { border: 0; clip-path: circle(48% at 50% 50%); }
/* Pinnwand: ordentlicher, kaum gedreht, alles mit Pin */
.v-pinn .s-foto { grid-area: 1 / 7 / 6 / 11; --r: -1deg; }
.v-pinn .s-karte { grid-area: 1 / 11 / 5 / 13; --r: 1.5deg; }
.v-pinn .s-sticker { grid-area: 5 / 11 / 7 / 12; --r: -6deg; }
.v-pinn .s-polaroid { grid-area: 7 / 10 / 13 / 13; --r: 2deg; }
.v-pinn .s-zettel { grid-area: 6 / 7 / 12 / 9; --r: -1.5deg; }
.v-pinn .s-notiz { grid-area: 7 / 9 / 10 / 11; --r: 2deg; }
.v-pinn .s-stiefel { grid-area: 10 / 9 / 13 / 10; --r: -3deg; }
.v-pinn .s-steckling{ grid-area: 5 / 12 / 8 / 13; --r: 4deg; }
/* ---------- Werte-Pult ---------- */
.pult { position: fixed; z-index: 30; left: clamp(16px, 3vw, 40px); bottom: 14px; display: flex; align-items: center; gap: 12px; padding: 5px 5px 5px 16px; border-radius: 999px; background: rgba(0, 34, 79, .82); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, .18); color: rgba(255, 255, 255, .78); font-size: 12px; font-stretch: 87%; white-space: nowrap; box-shadow: 0 10px 30px rgba(0, 10, 30, .3); }
.pult .modi { display: flex; gap: 3px; }
.pult .modi button { height: 30px; padding: 0 12px; border: 0; border-radius: 999px; background: transparent; color: rgba(255, 255, 255, .78); cursor: pointer; font-weight: 600; font-stretch: 100%; transition: background-color var(--ui) var(--kurve), color var(--ui) var(--kurve); }
.pult .modi button[aria-pressed="true"] { background: #fff; color: var(--marke); }
/* Vorführung: gezeichneter Zeiger */
.zeiger { position: fixed; left: 0; top: 0; z-index: 40; width: 20px; height: 20px; pointer-events: none; display: none; transition: scale var(--ui) var(--kurve); }
.vorfuehrung .zeiger { display: block; }
.zeiger.drueckt { scale: .8; }
.vorschau body { overflow: hidden; }
/* ---------- Schmal: Hochformat-Komposition mit weniger Elementen ---------- */
@media (max-width: 1180px) { .pult .werte { display: none; } .nav .weg-schmal { display: none; } }
@media (max-width: 760px) {
.nav a:not(.spenden) { display: none; }
.marke small { display: none; }
.held { grid-template-rows: auto auto; min-height: 0; }
.text { width: 100%; grid-area: 1 / 1; padding-bottom: 8px; }
.collage { grid-area: 2 / 1; grid-template-columns: repeat(6, minmax(0, 1fr)); grid-template-rows: repeat(8, minmax(0, 1fr)); min-height: 0; aspect-ratio: 3 / 4; margin-top: 16px; }
.s-karte, .s-steckling, .s-stiefel { display: none; }
.v-klebe .s-foto, .v-schnitt .s-foto, .v-pinn .s-foto { grid-area: 1 / 1 / 5 / 6; }
.v-klebe .s-sticker, .v-schnitt .s-sticker, .v-pinn .s-sticker { grid-area: 1 / 5 / 3 / 7; }
.v-klebe .s-polaroid, .v-schnitt .s-polaroid, .v-pinn .s-polaroid { grid-area: 4 / 4 / 8 / 7; }
.v-klebe .s-zettel, .v-schnitt .s-zettel, .v-pinn .s-zettel { grid-area: 5 / 1 / 9 / 4; }
.v-klebe .s-notiz, .v-schnitt .s-notiz, .v-pinn .s-notiz { grid-area: 7 / 3 / 9 / 6; }
.zahlen b { font-size: 2rem; }
}
@media (hover: none) { .blatt { cursor: default; } .stueck { touch-action: auto; } }
/* Zugang: bei 320 px bekommt die Notiz eine Zeile mehr und etwas kleinere Schrift, damit nichts abgeschnitten wird */
@media (max-width: 360px) {
.v-klebe .s-notiz, .v-schnitt .s-notiz, .v-pinn .s-notiz { grid-area: 6 / 3 / 9 / 6; }
.notiz .bild { font-size: 15px; padding: 12px 12px 10px; }
}
/* ---------- Reduzierte Bewegung: statisch, Wechsel ohne Fahrt ---------- */
.reduziert .blatt, .reduziert .bild, .reduziert .band, .reduziert .pin { transition: none !important; }
.reduziert .stueck:hover .blatt { translate: none; }
@media (forced-colors: active) { button, [role=button], [role=tab], [role=switch] { border: 1px solid ButtonText !important; } }
</style>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/CustomEase.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/Flip.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/Draggable.min.js"></script>
</head>
<body class="v-klebe">
<header class="kopf">
<a class="marke" href="#start" aria-label="Flussbande Halle e.V., Startseite">
<svg viewBox="0 0 38 38" aria-hidden="true"><circle cx="19" cy="19" r="19" fill="#edf5fa"/><path d="M6 17c3.3-3 6.7-3 10 0s6.7 3 10 0 5-2.4 6.4-1.6M6 24c3.3-3 6.7-3 10 0s6.7 3 10 0 5-2.4 6.4-1.6" fill="none" stroke="#002e6d" stroke-width="3" stroke-linecap="round"/></svg>
<span><b>Flussbande</b><small>Halle (Saale) e.V.</small></span>
</a>
<nav class="nav" aria-label="Hauptnavigation">
<a href="#mitmachen">Mitmachen</a>
<a href="#projekte">Projekte</a>
<a class="weg-schmal" href="#transparenz">Transparenz</a>
<a class="spenden" href="#spenden">Spenden</a>
</nav>
</header>
<main class="held" id="start">
<div class="text">
<p class="dach">Flussbande · seit 2016 an der Saale</p>
<h1>Wir holen die Saale <span>zurück.</span></h1>
<p class="text__lauf">Mit Freiwilligen sammeln wir Müll aus Fluss und Ufer, pflanzen Weiden gegen Abbruchkanten und bringen Schulklassen ans Wasser. Jeder Sammeltag steht im Protokoll.</p>
<div class="ctas">
<a class="spenden" href="#spenden">Jetzt spenden</a>
<a class="knopf" href="#mitmachen">Zum nächsten Sammeltag</a>
</div>
<div class="zahlen">
<div><b>3,1 t</b><span>Müll aus Saale und Ufer</span></div>
<div><b>1.240</b><span>Freiwillige</span></div>
<div><b>46</b><span>Sammeltage</span></div>
</div>
<p class="stand">Stand: Jahresbericht 2025</p>
</div>
<p class="sr">Collage aus dem Vereinsalltag: Foto vom Sammeltag an der Peißnitz, Polaroid eines Einkaufswagens aus dem Fluss, Sammelprotokoll vom 13. September 2025 mit 164 Kilogramm, handschriftlicher Dank, Karte der Abschnitte, Gummistiefel, Weidensteckling und Aufkleber. Die Teile lassen sich mit der Maus verschieben.</p>
<div class="collage" data-collage aria-hidden="true">
<div class="stueck s-foto foto"><div class="blatt"><span class="band" style="--br:-6deg"></span><span class="pin"></span><div class="bild">
<svg viewBox="0 0 400 290" preserveAspectRatio="xMidYMax slice">
<defs>
<pattern id="r1" width="5" height="5" patternUnits="userSpaceOnUse" patternTransform="rotate(15)"><circle cx="2.5" cy="2.5" r="1.45" fill="#002e6d"/></pattern>
<pattern id="r2" width="5" height="5" patternUnits="userSpaceOnUse" patternTransform="rotate(15)"><circle cx="2.5" cy="2.5" r=".75" fill="#002e6d"/></pattern>
<pattern id="r3" width="4" height="4" patternUnits="userSpaceOnUse" patternTransform="rotate(-20)"><circle cx="2" cy="2" r="1.2" fill="#8dbbe0"/></pattern>
</defs>
<rect width="400" height="290" fill="#e8f1f7"/>
<rect width="400" height="120" fill="url(#r2)" opacity=".45"/>
<path d="M0 132c18-14 30-22 46-16 10-18 28-24 44-12 14-16 34-14 46 0 16-12 34-10 44 6 12-10 30-8 40 6 14-14 36-12 46 4 16-10 36-6 46 8 16-6 30-2 38 8v38H0z" fill="url(#r1)"/>
<path d="M0 160h400v58H0z" fill="url(#r3)"/>
<path d="M0 160h400v58H0z" fill="#8dbbe0" opacity=".5"/>
<g stroke="#002e6d" stroke-width="1.6" opacity=".7"><path d="M20 172h70M140 178h110M290 170h80M60 190h120M220 196h60M310 188h70M30 206h50M160 210h140"/></g>
<path d="M0 214c60-10 120-8 200-2s140 4 200-4v82H0z" fill="#e8f1f7"/>
<g stroke="#002e6d" stroke-width="1.4" fill="none" opacity=".75"><path d="M14 236l-4-14M22 238l2-16M120 232l-5-12M340 230l4-14M352 232l-2-12M386 236l3-12"/></g>
<!-- Säcke -->
<g transform="translate(202 228)"><path d="M0 40c-6-22 4-38 22-38 6-6 12-6 16 0 18 2 24 18 18 38z" fill="url(#r1)"/><path d="M34 42c-4-18 4-30 18-30 4-5 10-5 13 0 14 2 18 14 14 30z" fill="#002e6d"/><path d="M-24 42c-4-16 4-26 16-26 3-4 8-4 11 0 12 2 15 12 11 26z" fill="url(#r1)"/></g>
<!-- Menschen, leicht versetzt gedruckt wie Riso -->
<g fill="#8dbbe0" transform="translate(2.5 1.5)">
<g transform="translate(78 286)"><circle cy="-70" r="8"/><path d="M-11-60h22l3 34h-28z"/><path d="M-9-27h7v27h-7zM2-27h7v27H2z"/></g>
<g transform="translate(142 282)"><circle cy="-66" r="7.5"/><path d="M-10-57h20l3 32h-26z"/><path d="M-8-26h6v26h-6zM2-26h6v26H2z"/></g>
<g transform="translate(300 284)"><circle cy="-68" r="8"/><path d="M-11-58h22l3 33h-28z"/><path d="M-9-26h7v26h-7zM2-26h7v26H2z"/></g>
<g transform="translate(352 286)"><circle cy="-56" r="6.5"/><path d="M-9-48h18l2 26h-22z"/><path d="M-7-23h6v23h-6zM1-23h6v23H1z"/></g>
</g>
<g fill="#002e6d" stroke="#002e6d" stroke-linecap="round">
<g transform="translate(78 286) rotate(-9)"><circle cy="-70" r="8"/><path d="M-9-79a9 6 0 0 1 18 0h5v3H-9z"/><path d="M-11-60h22l3 34h-28z"/><path d="M-9-27h7v27h-7zM2-27h7v27H2z"/><path d="M10-52l22 20M30-34l8 34" fill="none" stroke-width="2.5"/></g>
<g transform="translate(142 282)"><circle cy="-66" r="7.5"/><path d="M-10-57h20l3 32h-26z"/><path d="M-8-26h6v26h-6zM2-26h6v26H2z"/><path d="M-10-48l-14 22" fill="none" stroke-width="2.5"/><path d="M-30-30c-2 12 0 22 8 26h12c6-6 6-16 2-26z" fill="url(#r1)" stroke="none"/></g>
<g transform="translate(300 284)"><circle cy="-68" r="8"/><path d="M-6-76c4-6 12-4 14 2" fill="none" stroke-width="5"/><path d="M-11-58h22l3 33h-28z"/><path d="M-9-26h7v26h-7zM2-26h7v26H2z"/><path d="M-11-50l-20 18M-31-32l-6 32" fill="none" stroke-width="2.5"/><path d="M11-50l10 18" fill="none" stroke-width="2.5"/><path d="M14-34c-4 10-2 20 4 24h14c6-6 6-16 2-24z" fill="url(#r1)" stroke="none"/></g>
<g transform="translate(352 286)"><circle cy="-56" r="6.5"/><path d="M-9-48h18l2 26h-22z"/><path d="M-7-23h6v23h-6zM1-23h6v23H1z"/></g>
</g>
<text x="18" y="30" font-family="Caveat" font-weight="600" font-size="22" fill="#002e6d">Peißnitz, Mai 2025</text>
</svg>
</div></div></div>
<div class="stueck s-karte karte"><div class="blatt"><span class="band" style="--br:8deg"></span><span class="pin"></span><div class="bild">
<svg viewBox="0 0 220 260" preserveAspectRatio="xMidYMid slice">
<defs><pattern id="kar" width="14" height="14" patternUnits="userSpaceOnUse"><path d="M14 0H0v14" fill="none" stroke="#c9dceb" stroke-width="1"/></pattern></defs>
<rect width="220" height="260" fill="url(#kar)"/>
<path d="M120-10c-10 40 20 60 6 96-8 22-40 30-44 62-4 30 30 44 26 74-3 22-24 34-20 48" fill="none" stroke="#8dbbe0" stroke-width="16" stroke-linecap="round"/>
<path d="M126 86c26 10 40 30 30 58-6 18-30 22-44 16" fill="none" stroke="#8dbbe0" stroke-width="9" stroke-linecap="round"/>
<g fill="#002e6d" font-family="Caveat" font-weight="600">
<circle cx="138" cy="118" r="11"/><text x="134" y="124" font-size="17" fill="#fff">1</text>
<circle cx="86" cy="164" r="11"/><text x="81" y="170" font-size="17" fill="#fff">2</text>
<circle cx="110" cy="232" r="11"/><text x="105" y="238" font-size="17" fill="#fff">3</text>
<text x="152" y="122" font-size="19">Peißnitz</text>
<text x="10" y="148" font-size="19">Würfelwiese</text>
<text x="128" y="236" font-size="19">Rabeninsel</text>
<text x="12" y="30" font-size="24">Unsere Abschnitte</text>
</g>
<path d="M12 38c40-4 90-4 130 0" fill="none" stroke="#002e6d" stroke-width="2" stroke-linecap="round"/>
</svg>
</div></div></div>
<div class="stueck s-sticker sticker ausschnitt"><div class="blatt"><span class="pin"></span><div class="bild">
<svg viewBox="0 0 120 120">
<defs><path id="kreis" d="M60 60m-43 0a43 43 0 1 1 86 0a43 43 0 1 1-86 0"/></defs>
<circle cx="60" cy="60" r="58" fill="#fbfaf6"/>
<circle cx="60" cy="60" r="54" fill="none" stroke="#002e6d" stroke-width="2"/>
<text font-family="Big Shoulders" font-weight="800" font-size="13.5" letter-spacing="2.2" fill="#002e6d"><textPath href="#kreis">SAALE OHNE MÜLL · SEIT 2016 · HALLE ·</textPath></text>
<path d="M34 56c4.3-4 8.7-4 13 0s8.7 4 13 0 8.7-4 13 0 8.7 4 13 0M34 68c4.3-4 8.7-4 13 0s8.7 4 13 0 8.7-4 13 0 8.7 4 13 0" fill="none" stroke="#002e6d" stroke-width="4" stroke-linecap="round"/>
</svg>
</div></div></div>
<div class="stueck s-polaroid polaroid"><div class="blatt"><span class="band" style="--br:-12deg"></span><span class="pin"></span><div class="bild">
<svg viewBox="0 0 260 250" preserveAspectRatio="xMidYMid slice">
<defs><pattern id="r4" width="4" height="4" patternUnits="userSpaceOnUse" patternTransform="rotate(30)"><circle cx="2" cy="2" r="1.1" fill="#002e6d"/></pattern></defs>
<rect width="260" height="250" fill="#cfe2f1"/>
<path d="M0 0h260v70c-40 10-90 6-130 12S40 96 0 90z" fill="url(#r4)" opacity=".75"/>
<path d="M0 150c50-8 100-4 150 2s80 2 110-4v102H0z" fill="#8dbbe0"/>
<g stroke="#002e6d" stroke-width="2" opacity=".55"><path d="M20 182h60M120 192h90M40 214h110M180 226h60"/></g>
<!-- Einkaufswagen, triefend -->
<g fill="none" stroke="#002e6d" stroke-width="4.5" stroke-linejoin="round" stroke-linecap="round">
<path d="M58 92h150l-18 72H82z"/>
<path d="M70 110h132M76 128h120M80 146h106M98 92l6 72M128 92l2 72M158 92l-2 72M186 92l-8 72"/>
<path d="M208 92l14-18h14"/>
<path d="M82 164l-6 22h116l-4-22"/>
<circle cx="92" cy="196" r="9"/><circle cx="178" cy="196" r="9"/>
</g>
<g stroke="#8dbbe0" stroke-width="3" stroke-linecap="round"><path d="M96 168v14M140 168v20M170 168v10"/></g>
<path d="M40 158c-4-20 2-38 0-56M48 160c4-18 0-30 6-44M226 156c-2-18 4-30 2-46" fill="none" stroke="#3f6b4a" stroke-width="3" stroke-linecap="round"/>
</svg>
<p class="hand">Wagen Nr. 9, Giebichensteinbrücke</p>
</div></div></div>
<div class="stueck s-zettel zettel"><div class="blatt"><span class="pin"></span><div class="bild">
<h3>Sammelprotokoll</h3>
<p>Sa 13.09.2025 · Abschnitt 1<br>Peißnitz bis Würfelwiese</p>
<dl>
<dt>Freiwillige</dt><dd>84</dd>
<dt>Glas</dt><dd>38 kg</dd>
<dt>Kunststoff</dt><dd>61 kg</dd>
<dt>Metall</dt><dd>22 kg</dd>
<dt>Sonstiges</dt><dd>43 kg</dd>
<dt>Einkaufswagen</dt><dd>1</dd>
<dt>Fahrräder</dt><dd>2</dd>
<dt class="summe">Gesamt</dt><dd class="summe">164 kg</dd>
</dl>
<svg class="stempel" viewBox="0 0 120 120">
<defs><path id="st" d="M60 60m-41 0a41 41 0 1 1 82 0a41 41 0 1 1-82 0"/></defs>
<circle cx="60" cy="60" r="55" fill="none" stroke="#002e6d" stroke-width="3"/>
<circle cx="60" cy="60" r="31" fill="none" stroke="#002e6d" stroke-width="1.5"/>
<text font-family="Big Shoulders" font-weight="800" font-size="12" letter-spacing="2" fill="#002e6d"><textPath href="#st">GEPRÜFT · FLUSSBANDE E.V. · KASSE ·</textPath></text>
<text x="60" y="66" text-anchor="middle" font-family="Big Shoulders" font-weight="800" font-size="18" fill="#002e6d">✓ 09/25</text>
</svg>
</div></div></div>
<div class="stueck s-notiz notiz"><div class="blatt"><span class="band" style="--br:3deg"></span><span class="pin"></span><div class="bild hand">
84 Leute am Samstag! Danke euch. Nächster Sammeltag: 18. April, 10 Uhr am Peißnitzhaus. <br>– Ronja
</div></div></div>
<div class="stueck s-stiefel ausschnitt"><div class="blatt"><span class="pin"></span><div class="bild">
<svg viewBox="0 0 200 240">
<path d="M58 8h64c6 0 8 4 8 10l-4 120c18 10 50 18 62 34 6 8 6 22 2 30H36c-8 0-12-6-12-14l14-170c1-6 6-10 20-10z" fill="#3f6b4a"/>
<path d="M58 8h64c6 0 8 4 8 10v18H50l2-18c1-6 2-10 6-10z" fill="#33593d"/>
<path d="M66 50l-8 130" stroke="#6f9a78" stroke-width="7" stroke-linecap="round" opacity=".7"/>
<path d="M24 196h168c2 8 0 14-4 20H30c-6 0-8-8-6-20z" fill="#1f3326"/>
<g fill="#6b5a43"><circle cx="150" cy="186" r="6"/><circle cx="168" cy="180" r="4"/><circle cx="90" cy="190" r="5"/><ellipse cx="120" cy="170" rx="9" ry="5"/><circle cx="60" cy="150" r="3.5"/></g>
</svg>
</div></div></div>
<div class="stueck s-steckling ausschnitt"><div class="blatt"><span class="pin"></span><div class="bild">
<svg viewBox="0 0 100 240">
<path d="M48 230l4-200" stroke="#7a5c3e" stroke-width="7" stroke-linecap="round"/>
<g fill="#5d8f55"><ellipse cx="34" cy="60" rx="18" ry="6" transform="rotate(-35 34 60)"/><ellipse cx="68" cy="48" rx="20" ry="6.5" transform="rotate(30 68 48)"/><ellipse cx="30" cy="110" rx="20" ry="6" transform="rotate(-25 30 110)"/><ellipse cx="72" cy="96" rx="18" ry="6" transform="rotate(35 72 96)"/><ellipse cx="62" cy="22" rx="16" ry="5.5" transform="rotate(60 62 22)"/></g>
<g fill="none" stroke="#7a5c3e" stroke-width="2.5" stroke-linecap="round"><path d="M48 228c-8 4-14 8-18 6M49 226c8 6 14 6 18 10M48 222c-2 8 0 12-4 16"/></g>
</svg>
</div></div></div>
</div>
</main>
<div class="pult">
<span class="werte">12 × 12 · 800 ms easeInOutCubic · +90 ms</span>
<div class="modi" role="group" aria-label="Variante der Collage">
<button type="button" data-variante="klebe" aria-pressed="true">Klebebuch</button>
<button type="button" data-variante="schnitt" aria-pressed="false">Ausschnitte</button>
<button type="button" data-variante="pinn" aria-pressed="false">Pinnwand</button>
</div>
</div>
<svg class="zeiger" data-zeiger viewBox="0 0 18 18" aria-hidden="true"><path d="M2 1.5 15.5 9.2l-6 1.3-2.9 5.6Z" fill="#fbfaf6" stroke="#002e6d" stroke-width="1.2" stroke-linejoin="round"/></svg>
<script>
(() => {
const html = document.documentElement, body = document.body;
const reduziert = () => html.classList.contains('reduziert');
const $ = (s, w = document) => w.querySelector(s);
const $$ = (s, w = document) => [...w.querySelectorAll(s)];
gsap.registerPlugin(CustomEase, Flip, Draggable);
CustomEase.create('wirkung', '0.645, 0.045, 0.355, 1'); // easeInOutCubic
const GROSS = 0.8, VERSATZ = 0.09;
const collage = $('[data-collage]');
const stuecke = $$('.stueck', collage);
const sichtbar = () => stuecke.filter(s => s.offsetParent !== null);
$$('a[href^="#"]').forEach(a => a.addEventListener('click', e => e.preventDefault()));
// Ankommen: jedes Teil fällt leicht gedreht aus der Luft auf seinen Platz
let ankunft = null;
function ankommen() {
if (ankunft) ankunft.kill();
const blaetter = sichtbar().map(s => $('.blatt', s));
gsap.set(blaetter, { clearProps: 'transform,opacity' });
if (reduziert()) return;
ankunft = gsap.from(blaetter, { opacity: 0, y: -22, scale: 1.08, rotation: i => (i % 2 ? 6 : -6), duration: GROSS, ease: 'wirkung', stagger: VERSATZ, clearProps: 'transform,opacity' });
}
// Ziehen (Maus); auf Touch bleibt das Scrollen frei
const kannZiehen = matchMedia('(hover: hover) and (pointer: fine)').matches;
let oben = 10;
const ziehbar = kannZiehen ? Draggable.create(stuecke, {
type: 'x,y', bounds: '.held', edgeResistance: .7,
onPress() { this.target.style.zIndex = ++oben; },
}) : [];
// Varianten per Flip: Platz im Raster wechselt, Drehung gleitet per CSS mit
const VARIANTEN = { klebe: 'v-klebe', schnitt: 'v-schnitt', pinn: 'v-pinn' };
let variante = 'klebe';
function setzeVariante(v, { sofort = false } = {}) {
if (v === variante) return;
variante = v;
$$('[data-variante]').forEach(b => b.setAttribute('aria-pressed', String(b.dataset.variante === v)));
gsap.set(stuecke, { x: 0, y: 0 }); // gezogene Lage wird nicht übernommen
const zustand = Flip.getState(stuecke);
Object.values(VARIANTEN).forEach(k => body.classList.remove(k));
body.classList.add(VARIANTEN[v]);
if (sofort || reduziert()) return;
Flip.from(zustand, { duration: GROSS, ease: 'wirkung', stagger: VERSATZ / 3, nested: false });
}
$$('[data-variante]').forEach(b => b.addEventListener('click', () => { if (laeuft) neustart(); setzeVariante(b.dataset.variante); }));
/* ---------- Vorführung ---------- */
const zeiger = $('[data-zeiger]');
let uhren = [], laeuft = false, runde = 0, zpos = { x: 0, y: 0 }, zTween = null;
const nach = (ms, fn) => uhren.push(setTimeout(fn, ms));
const zeigerSetzen = () => { zeiger.style.transform = `translate(${zpos.x - 2}px, ${zpos.y - 1}px)`; };
function fahre(el, ms = 700, fx = .5, fy = .45) {
if (!el) return;
const r = el.getBoundingClientRect();
if (zTween) zTween.kill();
zTween = gsap.to(zpos, { x: r.left + r.width * fx, y: r.top + r.height * fy, duration: ms / 1000, ease: 'wirkung', onUpdate: zeigerSetzen });
}
const druecke = (an) => zeiger.classList.toggle('drueckt', an);
function heben(el, an) { stuecke.forEach(s => s.classList.toggle('gehoben', an && s === el)); }
function stoppe() { uhren.forEach(clearTimeout); uhren = []; if (zTween) zTween.kill(); gsap.killTweensOf(stuecke); }
function rundeSpielen() {
if (!laeuft) return;
const reihe = ['klebe', 'schnitt', 'pinn'];
setzeVariante('klebe', { sofort: true });
gsap.set(stuecke, { x: 0, y: 0 });
ankommen();
const foto = $('.s-foto'), pola = $('.s-polaroid'), notiz = $('.s-notiz');
nach(1300, () => fahre(foto, 700, .45, .5));
nach(2000, () => heben(foto, true));
nach(3000, () => { heben(foto, false); fahre(pola, 600, .5, .3); });
nach(3700, () => {
if (reduziert() || !pola.offsetParent) return;
druecke(true); heben(pola, true); pola.style.zIndex = ++oben;
const dx = -pola.offsetWidth * .9, dy = pola.offsetHeight * .18;
gsap.to(pola, { x: dx, y: dy, duration: 1, ease: 'wirkung', onUpdate() { const r = pola.getBoundingClientRect(); zpos.x = r.left + r.width * .5; zpos.y = r.top + r.height * .3; zeigerSetzen(); } });
});
nach(4900, () => { druecke(false); heben(pola, false); fahre(notiz, 700, .6, .6); });
nach(5900, () => setzeVariante(reihe[1]));
nach(7900, () => setzeVariante(reihe[2]));
nach(9900, () => setzeVariante(reihe[0]));
nach(11400, () => { runde++; rundeSpielen(); });
}
function neustart() {
stoppe(); laeuft = false; html.classList.remove('vorfuehrung'); heben(null, false); druecke(false);
setzeVariante('klebe', { sofort: true }); gsap.set(stuecke, { x: 0, y: 0 }); ankommen();
}
function vorfuehren() {
stoppe(); laeuft = true; runde = 0;
html.classList.add('vorfuehrung');
zpos = { x: innerWidth * .4, y: innerHeight * .8 }; zeigerSetzen();
rundeSpielen();
}
function pause() { stoppe(); laeuft = false; }
function weiter() { if (html.classList.contains('vorfuehrung') && !laeuft) { laeuft = true; rundeSpielen(); } }
ankommen();
})();
</script>
</body>
</html>