FlipArt ist ein universelles Klapp-Display für Uhrzeiten, Countdowns, Timer und Text.
Konfiguration erfolgt entweder vollständig deklarativ über data-*-Attribute
oder programmatisch über JavaScript. Auto-Init beim DOM-ready inklusive.
Ab jetzt rendert FlipArt in einen Shadow Root pro Instanz. Das gesamte
Painting liegt gekapselt im Widget - CSS der einbettenden Seite kann die interne
Darstellung nicht mehr überschreiben. Rohe Tag- oder Nachfahren-Selektoren wie
.panel div oder section * greifen nicht mehr durch (kein
dunkel-auf-dunkel, keine Fremd-Borders).
flipclock.css enthält jetzt ausschließlich Theme-Tokens
(CSS Custom Properties). Diese werden am .flipart-Host gesetzt, vererben über
die Shadow-Grenze und bleiben von außen überschreibbar. Theming läuft daher weiterhin
komplett über data-flip-theme und die --fa-*-Variablen - nur eben
nicht mehr über CSS auf die internen .fa-*-Klassen.
data-flip-*-Attribute und das Datenformat sind identisch zu v1.el.shadowRoot statt direkt über das Element.!important- oder höher-spezifischer Seiten-Selektor auf .flipart selbst (z.B. font-size zum Skalieren) wirkt weiterhin - das ist gewollt, nicht ein Leak.CSS und JS einbinden, ein Element mit Klasse .flipart anlegen - fertig.
<link rel="stylesheet" href="flipclock.css">
<script src="flipclock.js" defer></script>
<div class="flipart"
data-flip-mode="clock"
data-flip-format="HH:II:SS"></div>
Das Format-String beschreibt, welche Zeit-Einheiten angezeigt werden und welche Trennzeichen dazwischen stehen. Tokens werden 1:1 ausgetauscht, alles andere bleibt als Literal stehen.
| Token | Bedeutung | Default-Stellen |
|---|---|---|
YYYY | Jahre | 4 |
MM | Monate (1–12 im Clock-Mode) | 2 |
DD | Tage | 2 |
HH | Stunden | 2 |
II | Minuten (analog zu PHP date('i')) | 2 |
SS | Sekunden | 2 |
Ein Token in eckigen Klammern (z.B. [DD]) startet mit der
Default-Stellenzahl, wächst aber nach links wenn der Wert mehr Ziffern braucht.
Sinnvoll nur für das erste Token, da nur dieses die übergeordneten
Zeit-Anteile aufaddiert bekommt und damit überlaufen kann.
"DD HH II SS" → bei 5000 Tagen wird zu "00" truncated (max 99 Tage)
"[DD] HH II SS" → wächst auf "5000" Tage
"YYYY-MM-DD" → ISO-Datum
"DD.MM.YYYY HH:II:SS" → klassisches DE-Format mit Uhr
| Modus | Beschreibung | Pflicht-Attribute |
|---|---|---|
clock |
Aktuelle Uhrzeit. Alle Tokens im Format werden auf die jeweilige Komponente von new Date() gemappt. |
- |
countdown |
Runter zu einem Zieldatum. | data-flip-target |
countup |
Hoch ab einem Startdatum. | data-flip-target |
timer |
Reiner Sekunden-Countdown ab Aufruf. | data-flip-duration |
text |
Statischer oder zyklisch wechselnder Text. | data-flip-text oder data-flip-cycle-texts |
Bei countdown und countup entscheidet das erste Token
im Format, wie die Differenz aufgeteilt wird:
Das erste Token bekommt zudem alle übergeordneten Anteile aufaddiert - bei
"HH II SS" akkumulieren z.B. ganze Tage in der Stundenzahl.
Beim Wechsel zwischen Texten klappert jedes Tile durch alle Zwischen-Zeichen
seines Sets - wie eine alte Flughafen-Anzeigetafel. Beispiel: U auf
R wechseln läuft U → V → W → X → Y → Z → A → B → … → Q → R
(forward, mit Wrap durchs Alphabet).
Drei Zeichen-Sets sind hardcoded: A–Z, a–z, 0–9. Jedes Tile
scrambelt nur innerhalb des Sets, in dem sein Zielzeichen liegt. Cross-Set-Wechsel
(z.B. O → ! oder ' ' → A) werden als einzelner
direkter Flip behandelt.
<div class="flipart"
data-flip-mode="text"
data-flip-text="ARRIVAL"
data-flip-cycle="3500"
data-flip-cycle-texts='["ARRIVAL","BOARDING","ENROUTE ","DEPARTED"]'
data-flip-scramble="true"
data-flip-scramble-step="55"></div>
Während des Scramble läuft jedes Tile mit der durch data-flip-scramble-step
vorgegebenen Schritt-Dauer (Default 60 ms). Damit die einzelnen
Klapp-Animationen rechtzeitig durchrendern, setzt die Bibliothek dafür
temporär --fa-flip-duration als inline-style auf jedes Tile.
Der letzte Schritt jedes Tiles bekommt die volle Animations-Dauer zurück - das Zielzeichen klappt damit als sichtbarer Abschluss langsamer ein. Tiles mit kürzerem Pfad sind früher fertig, Tiles mit langem Pfad scramblen weiter.
flipclock.css die Animation über --fa-flip-duration
parametrisieren - z.B.:
animation: flip-down var(--fa-flip-duration, 0.6s) ease-in-out forwards;
Falls die Variable im CSS nicht referenziert wird, läuft jeder Scramble-Schritt
mit der unveränderten Standard-Animations-Dauer - der Effekt wirkt dann
weniger crisp, aber die Bibliothek bricht nichts.
data-flip-cycle sollte länger sein als die maximale Scramble-Dauer
plus etwas Lese-Zeit. Worst-Case: 25 Schritte × 60 ms = 1.5 s, plus volle
finale Animation (~600 ms) → mind. ~2 s + Lese-Zeit. Bei zu
kurzem Cycle wird der laufende Scramble einfach abgebrochen und der nächste
startet - funktional ok, optisch unruhig.
pause()
Beim Pausieren mitten in einem Scramble wäre es störend, wenn die Tiles in
einem zufälligen Zwischen-Zustand stehen bleiben (BOARDING → DRMITLL).
Daher: pause() bricht den Cycle sofort ab, lässt aber den aktuellen
Scramble bis zum Zieltext durchlaufen. Erst danach ist die Instanz angehalten.
Wer hartes Stop will, ruft stop(). Außerhalb von Scramble-Übergängen
ist pause() identisch zu stop().
// Toggle-Button für Demo-Element:
el.addEventListener('click', () => {
const fa = el._flipArt;
fa.isRunning ? fa.pause() : fa.start();
});
| Wert | Verhalten |
|---|---|
forward (default) | Vorwärts durchs Set, mit Wrap am Ende. U → R = 23 Schritte. |
backward | Rückwärts. U → R = 3 Schritte. |
shortest | Wählt automatisch die kürzere der beiden Richtungen. |
| Attribut | Wert | Beschreibung |
|---|---|---|
data-flip-mode | clock | countdown | countup | timer | text | Betriebsmodus. Default: clock. |
data-flip-format | z.B. HH:II:SS | Token-Format. Default je nach Modus. |
data-flip-target | ISO-Datumsstring | Ziel- bzw. Startdatum für countdown/countup. |
data-flip-duration | Zahl (Sekunden) | Dauer für timer-Modus. |
data-flip-text | String | Initialer Text im text-Modus. |
data-flip-cycle-texts | JSON-Array oder pipe-separiert | Texte zum Durchwechseln, z.B. ["A","B","C"] oder A|B|C. |
data-flip-cycle | Zahl (ms) | Intervall des Text-Cycles. |
data-flip-scramble | true | false | Aktiviert Scramble-Effekt im text-Modus. Default false. |
data-flip-scramble-step | Zahl (ms) | Tempo der Zwischen-Klappschritte. Default 60. |
data-flip-scramble-direction | forward | backward | shortest | Klapp-Richtung. Default forward. |
data-flip-labels | de | en | off | Sprache der Einheiten-Labels oder ausschalten. |
data-flip-theme | mono | paper | neon | terminal | Vorgefertigtes Theme. Default ist Stahl-Dunkel/Bernstein. |
data-flip-autostart | false | Verhindert automatischen Start beim Init. |
Programmatische Initialisierung und Steuerung:
const fa = new FlipArt(element, {
mode: 'countdown',
target: '2026-12-31T23:59:59',
format: '[DD] HH II SS',
labels: 'de',
onComplete: (instance) => console.log('done', instance)
});
// Text-Modus mit Scramble:
const ft = new FlipArt(textEl, {
mode: 'text',
texts: ['ARRIVAL','BOARDING','ENROUTE ','DEPARTED'],
cycle: 3500,
scramble: true,
scrambleStep: 55,
scrambleDirection: 'forward'
});
fa.start(); // startet (oder neu-startet)
fa.stop(); // stoppt alle Timer
fa.update('2027-01-01'); // ändert target / duration / text
fa.destroy(); // entfernt DOM & Bindings
// Alle .flipart-Elemente nachträglich initialisieren (idempotent):
FlipArt.init();
// Optional: jQuery-Bridge
$('.flipart').flipart({ mode: 'clock' });
| Methode | Beschreibung |
|---|---|
start() | Startet den Tick-Loop. Bei clock sekunden-synchronisiert. |
stop() | Hartes Stop: bricht alle Timer und einen laufenden Scramble sofort ab. |
pause() | Sanftes Stop: bricht den Cycle ab, lässt aber einen laufenden Scramble bis zum Zieltext durchlaufen. Ohne aktiven Scramble identisch zu stop(). |
update(value) | Ändert je nach Modus target, duration oder text und re-rendert. |
destroy() | Räumt vollständig auf: stoppt Timer, leert Inhalt, löst _flipArt-Backref. |
isRunning (Getter) | Truthy, wenn ein Tick, Cycle oder austrudelnder Scramble aktiv ist. Für Toggle-Buttons. |
FlipArt.init(selector?) | Statisch. Initialisiert alle passenden Elemente. Idempotent. |
Vier vorgefertigte Themes via data-flip-theme. Plus ein Default-Look ohne
Attribut (dunkles Stahl mit bernstein-farbiger Glyph).
Alle Farben und Maße sind über CSS Custom Properties steuerbar:
.flipart.mein-theme {
--fa-bg-top: linear-gradient(180deg, #444 0%, #222 100%);
--fa-bg-bottom: linear-gradient(180deg, #1a1a1a 0%, #0a0a0a 100%);
--fa-color: #ff5500;
--fa-divider: rgba(0, 0, 0, 0.7);
--fa-radius: 0.15em;
--fa-tile-w: 0.9em;
--fa-tile-h: 1.3em;
--fa-tile-gap: 0.08em;
--fa-group-gap: 0.6em;
}
Skalierung erfolgt über font-size auf dem .flipart-Container - alle
internen Maße sind in em definiert. Die Bibliothek snappt die Werte zur Laufzeit
auf das Device-Pixel-Raster, um Subpixel-Artefakte beim Klappen zu vermeiden.
Da das Painting gekapselt ist, ist das der einzige Weg zum Theming:
CSS auf die internen .fa-*-Klassen wirkt nicht mehr. Eigene Themes also immer
als --fa-*-Overrides auf .flipart bzw. .flipart[data-flip-theme="…"] schreiben.
prefers-reduced-motion: reduce wird die
Klapp-Animation auf 1ms verkürzt - Werte ändern sich, aber ohne sichtbare Animation.FlipArt.init() kann beliebig oft aufgerufen werden,
bereits initialisierte Elemente werden übersprungen.clock-Modus startet seinen Tick exakt zum nächsten
Sekundenwechsel, damit die Anzeige nicht „zwischen den Sekunden" steht..flipart in Tabs, Accordions, Modals oder
<details> funktioniert problemlos. Ein ResizeObserver snappt die Pixel-Maße
neu, sobald das Element wieder sichtbar wird.timer-Mode mit Token YYYY/MM wird nicht
kalender-genau gerechnet (nur countdown/countup nutzen _splitCalendar).el.shadowRoot. Seiten-CSS auf nackte Tags oder .fa-*-Klassen bleibt wirkungslos.