The Component Workshop: Reflex's 100 Library Components
·
Course overview
Layout
·
Box
·
Flex
·
Stack
·
Grid
·
Container
·
Section
·
Center
·
Spacer
·
Separator
·
Card
·
Inset
·
Aspect Ratio
·
Fragment
Typography
·
Text
·
Heading
·
Link
·
Code
·
Markdown
·
Blockquote
·
Quote
·
Strong
·
Em
·
Kbd
Forms
·
Button
·
Input
·
Text Area
·
Checkbox
·
Switch
·
Radio Group
·
Select
·
Slider
·
Form
·
Upload
Data display
·
Badge
·
Avatar
·
Icon
·
Callout
·
List
·
Data List
·
Code Block
·
Progress
·
Spinner
·
Scroll Area
·
Moment
Disclosure
·
Tabs
·
Accordion
·
Segmented Control
Overlay
·
Tooltip
·
Popover
·
Hover Card
·
Dialog
·
Alert Dialog
·
Drawer
·
Dropdown Menu
·
Context Menu
·
Toast
Dynamic rendering
·
Cond
·
Match
·
Foreach
·
Auto Scroll
Media
·
Image
·
Audio
·
Video
Tables and data grids
·
Table
·
Data Table
·
Data Editor
Charts
·
Area Chart
·
Bar Chart
·
Line Chart
·
Composed Chart
·
Pie Chart
·
Radar Chart
·
Radial Bar Chart
·
Scatter Chart
·
Funnel Chart
·
Treemap
·
Sankey Chart
·
Error Bar
Chart parts
·
Axis
·
Cartesian Grid
·
Chart Tooltip
·
Legend
·
Label
·
Reference
·
Brush
Other chart libraries
·
Plotly
·
Pyplot
HTML elements
·
HTML
·
HTML Text
·
HTML Layout
·
HTML Forms
·
HTML Media
·
HTML Tables
·
SVG
Other tools
·
Theme
·
Skeleton
·
Clipboard
·
Html Embed
·
Script
·
Memo
rx.flexOfficial docs
Workshop order
Lay out several product cards in a row, and when the screen gets narrow, let the extra cards move to the next line.
rx.flex is a container that lines its children up using CSS flexbox. A few props set the direction (horizontal or vertical), wrapping, alignment and how leftover space is shared. By default it runs horizontally (row) without wrapping. It is the layout you will reach for most when building responsive screens.
rx.flex(
rx.card("Card 1"),
rx.card("Card 2"),
rx.card("Card 3"),
rx.card("Card 4"),
rx.card("Card 5"),
spacing="2",
width="100%",
)Only Card 2 is taller, which makes the effect of align easy to see. Switch wrap to wrap and the overflowing cards drop to the next line.
Try the props
direction
align
justify
wrap
spacing
rx.flex(
rx.card("Card 1", width="30%"),
rx.card("Card 2", width="30%", height="5rem"),
rx.card("Card 3", width="30%"),
rx.card("Card 4", width="30%"),
rx.card("Card 5", width="30%"),
direction="row",
align="stretch",
justify="start",
wrap="nowrap",
spacing="2",
width="100%",
min_height="14rem",
padding="12px",
border="1px dashed var(--gray-7)",
border_radius="8px",
)| Prop | Values | Default | Use |
|---|---|---|---|
direction | "row" "column" "row-reverse" "column-reverse" | "row" | Direction the children line up in (main axis) |
align | "start" "center" "end" "baseline" "stretch" | "stretch" | Alignment on the axis across the main axis (cross axis) |
justify | "start" "center" "end" "between" | "start" | Alignment along the main axis. between pins items to both ends and spaces the rest evenly |
wrap | "nowrap" "wrap" "wrap-reverse" | "nowrap" | Whether to wrap to the next line on overflow |
spacing | "0" ~ "9" | none | Gap between children (Radix spacing scale). You can also set CSS gap directly |
as_child | True / False | False | Render the child element instead of Flex and merge the props |
Every prop accepts rx.breakpoints(...) to vary by screen width. The prop descriptions in the installed 0.10 have the axes of align and justify swapped, but the actual behavior is as in the table above.
When there are too many children to fit on one line, the default (nowrap) shrinks them. With wrap="wrap" they keep their size and move to the next line. Writing the CSS property flex_wrap="wrap", as the official docs do, gives the same result.
rx.flex(
rx.foreach(
rx.Var.range(10),
lambda i: rx.card(f"Card {i + 1}", width="16%"),
),
spacing="2",
wrap="wrap",
width="100%",
)direction="column" stacks from top to bottom. Adding -reverse flips the order. Use it when you want to change only the visual order and leave the code order alone.
rx.flex(
rx.flex(rx.card("Card 1"), rx.card("Card 2"), rx.card("Card 3"), spacing="2", direction="column"),
rx.flex(rx.card("Card 1"), rx.card("Card 2"), rx.card("Card 3"), spacing="2", direction="column-reverse"),
rx.flex(rx.card("Card 1"), rx.card("Card 2"), rx.card("Card 3"), spacing="2", direction="row-reverse"),
spacing="6",
wrap="wrap",
)Pass rx.breakpoints values from initial (the narrowest screen) up through xs sm md lg xl, and the prop changes with the screen width. The Radix breakpoints are xs 520px, sm 768px, md 1024px, lg 1280px, xl 1640px. The example below stacks vertically on narrow screens and lays out horizontally from sm up. Try resizing the browser window.
rx.flex(
rx.card("Card 1", flex_grow="1"),
rx.card("Card 2", flex_grow="1"),
rx.card("Card 3", flex_grow="1"),
direction=rx.breakpoints(initial="column", sm="row"),
spacing=rx.breakpoints(initial="2", md="4"),
width="100%",
)Children inside a Flex are sized with three CSS properties. Sizing always happens along the main axis (width for row, height for column).
flex_basis: the preferred base size. Without it, width (or height) is used, and failing that, the content size.flex_grow (default "0"): with "0" it never grows past its base size. With "1" it takes up leftover space.flex_shrink (default "1"): with "0" it never shrinks below its base size.Use the slider to narrow the outer Flex. The flex_shrink=0 box holds on to its 100px while the others shrink first.
class FlexSizeHintState(rx.State):
width_pct: int = 100
@rx.event
def set_width_pct(self, value: list[float]):
self.width_pct = int(value[0])
@rx.var
def width_css(self) -> str:
return f"{self.width_pct}%"
def flex_border_box(label, **props):
return rx.box(label, border="1px solid var(--gray-10)", border_radius="2px", padding="4px", font_size="12px", **props)
rx.box(
rx.flex(
flex_border_box("flex_shrink=0", flex_shrink="0", width="100px"),
flex_border_box("flex_shrink=1", flex_shrink="1", width="200px"),
flex_border_box("flex_grow=0", flex_grow="0"),
flex_border_box("flex_grow=1", flex_grow="1"),
width=FlexSizeHintState.width_css,
spacing="2",
margin_bottom="16px",
),
rx.slider(
min=0,
max=100,
value=[FlexSizeHintState.width_pct],
on_change=FlexSizeHintState.set_width_pct,
),
width="100%",
)Each card gets a base width with flex_basis="140px" and shares the leftover space with flex_grow="1". Thanks to wrap="wrap", cards move to the next line on narrow screens.
Mug
$12
Plate
$12
Bowl
$12
Vase
$12
Cup
$12
Tray
$12
rx.flex(
rx.foreach(
["Mug", "Plate", "Bowl", "Vase", "Cup", "Tray"],
lambda name: rx.card(
rx.text(name, weight="bold"),
rx.text("$12", size="2", color="var(--gray-11)"),
flex_basis="140px",
flex_grow="1",
),
),
spacing="3",
wrap="wrap",
width="100%",
)Workshop notes
rx.flex lines children up in a row. Defaults: row, nowrap.
direction sets the main axis, justify aligns along it, align aligns across it.
With wrap="wrap", overflowing children move to the next line. spacing "0"–"9" sets the gap.
Size children with flex_basis · flex_grow · flex_shrink.
rx.breakpoints(initial=…, sm=…) gives different values per screen width.
Get news about new lessons
We'll email you when this course gets new lessons or a follow-up course opens.
R
ReflexKR
Learn Python and Reflex by doing. Every example was run and verified on Reflex 0.10.0.
ReflexKR is free, with no banner ads. If it helped you, you can support it with a coffee. ☕ Buy us a coffee
Affiliate disclosure© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Questions & answers
Ask anything about this lesson. Questions from every language version of this page appear together.