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
rx.el.tablerx.el.captionrx.el.colgrouprx.el.colrx.el.theadrx.el.tbodyrx.el.tfootrx.el.trrx.el.thrx.el.tdOffizielle Doku
Werkstattauftrag
Café-Quittung als Tabelle: Bitte bau sie als nackte HTML-Tabelle mit Titel, Kopfzeile Artikel · Menge · Preis und einer Fußzeile mit der Summe.
Das sind die HTML-Tabellenelemente für Daten in Zeilen und Spalten. In table kommt ein tbody mit Zeilen tr, und in jede Zeile Kopfzellen th und normale Zellen td.
Sie sind ungestylt, Rahmen und Abstände setzt du selbst. Für eine Tabelle im Radix-Look gibt es rx.table, für Sortieren und Suchen rx.data_table.
| Name | Role |
|---|---|
| Ada | Engineer |
| Linus | Maintainer |
rx.el.table(
rx.el.tbody(
rx.el.tr(rx.el.th("Name"), rx.el.th("Role")),
rx.el.tr(rx.el.td("Ada"), rx.el.td("Engineer")),
rx.el.tr(rx.el.td("Linus"), rx.el.td("Maintainer")),
),
)Das preflight dieser Website lässt die Zellen aneinanderstoßen (border_collapse="collapse"). Mit separate bekommt jede Zelle einen eigenen, abgesetzten Rahmen.
Props ausprobieren
| Item | Qty |
|---|---|
| Apples | 3 |
| Pears | 12 |
caption
caption_side
align
collapse
rx.el.table(
rx.el.caption("Fruit stock", caption_side="top", padding="4px", font_weight="600"),
rx.el.thead(
rx.el.tr(
rx.el.th("Item", border="1px solid gray", padding="6px"),
rx.el.th("Qty", border="1px solid gray", padding="6px"),
),
),
rx.el.tbody(
rx.el.tr(
rx.el.td("Apples", border="1px solid gray", padding="6px"),
rx.el.td("3", align="right", border="1px solid gray", padding="6px"),
),
rx.el.tr(
rx.el.td("Pears", border="1px solid gray", padding="6px"),
rx.el.td("12", align="right", border="1px solid gray", padding="6px"),
),
),
border_collapse="collapse",
border_spacing="4px",
width="260px",
)| Prop | Werte | Standard | Verwendung |
|---|---|---|---|
col_span (td, th) | Ganzzahl | 1 | Zahl der horizontal verbundenen Zellen |
row_span (td, th) | Ganzzahl | 1 | Zahl der vertikal verbundenen Zellen |
scope (th) | "col" "row" "colgroup" "rowgroup" | keiner | Richtung, für die diese Kopfzelle gilt |
headers (td, th) | ids von th | keiner | Kopfzellen dieser Zelle direkt angeben |
align (td, th) | "left" "center" "right" "justify" "char" | links | Ausrichtung in der Zelle (altes Attribut, CSS text_align geht auch) |
span (col, colgroup) | Ganzzahl | 1 | Zahl der Spalten, die ein col abdeckt |
align summary (table) | String | keiner | In HTML5 veraltete Attribute. Ausrichtung per CSS, Beschreibung per caption |
thead·tbody·tfoot teilen die Zeilen in Kopf, Körper und Fuß. Jede Zeile gehört in genau einen dieser drei.
Steht ein tr direkt unter table, schiebt der Browser stillschweigend ein tbody ein, und die Struktur weicht von der ab, die React kennt.
caption ist der Titel der Tabelle und muss das erste Kind von table sein. scope bei th sagt, ob die Kopfzelle für eine Spalte ("col") oder eine Zeile ("row") gilt.
| Month | Visitors |
|---|---|
| Jan | 1,200 |
| Feb | 1,450 |
| Total | 2,650 |
rx.el.table(
rx.el.caption("Monthly visitors", padding="4px", font_weight="600"),
rx.el.thead(
rx.el.tr(rx.el.th("Month", scope="col"), rx.el.th("Visitors", scope="col")),
background=rx.color("indigo", 3),
),
rx.el.tbody(
rx.el.tr(rx.el.th("Jan", scope="row"), rx.el.td("1,200")),
rx.el.tr(rx.el.th("Feb", scope="row"), rx.el.td("1,450")),
),
rx.el.tfoot(
rx.el.tr(rx.el.th("Total", scope="row"), rx.el.td("2,650", font_weight="bold")),
border_top="2px solid gray",
),
width="280px",
text_align="left",
)col_span=2 schluckt die Zelle rechts daneben, row_span=2 eine Zelle der Zeile darunter. An geschluckten Stellen steht kein td.
Im Stundenplan unten hat die dritte Zeile eine Zelle weniger.
| Mon | Tue | Wed | |
|---|---|---|---|
| 9 am | Workshop | Free | |
| 10 am | Lunch prep | Review | Free |
| 11 am | Free | Demo | |
rx.el.table(
rx.el.thead(rx.el.tr(rx.el.th(""), rx.el.th("Mon"), rx.el.th("Tue"), rx.el.th("Wed"))),
rx.el.tbody(
rx.el.tr(rx.el.th("9 am"), rx.el.td("Workshop", col_span=2, background=rx.color("indigo", 4)), rx.el.td("Free")),
rx.el.tr(rx.el.th("10 am"), rx.el.td("Lunch prep", row_span=2, background=rx.color("amber", 4)), rx.el.td("Review"), rx.el.td("Free")),
rx.el.tr(rx.el.th("11 am"), rx.el.td("Free"), rx.el.td("Demo")),
),
border="1px solid gray",
text_align="center",
width="340px",
)Jedes col in colgroup steht für eine Spalte, mit span=2 für zwei. Damit gibst du ganzen Spalten Hintergrundfarbe oder Breite.
Bei col funktionieren nur wenige CSS-Eigenschaften, im Wesentlichen background, width, border und visibility.
| Plan | Price | Seats |
|---|---|---|
| Starter | $0 | 1 |
| Team | $20 | 10 |
rx.el.table(
rx.el.colgroup(rx.el.col(), rx.el.col(span=2)),
rx.el.thead(rx.el.tr(rx.el.th("Plan"), rx.el.th("Price"), rx.el.th("Seats"))),
rx.el.tbody(
rx.el.tr(rx.el.td("Starter"), rx.el.td("$0"), rx.el.td("1")),
rx.el.tr(rx.el.td("Team"), rx.el.td("$20"), rx.el.td("10")),
),
width="300px",
text_align="left",
# style the columns from the table: Reflex puts a <style> tag next to a styled
# element, and the browser moves a <style> found inside <colgroup> out of it
style={
"& col:first-child": {"background": rx.color("gray", 3)},
"& col:last-child": {"background": rx.color("teal", 3)},
},
)In komplexen Tabellen gibst du th eine id und trägst diese id in headers des td ein. Optisch ändert sich nichts, aber Screenreader lesen dann etwa „Price, $2“.
| Fruit | Price |
|---|---|
| Kiwi | $2 |
rx.el.table(
rx.el.tbody(
rx.el.tr(rx.el.th("Fruit", id="htmltable_fruit"), rx.el.th("Price", id="htmltable_price")),
rx.el.tr(rx.el.td("Kiwi", headers="htmltable_fruit"), rx.el.td("$2", headers="htmltable_price")),
),
width="200px",
text_align="left",
)Kommen die Zeilen aus einer State-Liste, erzeugst du die tr mit rx.foreach. Sortiert wird in einer berechneten Variable, und die Tabelle zeichnet einfach deren Ergebnis.
| Name | Score |
|---|---|
| Jun | 95 |
| Mina | 88 |
| Sora | 72 |
class HtmlTableScoreState(rx.State):
rows: list[dict[str, str]] = [
{"name": "Mina", "score": "88"},
{"name": "Jun", "score": "95"},
{"name": "Sora", "score": "72"},
]
descending: bool = True
@rx.event
def flip_order(self):
self.descending = not self.descending
@rx.var
def sorted_rows(self) -> list[dict[str, str]]:
return sorted(self.rows, key=lambda r: int(r["score"]), reverse=self.descending)
rx.el.div(
rx.el.button(
rx.cond(HtmlTableScoreState.descending, "High to low", "Low to high"),
on_click=HtmlTableScoreState.flip_order,
padding="4px 12px",
border="1px solid gray",
border_radius="6px",
margin_bottom="8px",
),
rx.el.table(
rx.el.thead(rx.el.tr(rx.el.th("Name"), rx.el.th("Score"))),
rx.el.tbody(
rx.foreach(
HtmlTableScoreState.sorted_rows,
lambda row: rx.el.tr(rx.el.td(row["name"]), rx.el.td(row["score"], align="right")),
),
),
width="220px",
text_align="left",
),
)caption trägt die Quittungsnummer, thead die Kopfzeile, tfoot die Summe. Die Kopfzelle der Summe nimmt mit col_span=2 zwei Spalten ein, und die Zahlenspalten sind per colgroup in der Breite angeglichen.
| Item | Qty | Price |
|---|---|---|
| Latte | 2 | $9.00 |
| Bagel | 1 | $3.50 |
| Total | $12.50 | |
rx.el.table(
rx.el.caption("Receipt #1024", padding="6px", font_weight="bold"),
rx.el.colgroup(rx.el.col(), rx.el.col(span=2)),
rx.el.thead(
rx.el.tr(rx.el.th("Item", scope="col"), rx.el.th("Qty", scope="col"), rx.el.th("Price", scope="col")),
border_bottom="2px solid gray",
),
rx.el.tbody(
rx.el.tr(rx.el.td("Latte"), rx.el.td("2", align="right"), rx.el.td("$9.00", align="right")),
rx.el.tr(rx.el.td("Bagel"), rx.el.td("1", align="right"), rx.el.td("$3.50", align="right")),
),
rx.el.tfoot(
rx.el.tr(rx.el.th("Total", scope="row", col_span=2), rx.el.td("$12.50", align="right", font_weight="bold")),
border_top="2px solid gray",
),
width="300px",
text_align="left",
font_variant_numeric="tabular-nums",
style={"& col:last-child": {"width": "70px"}}, # see the colgroup example above
)Werkstattnotizen
table > (caption) > thead · tbody · tfoot > tr > th · td. tr gehört immer in tbody o. Ä.
Unter preflight hat eine Tabelle weder Rahmen noch Abstände. border · padding selbst setzen.
Zellen mit col_span · row_span verbinden; an geschluckten Stellen keine Zelle setzen.
scope bei th und headers bei td sind Verknüpfungen für Screenreader.
Kommen Zeilen aus dem State, die tr per rx.foreach erzeugen. Für eine gestaltete Tabelle rx.table.
Ü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.