# CSS-Framework — CSS Framework für Jinja2 / HTMX Webapps Ein schlankes CSS-Framework für konsistente, moderne Webapplikationen. Classless wo möglich, opt-in Klassen wo nötig. Gebaut für Jinja2-Templates und HTMX-Interaktionen. --- ## Dateien & Struktur ``` framework/ ├── tokens.css — Design Tokens (CSS Custom Properties) ├── base.css — Classless Reset + semantische HTML-Elemente ├── components.css — Opt-in Komponenten-Klassen ├── utilities.css — Minimale Helfer-Klassen ├── main.css — Entry Point (importiert alle vier) └── fonts.css — Template für lokale Google Fonts (optional) ``` **Einbinden in Projekten:** ```html ``` --- ## Design Tokens (`tokens.css`) Alle Designentscheidungen sind als CSS Custom Properties definiert. **Zentrale Anlaufstelle für alle Anpassungen.** ### Farbsystem Zweischichtig aufgebaut: Rohe Palette + Semantische Aliases. ```css /* Nie direkt verwenden — nur als Rohwerte */ --color-accent-500: #6366f1; /* Diese verwenden — semantische Bedeutung */ --accent: var(--color-accent-500); --accent-hover: var(--color-accent-600); --accent-subtle: var(--color-accent-50); ``` **Primärfarbe anpassen:** Nur `--color-accent-*` in `tokens.css` ändern — alle Komponenten folgen automatisch. | Token | Verwendung | |---|---| | `--bg`, `--bg-subtle`, `--bg-muted` | Seitenhintergründe | | `--surface`, `--surface-raised`, `--surface-overlay` | Karten, Modals, Dropdowns | | `--border`, `--border-strong`, `--border-focus` | Rahmenlinien | | `--text`, `--text-muted`, `--text-subtle` | Texthierarchie | | `--accent`, `--accent-hover`, `--accent-active` | Primärfarbe + Zustände | | `--color-success/warning/danger/info` | Semantische Status-Farben | ### Dark Mode Nur semantische Aliases werden überschrieben — Rohpalette bleibt unverändert. ```html ``` ```css [data-theme="dark"] { --bg: var(--color-black); --surface: #161920; --text: var(--color-gray-100); /* ... alle Aliases werden überschrieben --> } ``` Umschalten und Speichern übernimmt `theme.js` (siehe „JavaScript API → Theme“), ohne Inline-Skript. ### Spacing 4px-Grid, 12 Stufen: `--space-1` (4px) bis `--space-24` (96px). ```css --space-1: 0.25rem; /* 4px */ --space-2: 0.5rem; /* 8px */ --space-4: 1rem; /* 16px */ --space-6: 1.5rem; /* 24px */ --space-8: 2rem; /* 32px */ ``` ### Typografie ```css --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif; --font-mono: "JetBrains Mono", ui-monospace, monospace; --text-xs: 0.75rem; /* 12px */ --text-sm: 0.875rem; /* 14px */ --text-base: 1rem; /* 16px */ --text-lg: 1.25rem; /* 20px */ --text-xl: 1.5rem; /* 24px */ --text-2xl: 1.875rem; /* 30px */ --text-3xl: 2.25rem; /* 36px */ --text-4xl: 3rem; /* 48px */ ``` ### Weitere Token-Gruppen | Gruppe | Tokens | |---|---| | Border Radius | `--radius-sm/md/lg/xl/2xl/full` | | Schatten | `--shadow-xs/sm/md/lg/xl`, `--shadow-focus` | | Übergänge | `--duration-fast/base/slow`, `--ease/ease-out/ease-in`, `--transition` | | Layout | `--container-sm/md/lg/xl/2xl`, `--nav-height`, `--sidebar-width` | | Z-Index | `--z-base/raised/dropdown/sticky/overlay/modal/toast` | --- ## Classless Base (`base.css`) Semantisches HTML benötigt **keine Klassen** für grundlegendes Styling. Einfach valides HTML schreiben: ```html

Überschrift

Text mit fett, kursiv, Link, Code.

