Media and embeds¶
A compact reference for loading local and remote images, setting a favicon, making internal and external links, playing video, and embedding a PDF. Every remote URL was checked when the example was written; the app needs internet access to display those resources.
media/
├── app.py # favicon + local static-files mount
├── settings.py # the remote asset URLs in one place
├── static/
│ └── logo.svg # a downloaded local asset
└── views/
├── styles/
└── pages/media.py # images, links, video and document embeds
1. Favicon and local files¶
Set a favicon with a local or remote URL. Mount a local directory once, then address files under that URL prefix:
"""Media: images, favicons, links, embedded documents and videos.
Run: python app.py --dev # hot reload, readable errors
python app.py --prod # production server
Needs internet access: every asset below is loaded from a public URL, which is the point.
"""
from rational import App
from settings import FAVICON, STATIC_DIR
from views.pages import router
app = App(title="Media", description="Images, favicons, links, embeds.", favicon=FAVICON)
app.include(router)
app.static("/static", STATIC_DIR)
if __name__ == "__main__":
app.run()
This example keeps three verified favicon choices in settings.py and displays all three on the
page. An application still has one active favicon at a time; choose it by changing FAVICON.
2. Images¶
def render(self):
return Column(
Heading("Media", level=1),
Text("Images, favicons, links, embedded documents and videos. This page needs internet.", muted=True),
Grid(
# -- images ----------------------------------------------------------------------
EmbedCard(
"A local image",
"Serve your own files with app.static('/static', 'static'); the URL stays stable.",
Image("/static/logo.svg", alt="The Rational Web example logo"),
Link("Source: static/logo.svg", href="/static/logo.svg", external=True, size="sm"),
),
EmbedCard(
"A remote image",
"Any public URL works. alt is required for meaningful images; "
'use alt="" for decorative images. Lazy loading is on by default.',
Image(PHOTO_JPG, alt="A stock photo of a dog", width=600, height=400),
Link("Source: picsum.photos", href="https://picsum.photos", external=True, size="sm"),
),
EmbedCard(
"An SVG, sized by style",
"SVGs scale: set a width in the style instead of attributes.",
Image(LOGO_SVG, alt="The Python logo", style=Style(width=220, height="auto")),
),
EmbedCard(
"Favicon choices",
"Pass any local or remote image URL as App(favicon=...). This app uses the first one.",
Grid(
*[
Link(
Image(url, alt=f"{name} favicon", width=48, height=48),
name,
href=url,
external=True,
key=name,
)
for name, url in FAVICON_CHOICES
],
min_column_width=100,
gap="sm",
),
),
# -- links -----------------------------------------------------------------------
EmbedCard(
"Links",
"external=True adds target=_blank and rel=noopener noreferrer. ButtonLink looks like a button.",
Link("python.org", href="https://www.python.org", external=True),
Link("A link inside the app", href="/about"),
Link("Mail and phone are just URLs", href="mailto:hi@example.org"),
),
# -- video -------------------------------------------------------------------------
EmbedCard(
"A video, with controls",
"h() builds any HTML element: sources, tracks, fallbacks. Multiple formats let the browser choose.",
h(
"video",
h("source", src=VIDEO_MP4, type="video/mp4"),
h("source", src=VIDEO_WEBM, type="video/webm"),
"Your browser cannot play this video.",
controls=True,
style=Style(width="100%", border_radius="md"),
),
),
# -- documents ----------------------------------------------------------------------
EmbedCard(
"A PDF, inline",
"An iframe shows documents in the page. The same element embeds maps and other pages.",
h(
"iframe",
src=PDF_DOC + "#view=FitH",
title="An example PDF document",
style=Style(
width="100%", height=340, border_style="solid", border_width=1, border_color="border"
),
),
Link("Or link to it directly", href=PDF_DOC, external=True),
),
key="cards",
min_column_width=320,
gap="md",
style=GRID,
),
tag="main",
max_width=1100,
style=PAGE,
)
Image accepts local paths and complete remote URLs. alt is required: describe meaningful
images; use alt="" only for decoration. It adds lazy loading and asynchronous decoding by
default. Width and height attributes prevent layout shifts; Style can size scalable SVGs.
3. Links¶
Link(..., href="/about") navigates inside the app. A complete URL with external=True opens
in a new tab and automatically adds rel="noopener noreferrer". mailto: and tel: use
the same href field. Use ButtonLink when navigation should look like a button; reserve
Button for actions.
4. Videos and documents¶
Rational’s named primitives cover common accessible elements. The h() escape hatch builds
anything else:
h(
"video",
h("source", src=VIDEO_MP4, type="video/mp4"),
h("source", src=VIDEO_WEBM, type="video/webm"),
"Your browser cannot play this video.",
controls=True,
style=Style(width="100%"),
)
h(
"iframe",
src=PDF_DOC,
title="An example PDF document",
style=Style(width="100%", height=340),
)
Multiple video sources let the browser choose a supported format. An iframe needs a useful
title for accessibility. Third-party sites may forbid iframe embedding with their security
headers; in that case, provide an external Link instead.
Run it¶
$ cd examples/media
$ python app.py --dev