R

ReflexKR

Reflex Docs

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

The Component Workshop: Reflex's 100 Library Components
HTML elements

HTML Layout

rx.el.addressrx.el.articlerx.el.asiderx.el.blockquoterx.el.bodyrx.el.ddrx.el.del_rx.el.detailsrx.el.dialogrx.el.dlrx.el.dtrx.el.figcaptionrx.el.footerrx.el.h1 ~ h6rx.el.headrx.el.headerrx.el.hrrx.el.htmlrx.el.lirx.el.linkrx.el.mainrx.el.navrx.el.noscriptrx.el.olrx.el.portalrx.el.prerx.el.scriptrx.el.sectionrx.el.templaterx.el.titlerx.el.ul

Official docs

Workshop order

Lay out one shop news post with meaningful HTML structure: a header, the body, a side tip, a collapsible question and a contact footer.

These HTML elements handle the structure and layout of a document. They include elements that name regions, like header, main and footer, the headings h1–h6, the lists ul, ol and dl, and the expandable details. You could build the same look with divs, but meaningful elements let screen readers and search engines understand the structure of the page.

Opening hours

Mon to Fri, 9 am to 6 pm.

Updated today
rx.el.article(
    rx.el.header(rx.el.h2("Opening hours", font_weight="bold")),
    rx.el.p("Mon to Fri, 9 am to 6 pm."),
    rx.el.footer("Updated today", font_size="12px", color="gray"),
    padding="12px",
    border="1px solid gray",
    border_radius="8px",
)

Try the props

Most structural elements only have common attributes. Play with the ones that have their own: ol (reversed) and details (open). On this site Tailwind preflight removes list markers, so the markers are brought back with the CSS list_style_type.

Try the props

  1. Mix
  2. Bake
  3. Serve
More info

Shown when the details element is open.

reversed

marker

summary

open

rx.el.div(
    rx.el.ol(
        rx.el.li("Mix"),
        rx.el.li("Bake"),
        rx.el.li("Serve"),
        reversed=False,
        list_style_type="decimal",
        padding_left="2em",
    ),
    rx.el.details(
        rx.el.summary("More info", cursor="pointer"),
        rx.el.p("Shown when the details element is open."),
        open=False,
    ),
)
Turn on reversed and the numbers count down. open shows details expanded from the start.
PropValuesDefaultUse
start (ol)integer1First number
reversed (ol)True / FalseFalseCount down
type (ol)"1" "a" "A" "i" "I""1"Numbering style. With preflight, CSS list_style_type takes over
open (details, dialog)True / FalseFalseExpanded / open
cite (blockquote, del_)URLnoneSource of the quotation or edit
date_time (del_)date stringnoneWhen the text was deleted
rel href … (link)stringnoneLinks an external resource (for the document head)
async_ defer src … (script)bool, stringnoneScript tag (see the Script page)

The skeleton of a page

header is the head, nav the navigation menu, main the main content, article a piece that still makes sense on its own, aside a side note, section a thematic group, footer the bottom, and address the contact details. They are all unstyled boxes, so the layout is set with CSS such as display="grid" or "flex".

Workshop

Post title

The main story goes here.

A themed section of the page.

hello@example.com
rx.el.div(
    rx.el.header(
        rx.el.strong("Workshop"),
        rx.el.nav(rx.el.span("Home"), rx.el.span("Parts"), rx.el.span("About"), display="flex", gap="12px"),
        display="flex",
        justify_content="space-between",
        padding="8px",
        background=rx.color("indigo", 3),
    ),
    rx.el.main(
        rx.el.article(rx.el.h3("Post title", font_weight="bold"), rx.el.p("The main story goes here.")),
        rx.el.aside("Related links", padding="8px", background=rx.color("gray", 3)),
        display="grid",
        grid_template_columns="2fr 1fr",
        gap="12px",
        padding="8px",
    ),
    rx.el.section(rx.el.p("A themed section of the page."), padding="8px", border_top="1px dashed gray"),
    rx.el.footer(rx.el.address("hello@example.com"), padding="8px", font_size="13px", color="gray"),
    border="1px solid gray",
    border_radius="8px",
    overflow="hidden",
)