Zitat— Autor
...
AkkordeonInhalt
``` **Gestylt ohne Klassen:** `h1–h6`, `p`, `a`, `strong`, `em`, `small`, `mark`, `kbd`, `code`, `pre`, `blockquote`, `hr`, `ul`, `ol`, `dl`, `table`, `thead`, `tbody`, `tfoot`, `th`, `td`, `input`, `textarea`, `select`, `fieldset`, `legend`, `label`, `details`, `summary`, `figure`, `figcaption`, `img`. Checkboxen und Radios behalten die native Darstellung des Browsers und werden über `accent-color` in `--accent` eingefärbt (hell wie dunkel). --- ## Komponenten (`components.css`) Opt-in Klassen für alles was semantisches HTML nicht abdeckt. ### Layout ```html
``` ### Navigation #### Breadcrumbs (`.breadcrumbs`) ```html ``` Semantischer Navigationspfad für hierarchische Seiten. Nutzt vorhandene Text-, Radius- und Surface-Tokens, trennt Einträge per Slash und bleibt auf schmalen Viewports horizontal scrollbar. #### Top Navigation (`.topnav`) ```html ``` **Modifier:** `.topnav-static` (nicht sticky) #### Sidebar (`.sidebar`) ```html ``` **Mobile Sidebar-Overlay (< 64rem):** Bei schmalen Viewports bricht `.with-sidebar` das Grid um. Die Sidebar wird dabei per JavaScript als festes Overlay eingeblendet. Benötigte HTML-Elemente: ```html
Meine App
...
``` JavaScript (im Basis-Template eintragen): ```js document.getElementById('sidebar-toggle') .addEventListener('click', () => document.body.classList.add('sidebar-open')); document.getElementById('sidebar-backdrop') .addEventListener('click', () => document.body.classList.remove('sidebar-open')); ``` #### Footer (`.footer`) ```html ``` ### Buttons (`.btn`) ```html Link-Button
``` Die Button Group fasst normale .btn-Elemente bündig zusammen. Die Segmented Control bleibt technisch eine Gruppe nativer Radio-Inputs und eignet sich für Filter, Ansichten und Moduswechsel ohne JavaScript. ### Badges (`.badge`) ```html Standard Primär Erfolg Warnung Fehler Info Outline Live ``` ### Cards (`.card`) ```html

Titel

Aktiv
Inhalt
``` **Varianten:** `.card-flat`, `.card-raised`, `.card-ghost` **Hover-Effekt:** `.card.card-hover` **Image Card:** ```html
...
...
``` ### Formulare ```html
Wird für Login genutzt.
Mindestens 8 Zeichen.
...
...
https://
Die Datei wird beim Absenden des Formulars normal übertragen.
Bitte nur Logos im SVG- oder PNG-Format verwenden.
``` Die Formular-Helfer decken damit einfache Gruppen, Hinweise, Fehlerstates, Switches und auch ein natives File-Upload-Pattern ab. `.file-upload` kapselt den klickbaren Bereich, `.file-upload-dropzone` schaltet auf eine gestrichelte Dropzone-Optik um und `.is-error` markiert visuell fehlerhafte Upload-Felder, ohne dass dafür JavaScript nötig ist. ### Accordion ```html
Was ist ein classless Framework?

Ein classless Framework stylt HTML-Elemente direkt.

Die Accordion-Komponente organisiert mehrere details-Elemente als zusammengehörige Gruppe.

Wie passe ich Farben an?

Farben und semantische Aliases werden in tokens.css gepflegt.

...
...
``` Das Pattern baut bewusst auf nativen details- und summary-Elementen auf. .accordion organisiert Abstände und Gruppierung, .accordion-body kapselt den Inhaltsbereich, und die Varianten .accordion-flush sowie .accordion-muted decken kompaktere oder weichere Darstellungen ab. ### Sortierbare Tabellen ```html ...
Name Datum Status
``` Erkennt automatisch numerische vs. alphabetische Werte. Deutsche Sortierung via `localeCompare`. ### Tabellen ```html
NameStatus
AnnaAktiv
...
...
...
...
...
NameStatus
Anna Aktiv
``` ### Alerts ```html
...

Hinweis

Deine Daten werden gespeichert.

