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 Media

rx.el.arearx.el.audiorx.el.canvasrx.el.embedrx.el.iframerx.el.imgrx.el.mathrx.el.metarx.el.objectrx.el.picturerx.el.sourcerx.el.trackrx.el.video

Official docs

Workshop order

A product detail screen: a large photo (a square photo on narrow screens), a how-to video and a sound preview, using only HTML media elements.

These HTML elements put images, video, sound and other documents on a page. img, video and audio are the most common; picture and source pick the right file for the screen; and iframe, embed and object embed other documents. They are simpler than Reflex's rx.image, rx.video and rx.audio and use the browser's built-in features as they are.

A dog in a blanket
rx.el.img(src="https://picsum.photos/id/1025/300/200", alt="A dog in a blanket", width="300px", height="200px")

Try the props

For img, change how it fits its box (object_fit) and the CSS filter; for video, change the control bar (controls), looping and muting.

Try the props

A city street

width

fit

radius

filter

loading

rx.el.img(
    src="https://picsum.photos/id/1043/400/250",
    alt="A city street",
    width="240px",
    height="160px",
    object_fit="cover",
    border_radius="8px",
    filter="none",
    loading="lazy",
    background=rx.color("gray", 4),
)
object_fit: cover crops to fill, contain shrinks so the whole image shows, and fill stretches it ignoring the aspect ratio.

Try the props

controls

loop

muted

width

rx.el.video(
    src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
    poster="https://picsum.photos/id/152/320/180",
    controls=True,
    loop=False,
    muted=True,
    plays_inline=True,
    width="280px",
)
Turn off controls and the playback bar disappears. poster is the image shown before playback.
PropValuesDefaultUse
src alt (img)URL / stringnoneImage address and alternative text. Always write alt
src_set sizes (img, source)list of candidatesnonePick a file for the screen density and width
loading (img, iframe)"lazy" "eager""eager"Load when it gets close to the viewport
decoding (img)"async" "sync" "auto""auto"When the image is decoded
controls loop muted auto_play (video, audio)True / FalseFalseControl bar, looping, muting, autoplay
poster plays_inline (video)URL / boolnoneImage before playback; play on mobile without going full screen
preload (video, audio)"none" "metadata" "auto"varies by browserHow much to download in advance
media type (source)media query / MIMEnoneCondition and file format
kind src_lang label default (track)string, boolnoneSubtitle file
src_doc sandbox allow (iframe)HTML / list of permissionsnoneDocument to embed and its restrictions
shape coords href (area)"rect" "circle" "poly" …noneClickable regions of an image map

img: alternative text and resolution candidates

alt is shown in place of the image when it can't load, and it's the text screen readers read. The image on the right deliberately uses an address that doesn't exist on this site, so its alt shows. Give src_set 1x and 2x candidates and high-resolution screens pick the larger file. loading="lazy" defers loading until the image gets close to the viewport.

Sharp on high density screensBroken image: the alt text shows
rx.el.div(
    rx.el.img(
        src="https://picsum.photos/id/1025/150/100",
        src_set="https://picsum.photos/id/1025/150/100 1x, https://picsum.photos/id/1025/300/200 2x",
        alt="Sharp on high density screens",
        loading="lazy",
        decoding="async",
    ),
    rx.el.img(src="/no-such-image.png", alt="Broken image: the alt text shows"),
    display="flex",
    gap="12px",
    align_items="center",
)

picture and source: the right image for the screen

The browser goes through the sources inside picture from the top and uses the first file whose media condition matches. If none match, it uses the final img. Make the window narrower than 640px and it switches to the square photo.

A landscape
rx.el.picture(
    rx.el.source(media="(max-width: 640px)", src_set="https://picsum.photos/id/1015/300/300"),
    rx.el.img(src="https://picsum.photos/id/1016/480/200", alt="A landscape", max_width="100%"),
)

video, audio, source, track

You can pass src directly, or give several files in different formats as source children. The browser picks the first source it can play. Text after the sources only shows in browsers that can't play the video. Most browsers only allow autoplay (auto_play) when the media is muted.