Headings, rules, quotations, preformatted text

Because of preflight, h1 and h3 come out the same size as body text. A heading is meaning; set its size separately with font_size. hr is a line marking a change of topic, blockquote a long quotation (source in cite), and pre text that keeps its spaces and line breaks exactly. The del element clashes with a Python keyword, so in Reflex it is written rx.el.del_ (the list in the official docs writes it as rx.el.Del). Its partner rx.el.ins marks newly inserted text.

h1 with no style

h3 with no style

h2 with style


Make it work, make it right, make it fast.
def hello():
    print('hi')

Price: $20 $15

rx.el.div(
    rx.el.h1("h1 with no style"),
    rx.el.h3("h3 with no style"),
    rx.el.h2("h2 with style", font_size="24px", font_weight="bold"),
    rx.el.hr(margin_y="8px"),
    rx.el.blockquote(
        "Make it work, make it right, make it fast.",
        cite="https://wiki.c2.com/?MakeItWorkMakeItRightMakeItFast",
        border_left="4px solid gray",
        padding_left="12px",
        font_style="italic",
    ),
    rx.el.pre("def hello():\n    print('hi')", padding="8px", background=rx.color("gray", 3)),
    rx.el.p("Price: ", rx.el.del_("$20", date_time="2026-10-01"), " ", rx.el.ins("$15")),
)

Lists

ul is an unordered list and ol a numbered one, with li items. dl is a description list of term (dt) and description (dd) pairs.

  • Apples
  • Pears
  1. Third
  2. Fourth
Box
A container with no meaning.
Flex
A row or column of children.
rx.el.div(
    rx.el.ul(rx.el.li("Apples"), rx.el.li("Pears"), list_style_type="disc", padding_left="1.5em"),
    rx.el.ol(rx.el.li("Third"), rx.el.li("Fourth"), start=3, list_style_type="decimal", padding_left="1.5em"),
    rx.el.dl(
        rx.el.dt("Box", font_weight="bold"),
        rx.el.dd("A container with no meaning.", margin_left="1.5em"),
        rx.el.dt("Flex", font_weight="bold"),
        rx.el.dd("A row or column of children.", margin_left="1.5em"),
    ),
    display="flex",
    gap="24px",
    flex_wrap="wrap",
)

Disclosure and dialogs

The first summary inside details becomes its title, and clicking it makes the browser expand and collapse it on its own. No State needed. dialog is opened with the open attribute. Opened this way it is a non-modal window that doesn't block what's behind it; for a modal dialog that covers the screen, rx.dialog is easier.

What is details?

A box the browser opens and closes by itself.

A non-modal dialog, opened by the open prop.

class HtmlLayoutDialogState(rx.State):
    is_open: bool = False

    @rx.event
    def toggle(self):
        self.is_open = not self.is_open


rx.el.div(
    rx.el.details(
        rx.el.summary("What is details?", cursor="pointer"),
        rx.el.p("A box the browser opens and closes by itself."),
    ),
    rx.el.button(
        "Toggle dialog",
        on_click=HtmlLayoutDialogState.toggle,
        padding="4px 12px",
        border="1px solid gray",
        border_radius="6px",
        margin_top="12px",
    ),
    rx.el.dialog(
        rx.el.p("A non-modal dialog, opened by the open prop."),
        open=HtmlLayoutDialogState.is_open,
        padding="12px",
        border="1px solid gray",
        border_radius="8px",
        top="40px",
    ),
    position="relative",
    min_height="150px",
)

Figures and captions

figcaption adds a caption to content inside a figure, such as an image, a table or code.