``` **Varianten:** `alert-info`, `alert-success`, `alert-warning`, `alert-danger` **Dismissible Alert:** ```html

Erfolgreich

Deine Änderungen wurden gespeichert.

``` ```js function dismissAlert(btn) { const alert = btn.closest('.alert'); alert.classList.add('is-dismissing'); alert.addEventListener('transitionend', () => alert.remove(), { once: true }); } ``` ### Modals ```html ``` **Größen:** `.modal-sm`, `.modal-lg`, `.modal-xl` ### Tabs ```html
Inhalt 1
Inhalt 2
``` ### Dropdowns ```html ``` **Varianten:** `.dropdown-menu-left`, `.dropdown-menu-top`, `.dropdown-wide` **Spezielle Item-Typen:** ```html ``` ### Pagination ```html ``` ### Feedback & Status ```html
Umsatz € 48.291 ↑ +12.4%
Saldo + € 1.240
Saldo − € 320
AM
AM
AM
BS
...

Keine Einträge

Erstelle deinen ersten Eintrag.

oder
``` ### Tooltip ```html ``` CSS-only via `data-tooltip`-Attribut. Kein JavaScript nötig. Funktioniert auf jedem Element, reagiert auch auf `:focus-visible`. ### Meta List / Definition List (`.meta-list`) ```html
Status
Aktiv
Erstellt am
12. Januar 2025
``` **Varianten:** `.meta-list-stacked` (Label über Wert), `.meta-list-compact`, `.meta-list-flush` (kein oberer Border) ### Filter Chips (`.chip-group`) ```html
...
``` ### Timeline / Activity Feed (`.timeline`) ```html

Deployment abgeschlossen

vor 2 Stunden

Version 2.4.1 ist live.

``` **Dot-Varianten:** `timeline-accent`, `timeline-success`, `timeline-warning`, `timeline-danger` ### Stepper / Progress Steps (`.stepper`) ```html
✓
Konto
2
Profil
3
Fertig
✓

Konto anlegen

E-Mail und Passwort festlegen.

...
``` **Step-Modifier:** `.step-done`, `.step-active` ### List Group / Action List ```html
  • Dashboard
  • Projekte
  • Archiv
``` **Varianten:** `.list-group-compact`, `.action-list-compact`, `.list-group-flush`, `.action-list-flush` --- ## Utilities (`utilities.css`) Minimale Helfer — bewusst schlank gehalten. ```html
...
...

Kleiner Hilfstext

Langer Text wird abgeschnitten

Akzentfarbe

Status-Farben