rx.el.div(
    rx.el.video(
        rx.el.source(src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4", type="video/mp4"),
        "Your browser cannot play this video.",
        controls=True,
        muted=True,
        preload="metadata",
        width="280px",
    ),
    rx.el.audio(
        src="https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3",
        controls=True,
        preload="none",
    ),
    display="flex",
    flex_direction="column",
    gap="12px",
)

track attaches a WebVTT (.vtt) subtitle file. The subtitle file has to be on the same site, so here it is shown as code only. Put the file in the assets folder.

rx.el.video(
    rx.el.source(src="/flower.mp4", type="video/mp4"),
    rx.el.track(src="/flower.en.vtt", kind="subtitles", src_lang="en", label="English", default=True),
    controls=True,
)

iframe: a page inside a page

Give src the address of another page, or pass HTML directly in src_doc. sandbox="" blocks all scripts, forms and pop-ups in the embedded document; lift only what you need, such as "allow-scripts". title tells screen readers what's inside. Many other sites block being embedded.

rx.el.iframe(
    src_doc="<h3 style='font-family:sans-serif'>Hello from an iframe</h3><p style='font-family:sans-serif'>This page lives in src_doc.</p>",
    sandbox="",
    loading="lazy",
    title="Inline document",
    width="320px",
    height="130px",
    border="1px solid gray",
    border_radius="6px",
)

embed and object

Both are old ways of including external resources. embed only takes src and type; object takes data and shows its children instead if loading fails. Nowadays it's better to use img for images, video for video and iframe for documents.

Fallback text if the data cannot load
rx.el.div(
    rx.el.embed(src="https://picsum.photos/id/237/160/110", type="image/jpeg", width="160px", height="110px"),
    rx.el.object(
        "Fallback text if the data cannot load",
        data="https://picsum.photos/id/40/160/110",
        type="image/jpeg",
        width="160px",
        height="110px",
    ),
    display="flex",
    gap="12px",
)

canvas: a drawing board

canvas is an empty drawing board, and the drawing is done by JavaScript. Below, rx.call_script in on_mount draws a rectangle and a circle. A canvas's width and height aren't CSS sizes but the board's pixel count, so in Reflex they are passed through custom_attrs (as keywords they would become CSS).

rx.el.canvas(
    id="htmlmedia_canvas",
    custom_attrs={"width": "260", "height": "100"},
    border="1px solid gray",
    border_radius="6px",
    on_mount=rx.call_script(
        "const g = document.getElementById('htmlmedia_canvas').getContext('2d');"
        " g.fillStyle = '#6e56cf'; g.fillRect(20, 20, 120, 60);"
        " g.fillStyle = '#e54d2e'; g.beginPath(); g.arc(200, 50, 30, 0, Math.PI * 2); g.fill();"
    ),
)

area: image maps

The areas inside a map are the clickable regions on an image. Connect it by writing "#map-name" in the img's use_map. The left half of the photo and the circle on the right each lead to a different document.

Library docsMedia docsImage map
rx.el.div(
    rx.el.map(
        rx.el.area(shape="rect", coords="0,0,150,200", href="https://reflex.dev/docs/library/", target="_blank", alt="Library docs"),
        rx.el.area(shape="circle", coords="225,100,60", href="https://reflex.dev/docs/library/html/media/", target="_blank", alt="Media docs"),
        name="htmlmedia-map",
    ),
    rx.el.img(src="https://picsum.photos/id/1060/300/200", alt="Image map", use_map="#htmlmedia-map", width="300px", height="200px"),
)

math and meta

rx.el.math is a container for formulas (MathML), but the tags that go inside it, such as mi, mo and msup, aren't in rx.el. For formulas, it's easier to insert the whole MathML with rx.html. meta is information for the document head. React 19 hoists meta from the body into the head, so it isn't rendered on the page; you usually pass it through the meta argument of @rx.page.

a2+b2=c2
rx.html("<math display='block'><msup><mi>a</mi><mn>2</mn></msup><mo>+</mo><msup><mi>b</mi><mn>2</mn></msup><mo>=</mo><msup><mi>c</mi><mn>2</mn></msup></math>")
rx.el.math(...)   # MathML box; rx.el has no mi/mo/mn tags to put inside it
rx.el.meta(name="description", content="A page about media")   # for the document head

@rx.page(title="Media", description="A page about media", meta=[{"name": "theme-color", "content": "#6e56cf"}])
def media_page(): ...

Filling the order

The photo adapts to the screen with picture, the video isn't downloaded until clicked thanks to poster and preload="none", and the sound uses audio's default bar.

Travel kit on a table

See it in action

Sound preview

rx.el.div(
    rx.el.picture(
        rx.el.source(media="(max-width: 640px)", src_set="https://picsum.photos/id/26/320/320"),
        rx.el.img(src="https://picsum.photos/id/26/440/240", alt="Travel kit on a table", border_radius="8px", max_width="100%"),
    ),
    rx.el.p("See it in action", font_weight="600", margin_top="8px"),
    rx.el.video(
        src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
        poster="https://picsum.photos/id/26/440/248",
        controls=True,
        muted=True,
        plays_inline=True,
        preload="none",
        width="100%",
    ),
    rx.el.p("Sound preview", font_weight="600", margin_top="8px"),
    rx.el.audio(src="https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3", controls=True, preload="none"),
    max_width="440px",
)

Workshop notes

  • Always give img an alt. src_set and loading="lazy" fetch the right file, later.

  • picture + source (media) shows different images depending on the screen, with an img last.

  • video and audio get a bar with controls; autoplay only together with muted. Subtitles go in track.

  • iframe takes src or src_doc and is restricted with sandbox. embed and object are old methods.

  • Set canvas size with custom_attrs and draw with JavaScript. Pass meta with @rx.page(meta=...).

← Previous

HTML elements · HTML Forms

Next →

HTML elements · HTML Tables

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