Zum Inhalt springen
    WingoUI
    KomponentenVorlagenDokuPreiseKI-AgentenBlogChangelog
    1. Startseite
    2. Blog
    3. Mobile UI mit React
    4. React Floating Action Button: Speed Dial und Safe Areas
    Read in English
    1. Blog
    2. Mobile UI mit React
    3. React Floating Action Button: Speed Dial und Safe Areas
    Mobile UI mit React
    Mobile UI mit React

    React Floating Action Button: Speed Dial und Safe Areas

    SR
    Serban Rusu · Gründer von Wingo UI
    16. Okt. 2026 · 9 Min. Lesezeit

    Auf dieser Seite

    0%
    1. Wann braucht ein Screen einen Floating Action Button?
    2. Wie installiere und rendere ich einen einfachen FAB?
    3. Wie funktioniert ein React FAB Speed Dial?
      1. Vertikal oder radial?
    4. Wie lasse ich einen Extended FAB beim Scrollen einklappen?
    5. Wie staple ich einen FAB über Tab-Leiste, Kaufleiste und Home-Indikator?
    6. Was braucht ein FAB für Tastatur- und Screenreader-Nutzer?
    7. Was sind die häufigsten Fehler beim Floating Action Button?
    8. Was baue ich als Nächstes?
    9. Häufige Fragen
      1. Wie viele Aktionen sollte ein FAB Speed Dial haben?
      2. Soll sich ein Floating Action Button beim Scrollen verstecken?
      3. Hat shadcn/ui einen Floating Action Button?
      4. Wie halte ich einen FAB über einer Bottom Navigation Bar?
      5. Ist der FAB von Wingo UI kostenlos?

    Kurz gesagt

    Ein React Floating Action Button ist ein einzelner runder Button unten in der Ecke für die Hauptaktion des Screens, der auf Wunsch ein Speed Dial mit 2 bis 6 verwandten Aktionen als Menü öffnet. Im Web muss er außerdem sein Label beim Scrollen einklappen, über einer Bottom Tab Bar, einer festen Kaufleiste und dem Home-Indikator des iPhones sitzen, ohne die Safe Area doppelt zu zählen, und mit Tastatur und Screenreader funktionieren. Der FAB von Wingo UI deckt das über Props ab: actions, layout="vertical" oder "radial", extended="auto" und hideOnScroll.

    Veröffentlicht am 16. Okt. 2026

    Ein React Floating Action Button wirkt wie die einfachste Komponente auf einem Smartphone-Screen: ein runder Button, position: fixed, bottom: 16px, right: 16px. Dann wächst das Produkt. Aus einer Aktion zum Anlegen werden vier, das Label verdeckt die Liste, der Button landet auf der Tab-Leiste, auf der Produktseite kommt eine Kaufleiste dazu, und unten sitzt der Home-Indikator des iPhones. Dieser Guide löst jeden dieser Punkte mit dem FAB von Wingo UI: wann ein FAB das richtige Bedienelement ist, das vertikale und das radiale Speed Dial, das Label, das beim Scrollen einklappt, das Stapeln über der Bottom Tab Bar und der Sticky CTA Bar und die Details zur Barrierefreiheit, die die meisten Beispiele weglassen.

    Wann braucht ein Screen einen Floating Action Button?

    Wenn es auf dem Screen eine Aktion gibt, die Leute viel öfter ausführen als jede andere, und diese Aktion etwas Neues anlegt: einen Kunden, eine Nachricht, ein Inserat. Die FAB-Doku von Material Components (opens in a new tab) beschreibt ihn als den Button für die wichtigste oder häufigste Aktion eines Screens, und die FAB-Doku von MUI (opens in a new tab) ergänzt, dass pro Screen nur einer empfohlen wird. Eine Einstellungsseite, ein Checkout oder ein Formular mit eigenem Absenden-Button braucht keinen.

    Genau darum sitzt er unten in der Ecke. In Steven Hoobers Feldstudie von 2013 (opens in a new tab) (1.333 Beobachtungen von Menschen an mobilen Geräten) hielten 49 % der Leute, die den Screen berührten, das Smartphone in einer Hand. Ein Button zum Anlegen in der oberen Leiste ist weit weg von diesem Daumen, ein FAB unten in der Ecke liegt genau darunter. Auf dem Desktop gehört dieselbe Aktion meist in den Seitenkopf. Rendere den FAB also nur unter 768px (className="md:hidden"), wenn der Kopf den Button schon hat.

    Wie installiere und rendere ich einen einfachen FAB?

    Installier ihn mit der CLI. Sie kopiert components/ui/fab.tsx in dein Projekt, zusammen mit den Registry-Abhängigkeiten: dem Tooltip, vier Hooks (use-scroll-state, use-keyboard-inset, use-shortcut, use-controllable-state) und den Helfern haptics, motion, navigation, tones und ui-config. Auf der npm-Seite kommen motion und lucide-react dazu.

    bash
    npx wingo-ui@latest add fab

    Ohne actions ist der FAB ein normaler Button, und onClick ist die Aktion. Gib ihm ein label, dann startet er ausgeklappt, als Pille mit Icon und Text:

    tsx
    "use client";
    import { Pencil } from "lucide-react";
    import { Fab } from "@/components/ui/fab";
    export function ComposeFab({ onCompose }: { onCompose: () => void }) {
    return <Fab icon={<Pencil />} label="Verfassen" onClick={onCompose} className="md:hidden" />;
    }

    Die Defaults: size="md" ist ein Button mit 56px und einem Icon mit 24px (dieselben 56dp wie beim normalen FAB von Material), tone="neutral" ist im Light Mode schwarz und im Dark Mode weiß, position="fixed" heftet ihn an den Viewport, und side="end" setzt ihn auf Seiten mit Leserichtung links nach rechts an den rechten Rand und auf Seiten mit Leserichtung rechts nach links an den linken. Nimm tone="brand" nur, wenn genau diese Aktion der Grund ist, warum es den Screen gibt, etwa „Inserat aufgeben“ auf einem Marktplatz.

    Wie funktioniert ein React FAB Speed Dial?

    Übergib 2 bis 6 actions, und der Button öffnet ein Dial, statt eine Aktion auszuführen. Jede Aktion ist { id, label, icon, onSelect?, href?, tone?, disabled? }. Eine Aktion mit href rendert einen Link über linkComponent (oder den LinkProvider der App) und schließt das Dial:

    tsx
    "use client";
    import Link from "next/link";
    import { FileText, Handshake, StickyNote, UserPlus } from "lucide-react";
    import { Fab, type FabAction } from "@/components/ui/fab";
    export function ClientsFab({ onCreate }: { onCreate: (kind: string) => void }) {
    const actions: FabAction[] = [
    { id: "client", label: "Neuer Kunde", icon: <UserPlus />, onSelect: () => onCreate("client") },
    { id: "invoice", label: "Neue Rechnung", icon: <FileText />, onSelect: () => onCreate("invoice") },
    { id: "quote", label: "Neues Angebot", icon: <Handshake />, href: "/quotes/new" },
    { id: "note", label: "Notiz", icon: <StickyNote />, onSelect: () => onCreate("note") },
    ];
    return <Fab label="Hinzufügen" actions={actions} shortcut="n" linkComponent={Link} />;
    }

    Sortier das Array nach Häufigkeit: Die erste Aktion erscheint dem Daumen am nächsten. Öffnet sich das Dial, wird die Seite dahinter von einem Scrim abgedunkelt (ein Tipp darauf schließt es), das Plus dreht sich um 45 Grad zu einem x, und auf Touch-Geräten vibriert das Smartphone einmal kurz über den Haptics-Helfer. Das Label klappt ein, sobald sich das Dial öffnet, damit der Auslöser wieder der runde Button ist. Das passt zur Doku zum FAB-Menü von Material (opens in a new tab): Dort steht, dass das Menü nicht mit ausgeklappten FABs verwendet wird und das Speed Dial sowie gestapelte kleine FABs ersetzen soll.

    Tippe auf Add, um das Speed Dial zu öffnen, wähl New invoice und sieh zu, wie sich der Kopf aktualisiert, dann scroll die Kundenliste: Das Label klappt beim Runterscrollen ein und kommt beim Hochscrollen zurück
    $ npx wingo-ui@latest add fab
    ProDoku: FAB

    Halte das Dial kurz. Die Material-Doku setzt das Menü auf 2 bis 6 verwandte Aktionen, die Speed-Dial-Doku von MUI (opens in a new tab) auf drei bis sechs und rät, ab mehr als sechs etwas anderes als einen FAB zu nehmen (beides geprüft im Oktober 2026). Der FAB rendert jede Aktion, die du übergibst, gibt aber ab mehr als sechs eine Warnung im Development-Modus aus. Ein siebter Eintrag fällt also in der Konsole auf, bevor er im Review auffällt.

    Vertikal oder radial?

    layout="vertical" ist das Muster von Material: eine Spalte runder Aktionen über dem Button, jede mit einem Label-Chip daneben, und die ganze Zeile ist die Tippfläche. Das ist der Default, weil die Labels immer sichtbar sind. Auf Touch-Geräten zählt das, denn dort gibt es kein Hover.

    layout="radial" lässt kleine runde Aktionen auf einem Viertelbogen ausfahren (einem Halbbogen mit side="center"). Das verdeckt weniger von der Seite und passt zu einer Karte oder einem Foto, aber die Labels wandern in Tooltips, die bei Hover, Tastaturfokus oder langem Drücken erscheinen. Nimm es für drei oder vier Aktionen mit eindeutigen Icons, etwa Kamera, Galerie und Standort.

    Dasselbe Dial mit layout="radial": Tippe auf den Button, und die vier Aktionen fächern sich auf einem Bogen auf; fahr mit der Maus darüber oder drück lange, um ihren Namen zu sehen
    $ npx wingo-ui@latest add fab
    ProDoku: FAB

    Wie lasse ich einen Extended FAB beim Scrollen einklappen?

    Setz ein label und lass extended="auto" auf dem Default. Das Label ist oben auf der Seite und beim Hochscrollen zu sehen und klappt beim Runterscrollen zum Icon ein, sobald die Seite mehr als 8px vom oberen Rand entfernt ist. Die Breitenänderung ist eine Layout-Animation mit Spring, gesteuert von der Scrollrichtung, die useScrollState meldet. extended="always" behält die Pille, extended="never" zeigt nur das Icon und verschiebt das Label in einen Tooltip.

    Einen Extended FAB beim Scrollen einklappen zu lassen ist die sanfte Variante. hideOnScroll ist die starke: Der ganze Button gleitet beim Runterscrollen hinaus, folgt dabei dem Finger und kommt beim Hochscrollen zurück. Das Gleiten läuft über Motion Values, also gibt es keinen React-Render pro Frame. Er verschwindet nie, solange sein Dial offen ist oder er den Tastaturfokus hat, und inert sorgt dafür, dass Tab nicht auf ihm landet, solange er weg ist. Wir lassen es standardmäßig aus, weil man einen Button, den man nicht sieht, auch nicht antippen kann. Schalte es für Feeds und Posteingänge ein, in denen der FAB Text verdeckt, den Leute gerade lesen.

    Der FAB geht außerdem aus dem Weg, solange die Bildschirmtastatur offen ist (hideOnKeyboard, standardmäßig an), und schließt ein offenes Dial. So verdeckt er nie das Feld, in das du tippst. Scrollt die Seite in einem Element statt im Fenster, beobachtet der FAB den falschen Scroller und klappt nie ein. Pack den Inhalt in <ScrollContainerProvider value={scrollerElement}> aus @/hooks/use-scroll-state oder übergib das Element oder eine Ref als scrollTarget. Mit position="sticky" oder "absolute" und ohne Provider und scrollTarget sucht er sich den nächsten scrollenden Parent selbst.

    Wie staple ich einen FAB über Tab-Leiste, Kaufleiste und Home-Indikator?

    Jede Leiste veröffentlicht ihre Höhe als CSS-Variable, und der FAB addiert sie. Eine handgeschriebene Floating Action Button Tailwind-Klasse scheitert genau hier: bottom-4 landet auf dem Smartphone unter der Tab-Leiste, und bottom-[calc(64px+env(safe-area-inset-bottom)+16px)] sitzt zu hoch, sobald die Leiste unten selbst dasselbe Inset als Padding bekommt, weil das Inset dann doppelt zählt.

    In Wingo UI teilen sich die drei Komponenten zwei Variablen. Die Bottom Tab Bar schreibt --bottom-bar-offset (ihre Höhe inklusive der Safe Area, die sie abdeckt) auf <html>, wenn sie fixiert ist. Die Sticky CTA Bar schreibt --cta-bar-offset, ihre sichtbare Höhe, die auf 0 fällt, solange sie versteckt ist. Der FAB liest beide und berechnet seine Unterkante so:

    css
    bottom: calc(
    max(var(--bottom-bar-offset, 0px) + var(--cta-bar-offset, 0px), env(safe-area-inset-bottom, 0px))
    + 16px
    );

    Ist eine Leiste zu sehen, enthält sie das Inset schon, und der FAB addiert nur seinen offset von 16px. Ohne Leiste gewinnt das Inset allein, und der FAB hält Abstand zum Home-Indikator. Eine Produktseite mit allen dreien braucht keine zusätzliche Rechnung:

    tsx
    "use client";
    import Link from "next/link";
    import { House, MessageCircle, Search, UserRound } from "lucide-react";
    import { BottomTabBar, type BottomTabBarItem } from "@/components/ui/bottom-tab-bar";
    import { Fab } from "@/components/ui/fab";
    import { StickyCtaBar } from "@/components/ui/sticky-cta-bar";
    const tabs: BottomTabBarItem[] = [
    { label: "Start", href: "/", icon: <House /> },
    { label: "Suche", href: "/search", icon: <Search /> },
    { label: "Profil", href: "/profile", icon: <UserRound /> },
    ];
    export function ListingChrome({ onBuy, onMessage }: { onBuy: () => Promise<void>; onMessage: () => void }) {
    return (
    <>
    <Fab icon={<MessageCircle />} labels={{ action: "Verkäufer anschreiben" }} onClick={onMessage} />
    <StickyCtaBar price={349} locale="en-US" actionLabel="Jetzt kaufen" tone="brand" onAction={onBuy} hideOnScroll />
    <BottomTabBar items={tabs} linkComponent={Link} className="md:hidden" />
    </>
    );
    }

    Die Kaufleiste sitzt auf der Tab-Leiste (ihre eigene Unterkante ist var(--bottom-bar-offset)), und der FAB schwebt 16px über der Kaufleiste. Versteckt sich die Kaufleiste beim Scrollen (hideOnScroll ist standardmäßig aus, das Snippet schaltet es also ein), fällt --cta-bar-offset Frame für Frame auf 0, und der FAB folgt nach unten. In einem Scroll-Container (einem Smartphone-Rahmen, einem Panel) nimm position="sticky" für alle drei und rendere sie am Ende des Scrollers, nach dem Inhalt. Die Safe Area erklärt der Beitrag zu Tailwind Safe Area Insets ausführlich, die Tab-Leiste selbst der Guide zur React Bottom Navigation Bar.

    Was braucht ein FAB für Tastatur- und Screenreader-Nutzer?

    Er braucht einen Fokusstopp pro Aktion, Menü-Semantik mit einem Expanded-Zustand am Auslöser, einen Namen, der ohne sichtbares Label funktioniert, und Navigation mit den Pfeiltasten. Ein Beitrag im Joplin-Forum vom Juni 2022 (opens in a new tab) über die mobile App von Joplin listet die typischen Fehler eines Speed Dial mit TalkBack auf: Button und Label jeder Aktion waren beide fokussierbar, das Öffnen des Menüs wurde nicht angesagt, und der Umschalter hieß offen wie geschlossen gleich. Der FAB von Wingo UI löst jeden dieser Punkte:

    • Ein Element pro Aktion. Jede Aktion ist ein einzelner menuitem-Button oder -Link, der Label-Chip und Icon enthält, also hält ein Screenreader pro Aktion nur einmal an.
    • Zustand am Auslöser. Der Button hat aria-haspopup="menu", aria-expanded und aria-controls; das Dial ist ein role="menu" mit einem Namen aus labels.menu.
    • Ein Name für den reinen Icon-Button. Mit label ist das der Name; ohne ist es labels.open / labels.close für ein Dial und labels.action für einen normalen Button, alle für Übersetzungen überschreibbar.
    • Tastatur. Enter, Leertaste oder Pfeil nach oben öffnen das Dial und fokussieren die nächstgelegene Aktion; die Pfeiltasten bewegen den Fokus, Pos1 und Ende springen zur ersten und zur letzten Aktion, Escape schließt und gibt den Fokus an den Button zurück, und Tab schließt und geht weiter. shortcut="n" öffnet es von überall und wird als aria-keyshortcuts gesetzt.
    • Tippflächen. Der Auslöser hat je nach Größe 48, 56 oder 64px, die Aktionen im Dial 40, 44 oder 48px; die Aktion sm mit 40px wächst bei groben Zeigern auf 44px, und eine vertikale Zeile ist samt Chip mindestens 44px hoch, das Minimum, das wir überall verwenden (siehe Größen für Tippflächen).

    Ist reduzierte Bewegung eingestellt, werden das Dial und das Hinausgleiten beim Scrollen zu einfachen Überblendungen.

    Was sind die häufigsten Fehler beim Floating Action Button?

    Die meisten haben damit zu tun, wo der Button auf dem Screen sitzt:

    • Zwei FABs auf einem Screen. Brauchst du einen zweiten schwebenden Button, gehört einer davon in den Kopf oder ins Dial.
    • Ein FAB über der letzten Zeile. Gib dem Scrollbereich unten so viel Padding, wie der FAB hoch ist, plus seinen Abstand (die Demo nutzt pb-28), sonst landet der letzte Listeneintrag unter dem Button.
    • Ein FAB als Navigation. „Zum Posteingang“ ist ein Tab. Der FAB legt etwas auf dem aktuellen Screen an oder startet es.
    • Ein fixierter FAB in einem transformierten Parent. position: fixed bezieht sich auf den nächsten Vorfahren mit transform, filter oder will-change: transform, also zieht ein Wrapper für Seitenübergänge den FAB mit der Seite mit. Rendere ihn außerhalb dieses Wrappers oder nimm bewusst position="absolute" in einem relativen Container.
    • Ein Material FAB Web-Nachbau, der die Safe Area ignoriert. Eine Webseite muss sie mit viewport-fit=cover erst aktivieren und env(safe-area-inset-bottom) selbst lesen, sonst sitzt der Button auf dem Home-Indikator. Teste auf einem echten iPhone, nicht nur in einem verkleinerten Desktop-Fenster.

    Was baue ich als Nächstes?

    Installier den FAB mit npx wingo-ui@latest add fab und probier die Props im FAB-Playground aus. Er gehört zu Wingo UI Pro, zusammen mit der Tab-Leiste und der Kaufleiste, mit denen er sich stapelt. Für den Rest des unteren Bildschirmrands auf dem Smartphone erklärt der Guide zu Mobile-first React-Komponenten die neun Regeln, denen diese Komponenten folgen. Weitere Beiträge findest du unter Mobile UI in React.

    Komponenten in diesem Artikel

    • FAB

      A React floating action button (FAB) for a phone screen's main action, with a labeled or radial speed dial and a label that folds on scroll.

      Pro
    • Bottom Tab Bar

      A React bottom tab bar for phones: 3 to 5 tabs at the thumb with an animated pill, badges, a raised center action and hide on scroll.

      Pro
    • Sticky CTA Bar

      A React sticky CTA bar for product, listing and checkout pages on phones: the price on one side, the main action on the other.

      Pro

    Häufige Fragen

    Wie viele Aktionen sollte ein FAB Speed Dial haben?

    Zwei bis sechs. Laut der Doku zum FAB-Menü von Material Components zeigt es 2 bis 6 verwandte Aktionen, und die Speed-Dial-Doku von MUI nennt drei bis sechs und rät, ab mehr als sechs etwas anderes als einen FAB zu nehmen. Bei mehr Aktionen nimm ein Action Sheet oder ein Menü.

    Soll sich ein Floating Action Button beim Scrollen verstecken?

    Nur in langen Listen, in denen er Inhalte verdeckt, die Leute lesen. Wenn er sich versteckt, sollte er dem Finger folgen, beim Hochscrollen sofort zurückkommen und nie verschwinden, solange sein Dial offen ist oder er den Tastaturfokus hat. Oft reicht es schon, das Label beim Scrollen einzuklappen, und die Aktion bleibt erreichbar.

    Hat shadcn/ui einen Floating Action Button?

    Stand Oktober 2026 nicht: Die Komponentenliste enthält Button, Button Group und Dropdown Menu, aber keinen FAB und kein Speed Dial. Der FAB von Wingo UI wird genauso installiert, als Quellcode in deinem Projekt, mit npx wingo-ui@latest add fab.

    Wie halte ich einen FAB über einer Bottom Navigation Bar?

    Miss die Leiste und addier ihre Höhe zum unteren Abstand des FAB. Die Bottom Tab Bar von Wingo UI schreibt --bottom-bar-offset, die Sticky CTA Bar schreibt --cta-bar-offset, und der FAB addiert beide und nimmt dann den größeren Wert aus dieser Summe und dem Safe-Area-Inset. So zählt der Home-Indikator nur einmal.

    Ist der FAB von Wingo UI kostenlos?

    Nein. Der FAB ist eine Pro-Komponente, genau wie die Bottom Tab Bar und die Sticky CTA Bar, mit denen er sich stapelt. Der Tooltip, den er für die Namen reiner Icon-Buttons nutzt, ist kostenlos.

    • Mobile UI
    • FAB
    • Speed Dial
    • React
    • Tailwind CSS

    Teilen

    SR

    Über den Autor

    Serban Rusu

    Gründer von Wingo UI

    Serban Rusu hat Wingo UI gegründet. Er baut die Komponenten, die CLI und den MCP-Server und schreibt über React-UIs für Smartphones und KI-Agents.

    Mehr von Serban
    Weiterlesen

    Ähnliche Artikel

    Alle Artikel
    Mobile UI mit React

    Tailwind Safe Area: Bottom Bars, FABs und Toasts

    Tailwind Safe Area in v4: viewport-fit=cover aktivieren, Leisten Padding aus env(safe-area-inset-bottom) geben, FABs und Toasts vom Home-Indikator fernhalten.

    SRSerban Rusu·9. Okt. 2026·11 Min. Lesezeit
    Mobile UI mit React

    Mobile First React: 9 Regeln für Komponenten mit Code

    Mobile First React Regel für Regel, mit Code: Bottom Sheets statt Popover, 44px Touch-Ziele, Safe Areas, dvh, Leisten über der Tastatur, Tabellen als Karten.

    SRSerban Rusu·9. Okt. 2026·21 Min. Lesezeit
    Mobile UI mit React

    React Bottom Navigation Bar: Safe Areas und Badges

    React Bottom Navigation Bar in Next.js: 3 bis 5 Tabs, Safe Areas, Badges, die Screenreader vorlesen, Ausblenden beim Scrollen und wann die Sidebar besser passt.

    SRSerban Rusu·9. Okt. 2026·9 Min. Lesezeit
    Newsletter

    Neue Artikel per E-Mail

    Neue Guides, Tutorials und Vergleiche aus dem Wingo UI Blog, sobald sie erscheinen. Die meisten Artikel sind auf Englisch.

    Kein Spam. Du kannst dich jederzeit abmelden.

    WingoUI

    Animierte, konfigurierbare, mobile-first React-Komponenten und Blöcke. Kopier den Quellcode, pass ihn an und lass deinen Coding-Agenten damit bauen.

    Produkt

    • Komponenten
    • Vorlagen
    • Preise
    • KI-Agenten
    • Theme-Generator

    Ressourcen

    • Doku
    • Blog
    • Changelog
    • Changelog-RSS
    • llms.txt

    Rechtliches

    • AGB
    • Datenschutz
    • Rückerstattung
    • Lizenz
    • Impressum

    Komponenten-Kategorien

    • Buttons & Actions
    • Inputs
    • Forms
    • Navigation
    • Overlays
    • Feedback
    • Data Display
    • Tables & Lists
    • Charts & Stats
    • Layout
    • Media
    • AI Kit
    • Text & Effects
    • Mobile
    • Commerce
    • Marketing Sections
    • Blocks
    • Hooks & Utilities

    © 2026 Wingo UI

    Wingo UI