...
Schiebt nach rechts
...
...
Nur für Screenreader ``` --- ## JavaScript API `framework.js` bietet jede Funktion auf zwei Wegen an: 1. **Deklarativ über `data-action`** (empfohlen). Ein einziger Listener am `document` wertet die Attribute aus. Das funktioniert unter einer strengen Content Security Policy und auch für Inhalte, die HTMX später nachlädt. 2. **Als globale Funktion**, z. B. `openModal('m')`, für eigene Skripte. Inline-Handler wie `onclick="…"` gehen zwar weiterhin, verlangen aber `'unsafe-inline'` in der CSP. ```html ``` ### Aktionen | `data-action` | Weitere Attribute | Wirkung | Entspricht | |---|---|---|---| | `modal-open` | `data-target="id"` | Modal öffnen, Seite nicht mehr scrollen | `openModal(id)` | | `modal-close` | `data-target="id"` (optional, sonst umgebendes Modal) | Modal schließen | `closeModal(id)` | | `modal-backdrop` | auf `.modal-backdrop` mit `id` | Klick auf den Hintergrund schließt | `closeOnBackdrop(e, id)` | | `tab` | `data-target="panel-id"` | Tab wechseln | `switchTab(btn, id)` | | `dropdown` | `data-target="id"` (optional, sonst umgebendes `.dropdown`) | Dropdown öffnen/schließen | `toggleDropdown(id)` | | `nav-dropdown` | – | Nav-Dropdown öffnen/schließen | `toggleNavDd(btn)` | | `sidebar-open` / `sidebar-close` | – | Mobile Sidebar ein-/ausblenden | `toggleSidebar()` / `closeSidebar()` | | `alert-dismiss` | – | Alert mit Transition entfernen | `dismissAlert(btn)` | | `sort` | auf `th`, mit `data-sort=""` | Spalte sortieren | `sortTable(th)` | | `toggle-class` | `data-class="checked"` | Klasse am Element umschalten | – | | `toast` | `data-message="…"`, `data-type="success"` | Toast einblenden | `showToast(msg, type)` | | `toast-close` | – | Toast schließen (setzt `showToast` selbst) | `removeToast(id)` | | `theme-toggle` | – | Hell/Dunkel umschalten (`theme.js`) | – | ### Funktionsübersicht | Funktion | Beschreibung | |---|---| | `openModal(id)` | Modal öffnen, Scroll sperren (`body.modal-open`) | | `closeModal(id)` | Modal schließen | | `closeOnBackdrop(e, id)` | Modal schließen, wenn der Klick auf dem Hintergrund lag | | `switchTab(btn, panelId)` | Tab wechseln | | `toggleDropdown(id)` | Dropdown öffnen/schließen | | `toggleNavDd(btn)` | Nav-Dropdown öffnen/schließen | | `showToast(message, type)` | Toast einblenden (`type`: `'success'`, `'warning'`, `'danger'`, `'info'`). Die Meldung wird als Text gesetzt, HTML darin nicht ausgeführt | | `removeToast(id)` | Toast ausblenden und entfernen | | `dismissAlert(btn)` | Alert mit Transition entfernen | | `sortTable(th)` | Tabellenspalte auf-/absteigend sortieren | | `toggleSidebar()` | Mobile Sidebar einblenden | | `closeSidebar()` | Mobile Sidebar ausblenden | ESC schließt automatisch alle offenen Modals. Klick außerhalb schließt Dropdowns. ### Theme (`theme.js`) `theme.js` setzt Hell/Dunkel vor dem ersten Rendern (gespeicherter Wert, sonst `prefers-color-scheme`) und schaltet bei `data-action="theme-toggle"` um. Im `` **ohne** `defer` einbinden. Die Icons wechseln per CSS: `.icon-theme-light` ist im hellen, `.icon-theme-dark` im dunklen Modus sichtbar. ```html … ``` ### Content Security Policy Das Framework läuft unter einer strengen CSP ohne `'unsafe-inline'` und ohne `'unsafe-eval'`: ``` default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: ``` Dafür gilt: - Keine `on…`-Attribute, sondern `data-action`. - Keine `style`-Attribute, sondern Klassen (Tokens, Utilities, z. B. `min-w-0`, `skeleton-line`). - Kein Inline-` ``` `framework.js` enthält alle Funktionen und den Listener für `data-action` (Modal, Toast, Tabs, Dropdown usw.), `theme.js` das Umschalten von Hell/Dunkel — kein weiterer Setup-Schritt nötig. ### 3. KI-Guidance mitgeben (OpenCode) Den `.opencode/`-Ordner aus diesem Repo ins Consumer-Projekt kopieren: ``` .opencode/ ├── commands/ — Prompt-Checklisten für neue Komponenten, Tokens, Sync └── skills/ ├── SKILL.md — Schnellreferenz (wird beim Skill-Aufruf geladen) └── references/ — Vollständige Referenzen für Komponenten, Tokens, Jinja2 ``` Außerdem `AGENTS.md` ins Projektstamm-Verzeichnis kopieren — sie enthält die verbindlichen Arbeitsregeln für KI-Agenten. ### 4. Basis-Template einrichten Das fertige `base.html` für FastAPI + Jinja2 + HTMX liegt in `.opencode/skills/references/jinja2.md`. Es enthält: - Theme-Toggle über `theme.js` (CSP-fest, ohne Inline-Skript) - Sidebar-Layout mit Mobile-Overlay - Alle Aktionen über `data-action` (CSP-fest) - HTMX-Einbindung ### 5. Version prüfen Die aktuelle Framework-Version steht im Kommentar von `main.css`. Beim Aktualisieren des Frameworks einfach die CSS-Dateien ersetzen — keine Build-Schritte nötig.