Die Komponentenwerkstatt: Reflex' 100 Bibliotheksbausteine
·
Kursüberblick
Layout
·
Box
·
Flex
·
Stack
·
Grid
·
Container
·
Section
·
Center
·
Spacer
·
Separator
·
Card
·
Inset
·
Aspect Ratio
·
Fragment
Typografie
·
Text
·
Heading
·
Link
·
Code
·
Markdown
·
Blockquote
·
Quote
·
Strong
·
Em
·
Kbd
Formulare
·
Button
·
Input
·
Text Area
·
Checkbox
·
Switch
·
Radio Group
·
Select
·
Slider
·
Form
·
Upload
Datenanzeige
·
Badge
·
Avatar
·
Icon
·
Callout
·
List
·
Data List
·
Code Block
·
Progress
·
Spinner
·
Scroll Area
·
Moment
Auf- und Zuklappen
·
Tabs
·
Accordion
·
Segmented Control
Overlays
·
Tooltip
·
Popover
·
Hover Card
·
Dialog
·
Alert Dialog
·
Drawer
·
Dropdown Menu
·
Context Menu
·
Toast
Dynamisches Rendern
·
Cond
·
Match
·
Foreach
·
Auto Scroll
Medien
·
Image
·
Audio
·
Video
Tabellen und Datengrids
·
Table
·
Data Table
·
Data Editor
Diagramme
·
Area Chart
·
Bar Chart
·
Line Chart
·
Composed Chart
·
Pie Chart
·
Radar Chart
·
Radial Bar Chart
·
Scatter Chart
·
Funnel Chart
·
Treemap
·
Sankey Chart
·
Error Bar
Diagrammbausteine
·
Axis
·
Cartesian Grid
·
Chart Tooltip
·
Legend
·
Label
·
Reference
·
Brush
Andere Diagrammbibliotheken
·
Plotly
·
Pyplot
HTML-Elemente
·
HTML
·
HTML Text
·
HTML Layout
·
HTML Forms
·
HTML Media
·
HTML Tables
·
SVG
Weitere Werkzeuge
·
Theme
·
Skeleton
·
Clipboard
·
Html Embed
·
Script
·
Memo
Werkstattauftrag
Bitte gestalte ohne Designsystem, nur mit nacktem HTML, eine kleine Hinweiskarte mit Schließen-Button und Link.
In rx.el stecken die HTML-Elemente der Webentwicklung, wie sie sind. rx.el.div wird zu <div>, rx.el.button zu <button>.
Anders als das Radix-basierte rx.button gibt es keine Aussehen-Props wie variant oder size, und die Elemente kommen völlig ungestylt daher.
Auf dieser Seite ist das Basis-Reset von Tailwind (preflight) aktiv, deshalb fehlen sogar der Rahmen des Buttons und die Linie des Eingabefelds.
A plain paragraph.
rx.el.div(
rx.el.p("A plain paragraph."),
rx.el.button("A plain button"),
rx.el.input(placeholder="A plain input"),
)Das Aussehen gibst du direkt über Stil-Props (CSS-Eigenschaftsnamen mit Unterstrich als Schlüsselwortargument). Ändere die Werte und sieh, wie sich der nackte Button verändert.
Props ausprobieren
label
background
color
padding
radius
weight
disabled
rx.el.button(
"Buy now",
background="#4f46e5",
color="white",
padding="8px 16px",
border_radius="6px",
font_weight="600",
disabled=False,
cursor="pointer",
)| Prop | Werte | Standard | Verwendung |
|---|---|---|---|
CSS-Eigenschaften (padding, color …) | CSS-Wert | keiner | Stil direkt per Schlüsselwort setzen |
class_name | Klassen-String | keiner | CSS-Klassen, etwa von Tailwind |
id title hidden role tab_index lang dir | String · bool · int | keiner | HTML-Attribute, die alle Elemente haben |
custom_attrs | dict | keiner | Attribute mit - im Namen wie aria-* oder data-* |
type (button) | "submit" "reset" "button" | Browser: "submit" | Was ein Klick im Formular auslöst |
type (input) | "text" "email" "range" "date" … 22 Arten | "text" | Art des Eingabefelds |
value / on_change (input) | String · Zahl / Event | keiner | Gesteuertes Eingabefeld. default_value für ungesteuert |
href target (a) | URL / "_blank" … | keiner | Linkziel und wo es geöffnet wird |
on_click on_key_down … | Event-Handler | keiner | Grundlegende Events aller Elemente |
Stil-Props als Schlüsselwortargumente, ein style-Dictionary und CSS-Klassen per class_name. Du kannst alle drei mischen.
Theme-Farben wie rx.color("indigo", 3) passen sich auch im Dark Mode passend an.
rx.el.div(
rx.el.div(
"Style props",
padding="12px",
border=f"1px solid {rx.color('indigo', 7)}",
border_radius="8px",
background=rx.color("indigo", 3),
),
rx.el.div(
"style dict",
style={"padding": "12px", "border": "1px dashed gray", "border_radius": "8px"},
),
rx.el.div(
"Tailwind classes",
class_name="p-3 rounded-lg border-2 border-dotted font-semibold",
),
display="flex",
gap="12px",
flex_wrap="wrap",
)title ist der Standard-Tooltip beim Überfahren mit der Maus, hidden verbirgt, dir legt die Schreibrichtung fest, tab_index die Reihenfolge der Tab-Taste.
Attribute mit Bindestrich im Namen wie aria-label oder data-kind übergibst du per custom_attrs.
Right to left
rx.el.div(
rx.el.span("Hover me", title="A native tooltip", text_decoration="underline dotted"),
rx.el.span("You cannot see me", hidden=True),
rx.el.p("Right to left", dir="rtl", lang="en"),
rx.el.div(
"Focus me with Tab",
tab_index=0,
role="note",
custom_attrs={"aria-label": "Demo note", "data-kind": "demo"},
padding="8px",
border="1px solid gray",
border_radius="6px",
),
display="flex",
flex_direction="column",
gap="8px",
)Den State per on_click zu ändern funktioniert wie bei rx.button. In einem Formular kommt es auf type an.
Ohne Angabe gilt der Browser-Standard "submit", und ein Klick sendet das Formular sofort ab, daher schreibst du normale Buttons mit type="button".
name·value sind Werte, die beim Absenden mitgeschickt werden, und form_*-Attribute wie form_action·form_method ändern die Formulareinstellungen nur für diesen Button.
class HtmlElButtonState(rx.State):
count: int = 0
@rx.event
def add_one(self):
self.count += 1
rx.el.div(
rx.el.button(
"Add one",
type="button",
on_click=HtmlElButtonState.add_one,
padding="6px 14px",
border="1px solid gray",
border_radius="6px",
cursor="pointer",
),
rx.el.button("Disabled", disabled=True, padding="6px 14px", border="1px solid gray", border_radius="6px", opacity="0.5"),
rx.el.span("Count: ", HtmlElButtonState.count),
display="flex",
gap="12px",
align_items="center",
)Mit value und on_change zusammen wird es ein gesteuertes Eingabefeld, das der State in der Hand hat. rx.el.input hat eigene Events on_change, on_key_down und on_key_up.
on_key_down übergibt den Namen der gedrückten Taste, unten wird deshalb die zuletzt gedrückte angezeigt. type="range" wird zum Slider.
Hello, (last key: )
Level: 40
class HtmlElInputState(rx.State):
name: str = ""
level: int = 40
last_key: str = ""
@rx.event
def change_name(self, value: str):
self.name = value
@rx.event
def change_level(self, value: float):
self.level = int(value)
@rx.event
def remember_key(self, key: str):
self.last_key = key
rx.el.div(
rx.el.input(
type="text",
value=HtmlElInputState.name,
on_change=HtmlElInputState.change_name,
on_key_down=HtmlElInputState.remember_key,
placeholder="Your name",
max_length=20,
padding="6px 10px",
border="1px solid gray",
border_radius="6px",
),
rx.el.p("Hello, ", HtmlElInputState.name, " (last key: ", HtmlElInputState.last_key, ")"),
rx.el.input(
type="range",
min=0,
max=100,
step=5,
value=HtmlElInputState.level,
on_change=HtmlElInputState.change_level,
),
rx.el.p("Level: ", HtmlElInputState.level),
display="flex",
flex_direction="column",
gap="8px",
max_width="320px",
)Ein einziges type macht daraus ein Datums-, Farb-, Checkbox-, E-Mail- oder Zahlenfeld. Willst du ohne State nur einen Anfangswert setzen, nimm default_value·default_checked.
Prüf-Attribute wie required, min·max, pattern und max_length kontrolliert der Browser beim Absenden des Formulars.
rx.el.div(
rx.el.input(type="date"),
rx.el.input(type="color", default_value="#6e56cf"),
rx.el.label(rx.el.input(type="checkbox", default_checked=True), " Remember me"),
rx.el.input(type="email", placeholder="you@example.com", required=True, border="1px solid gray", padding="4px 8px"),
rx.el.input(type="number", min=1, max=9, default_value=3, border="1px solid gray", padding="4px 8px", width="80px"),
display="flex",
gap="12px",
flex_wrap="wrap",
align_items="center",
)p ist ein Absatz und nimmt eine ganze Zeile ein, span ist ein Stück, das im Textfluss bleibt. div ist eine Box ohne Bedeutung, mit der du alles Mögliche gruppierst.
A p is a block. A span stays inside the line.
rx.el.div(
rx.el.p(
"A p is a block. A ",
rx.el.span("span", color=rx.color("tomato", 11), font_weight="bold"),
" stays inside the line.",
),
rx.el.div("A div is a box with no meaning.", padding="8px", background=rx.color("gray", 3)),
)In Reflex 0.10 wird rx.el.a als Link von React Router gerendert, und href wird intern zu to.
Adressen innerhalb der Seite wie "/" wechseln deshalb ohne Neuladen, externe Adressen öffnen sich wie normale Links.
Mit Neuladen wechselst du per reload_document=True, den Verlaufseintrag ersetzt replace=True, Übergangseffekte gibt es mit view_transition=True. download lädt das Ziel als Datei herunter.
rx.el.div(
rx.el.a(
"Reflex docs (new tab)",
href="https://reflex.dev/docs/library/html/html/",
target="_blank",
rel="noopener noreferrer",
color=rx.color("indigo", 11),
text_decoration="underline",
),
rx.el.a("Home page", href="/", color=rx.color("indigo", 11), text_decoration="underline"),
display="flex",
gap="16px",
)rx.el hat über 100 Elemente. Textelemente, Dokumentstruktur, Formulare, Medien, Tabellen und SVG behandeln die folgenden fünf Seiten jeweils als Gruppe.
Das Badge entsteht aus span, der Text aus p, die Aktionen aus a und button, und alles ist per Stil-Props gestaltet. Beim Schließen blendet der State die Karte aus.
class HtmlElNoticeState(rx.State):
visible: bool = True
@rx.event
def dismiss(self):
self.visible = False
@rx.event
def show_again(self):
self.visible = True
rx.cond(
HtmlElNoticeState.visible,
rx.el.div(
rx.el.p(
rx.el.span(
"New",
background=rx.color("indigo", 9),
color="white",
padding="2px 8px",
border_radius="999px",
font_size="12px",
margin_right="8px",
),
"Version 2 is out.",
font_weight="600",
),
rx.el.p("Read what changed before you update.", color=rx.color("gray", 11), margin_y="6px"),
rx.el.div(
rx.el.a(
"Release notes",
href="https://reflex.dev/docs/",
target="_blank",
rel="noopener noreferrer",
color=rx.color("indigo", 11),
text_decoration="underline",
),
rx.el.button(
"Dismiss",
type="button",
on_click=HtmlElNoticeState.dismiss,
padding="4px 12px",
border=f"1px solid {rx.color('gray', 7)}",
border_radius="6px",
cursor="pointer",
),
display="flex",
gap="16px",
align_items="center",
),
padding="16px",
border=f"1px solid {rx.color('indigo', 6)}",
border_radius="10px",
background=rx.color("indigo", 2),
max_width="360px",
),
rx.el.button("Show again", on_click=HtmlElNoticeState.show_again, text_decoration="underline", cursor="pointer"),
)Werkstattnotizen
rx.el.<tag> ist das HTML-Element pur, ohne Stil. Aussehen per CSS-Schlüsselwort-Props · style · class_name.
title · hidden · dir · tab_index · role haben alle Elemente. aria-* · data-* per custom_attrs.
rx.el.button im Formular ist standardmäßig submit. Normale Buttons: type="button".
rx.el.input gesteuert mit value + on_change, ungesteuert mit default_value. on_key_down übergibt die gedrückte Taste.
rx.el.a in 0.10 ist ein React-Router-Link: href wird zu to, innerhalb der Seite ohne Neuladen.
Über neue Lektionen informiert werden
Wir schicken dir eine E-Mail, wenn dieser Kurs neue Lektionen bekommt oder ein Folgekurs erscheint.
R
ReflexKR
Python und Reflex zum Anfassen. Alle Beispiele wurden mit Reflex 0.10.0 ausgeführt und geprüft.
ReflexKR ist kostenlos und ohne Werbebanner. Wenn es dir geholfen hat, kannst du es mit einem Kaffee unterstützen. ☕ Spendier uns einen Kaffee
Hinweis zu Affiliate-Links© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Fragen & Antworten
Frag alles zu dieser Lektion. Fragen aus allen Sprachversionen dieser Seite erscheinen hier gemeinsam.