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.imageOfficial docs
Workshop order
Fill the top of the poster product card with the product photo, and add a button for viewing the other photos.
rx.image is the HTML <img> element that shows a picture. Put the image address in src. It can be an external address (https://…), or, for a file in the app's assets folder, a path starting with / such as /logo.png. Write a description in alt for people who cannot see the image.
rx.image(src="https://picsum.photos/id/1015/400/250", alt="A river between mountains", width="240px", height="auto")rx.image takes style props just like Box. Set the size, then choose with object_fit how the picture fits its box.
Try the props
src
width
height
object_fit
radius
rx.image(src="https://picsum.photos/id/1015/400/250", alt="Sample photo", width="200px", height="auto", object_fit="cover", border_radius="8px")| Prop | Values | Default | Use |
|---|---|---|---|
src | address, /assets path, State value, PIL image | none | The image to show. Passing it as the first child also sets src |
alt | string | none | Image description (for screen readers and when the image fails to load) |
loading | "eager" "lazy" | "eager" | With "lazy", it downloads when it comes near the screen |
decoding | "async" "auto" "sync" | "auto" | Whether to decode the image separately from painting the page |
src_set · sizes | string | none | Picks an image size that fits the screen width |
cross_origin | "anonymous" "use-credentials" | none | How CORS requests are made for images from other domains |
referrer_policy | "no-referrer" "origin" … | none | Which referrer to send when requesting the image |
use_map | "#map-name" | none | Links clickable areas on the image (<map>) |
| styles | width height object_fit border_radius border … | Styled with CSS props, like Box |
It takes the standard events such as on_click.
Use style props such as border_radius, border and box_shadow as they are. A square image with border_radius="50%" becomes a circle. In 0.10, passing the address as the first child, as in the third image, also sets src.
rx.flex(
rx.image(
src="https://picsum.photos/id/237/300/300",
alt="A black puppy",
width="120px",
height="auto",
border_radius="15px 50px",
border="5px solid #555",
),
rx.image(
src="https://picsum.photos/id/1025/300/300",
alt="A pug in a blanket",
width="120px",
border_radius="50%",
box_shadow="0 4px 14px rgba(0, 0, 0, 0.25)",
),
rx.image("https://picsum.photos/id/1043/300/300", alt="Positional src", width="120px", border_radius="8px"),
spacing="4",
align="center",
wrap="wrap",
)Here a 400×250 image sits in a 160×160 box. cover keeps the proportions, fills the box and crops what spills over. contain keeps the proportions and shrinks the image until all of it shows, leaving empty space. fill ignores the proportions and stretches. When cells must match in size, as in a product list, cover is the usual choice.
covercontainfillrx.flex(
rx.vstack(
rx.image(src="https://picsum.photos/id/1039/400/250", alt="cover", width="160px", height="160px", object_fit="cover"),
rx.code("cover"),
align="center",
),
rx.vstack(
rx.image(src="https://picsum.photos/id/1039/400/250", alt="contain", width="160px", height="160px", object_fit="contain",
background=rx.color("gray", 4)),
rx.code("contain"),
align="center",
),
rx.vstack(
rx.image(src="https://picsum.photos/id/1039/400/250", alt="fill", width="160px", height="160px", object_fit="fill"),
rx.code("fill"),
align="center",
),
spacing="4",
wrap="wrap",
)List several sizes of the same image in src_set and tell the browser in sizes which width to use at which screen width, and it picks and downloads the right file. Narrow screens get the small file and load faster. loading="lazy" delays the download until the image comes near the screen.
rx.image(
src="https://picsum.photos/id/1060/800/500",
src_set="https://picsum.photos/id/1060/400/250 400w, https://picsum.photos/id/1060/800/500 800w",
sizes="(max-width: 600px) 400px, 800px",
alt="Coffee being poured",
loading="lazy",
decoding="async",
width="100%",
max_width="400px",
border_radius="8px",
)Put a State value in src and the image changes when the value does. Click a thumbnail below and the large image changes. The list of addresses lives in State, and only the selected index changes.
class ImageGalleryState(rx.State):
photos: list[str] = [
"https://picsum.photos/id/1015/480/300",
"https://picsum.photos/id/1025/480/300",
"https://picsum.photos/id/1043/480/300",
"https://picsum.photos/id/1080/480/300",
]
current: int = 0
@rx.event
def show(self, i: int):
self.current = i
rx.vstack(
rx.image(
src=ImageGalleryState.photos[ImageGalleryState.current],
alt="Selected photo",
width="100%",
max_width="480px",
aspect_ratio="16 / 10",
object_fit="cover",
border_radius="8px",
),
rx.flex(
rx.foreach(
ImageGalleryState.photos,
lambda p, i: rx.image(
src=p,
alt="Thumbnail",
width="72px",
height="45px",
object_fit="cover",
border_radius="4px",
cursor="pointer",
opacity=rx.cond(i == ImageGalleryState.current, "1", "0.45"),
on_click=ImageGalleryState.show(i),
),
),
spacing="2",
),
spacing="3",
)Files in the app's assets folder are referenced with a path starting with /. You can also keep a Pillow (PIL) Image object in a State var and pass it to src; Reflex converts it to image data and sends it. Use this to show an image right after creating or editing it on the server. Pillow is not installed on this site, so it is shown only as code (it needs pip install pillow).
rx.image(src="/logo.png", alt="Logo", width="80px") # assets/logo.png
from PIL import Image
import requests
class ImagePilState(rx.State):
url: str = "https://picsum.photos/id/1/200/300"
image: Image.Image = Image.open(requests.get(url, stream=True).raw)
def image_pil_example():
return rx.image(src=ImagePilState.image, alt="Dynamically generated image")rx.image only accepts addresses and PIL images. Convert an OpenCV (cv2) image to a PIL image, or save it as a file in the assets folder, before passing it. To let users upload images, see the Upload page.
rx.inset removes the card's top padding so the image fills the edge. Because the height is fixed, object_fit="cover" crops it to fit. The photo uses the same State as the gallery above, so clicking the button changes the photo in both examples.
Mountain Trip Print
A3 poster, matte paper
rx.card(
rx.inset(
rx.image(
src=ImageGalleryState.photos[ImageGalleryState.current],
alt="Product photo",
width="100%",
height="180px",
object_fit="cover",
loading="lazy",
),
side="top",
pb="current",
),
rx.text("Mountain Trip Print", weight="bold"),
rx.text("A3 poster, matte paper", size="2", color_scheme="gray"),
rx.button("Next photo", size="1", variant="soft", margin_top="8px",
on_click=ImageGalleryState.show((ImageGalleryState.current + 1) % 4)),
max_width="300px",
)Workshop notes
rx.image(src="…", alt="…"). Takes external addresses, /assets paths, State values and PIL images.
Style it like Box: width, height, border_radius, border.
With a fixed cell size, object_fit="cover" crops to fill (contain shows everything).
src_set and sizes pick a file for the screen width; loading="lazy" delays loading.
Always write alt, for people who cannot see the image and for when it fails to load.
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.