Strawberries
Fig. 1 - Fresh strawberries
rx.el.figure(
    rx.el.img(src="https://picsum.photos/id/1080/320/160", alt="Strawberries", border_radius="6px"),
    rx.el.figcaption("Fig. 1 - Fresh strawberries", font_size="13px", color="gray", margin_top="4px"),
    width="320px",
)

Invisible elements and document-level elements

Content inside template is not drawn on screen; it only remains as a template to clone. noscript only shows in browsers with JavaScript turned off. Reflex apps run on JavaScript, so it doesn't show here.

Only this line is visible.

rx.el.div(
    rx.el.p("Only this line is visible."),
    # rx.el.template(...) also keeps its content off the page, but React cannot
    # hydrate children inside <template>, so it is left out of this live example.
    rx.el.noscript("Please turn on JavaScript."),
)

html, head, body, title, link, script and portal are elements for the whole document or its head. Reflex already builds this frame for you, so they are rarely used inside a page, and here they are shown as code only. React 19 hoists title and link placed in the body up into the document head, so rendering them on a page would change this site's tab title.

# Document-level and head elements: Reflex already renders these, so pages rarely use them
rx.el.html(...)    # manifest attribute (removed in HTML5)
rx.el.head(...)
rx.el.body(...)
rx.el.title("Page title")   # set page titles with @rx.page(title=...)
rx.el.link(rel="stylesheet", href="/styles.css")   # add stylesheets with rx.App(stylesheets=[...])
rx.el.script(src="/my-script.js")   # use rx.script for scripts (see the Script page)
rx.el.portal(...)  # experimental element that never became a standard

Filling the order

The whole post is an article, the title and date a header, the body a section, the tip an aside, the question a details, and the contact details an address inside the footer.

Spring menu is here

Three new dishes join the menu this week.

  • Spring rolls
  • Pea soup
  • Lemon tart
Do you have vegan options?

Yes, the soup and rolls are vegan.


12 Market St · hello@example.com
rx.el.article(
    rx.el.header(
        rx.el.h1("Spring menu is here", font_size="22px", font_weight="bold"),
        rx.el.p(rx.el.time("Mar 3, 2026", date_time="2026-03-03"), font_size="13px", color="gray"),
    ),
    rx.el.section(
        rx.el.p("Three new dishes join the menu this week."),
        rx.el.ul(rx.el.li("Spring rolls"), rx.el.li("Pea soup"), rx.el.li("Lemon tart"), list_style_type="disc", padding_left="1.5em"),
        margin_y="8px",
    ),
    rx.el.aside("Tip: book a table early.", padding="8px", background=rx.color("amber", 3), border_radius="6px"),
    rx.el.details(
        rx.el.summary("Do you have vegan options?", cursor="pointer", font_weight="600"),
        rx.el.p("Yes, the soup and rolls are vegan."),
        margin_y="8px",
    ),
    rx.el.hr(),
    rx.el.footer(rx.el.address("12 Market St · hello@example.com"), font_size="13px", color="gray", margin_top="8px"),
    padding="16px",
    border="1px solid gray",
    border_radius="10px",
    max_width="420px",
)

Workshop notes

  • header, nav, main, article, section, aside and footer name regions. Layout is done with CSS.

  • h1–h6 are only meaning. Under preflight, set the size with font_size.

  • ul, ol, li; dl, dt, dd. List markers via list_style_type; ol has start and reversed.

  • details + summary expands without State. dialog's open is non-modal; for a modal, use rx.dialog.

  • del is rx.el.del_. html, head, body, title and link are handled by Reflex, so don't use them in pages.

← Previous

HTML elements · HTML Text

Next →

HTML elements · HTML Forms

Get news about new lessons

We'll email you when this course gets new lessons or a follow-up course opens.

We collect: your email address · Purpose: news about new lessons or the launch of this course · Kept until: you ask us to remove it. We never use it for anything else or share it. Reply to any notice email and we'll delete it right away.

Questions & answers

Ask anything about this lesson. Questions from every language version of this page appear together.

Shown as plain text, without links or formatting.

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
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex