Your First Elements — Tag Functions
Tag functions are the fastest way to generate HTML in Probo-ui. Import them directly from the probo package:
from probo import div, h1, h2, p, span, a, img, button, strong, em, ul, li
Creating Elements
Call the function with content as positional arguments and attributes as keyword arguments:
# Simple heading
h1("Hello World")
# → <h1>Hello World</h1>
# With attributes
h1("Hello World", Class="title", Id="main-title")
# → <h1 class="title" id="main-title">Hello World</h1>
# Link with href
a("Click me", href="https://example.com", target="_blank")
# → <a href="https://example.com" target="_blank">Click me</a>
Nesting Elements
Pass elements inside other elements as positional arguments:
page = div(
h1("Welcome to Probo"),
p("This is ", strong("bold"), " and ", em("italic"), " text."),
ul(
li("First item"),
li("Second item"),
li("Third item"),
),
Class="container"
)
This generates:
<div class="container">
<h1>Welcome to Probo</h1>
<p>This is <strong>bold</strong> and <em>italic</em> text.</p>
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ul>
</div>
Self-Closing (Void) Elements
Tags like <img>, <br>, <hr>, and <input> work the same way — they just don't accept children:
from probo import img, br, hr, Input, meta, link
# Image
img(src="/images/logo.png", alt="Company Logo")
# → <img src="/images/logo.png" alt="Company Logo"/>
# Line break
br()
# → <br/>
# Input field
Input(type="email", placeholder="you@example.com", required=True)
# → <input type="email" placeholder="you@example.com" required/>
⚠️ Python Reserved Words
Some HTML tags conflict with Python builtins. Probo renames them with a capital letter:
| HTML Tag | Probo Name | Why? |
|---|---|---|
<input> |
Input() |
input is a Python builtin |
<del> |
Del() |
del is a Python keyword |
<map> |
Map() |
map is a Python builtin |
<object> |
Object() |
object is a Python builtin |
<filter> (SVG) |
Filter() |
filter is a Python builtin |
<set> (SVG) |
Set() |
set is a Python builtin |
return types
list : adding
return_listas key word arguments signals theElementengine to render the element as list of strings being opening tag as first and closing tag as last
from probo import img, br, h1, Input
# Image
img(src="/images/logo.png", alt="Company Logo",return_list=True)
# → ['<img src="/images/logo.png" alt="Company Logo"/>']
# Line break
br(return_list=True)
# → ["<br/>"]
# Input field
Input(type="email", placeholder="you@example.com", required=True,return_list=True)
# → ["<input type="email" placeholder="you@example.com" required/>"]
# Simple heading
h1("Hello World",return_list=True)
# → ["<h1>","Hello World","</h1>"]
# With attributes
h1("Hello","World", Class="title", Id="main-title",return_list=True)
# → ['<h1 class="title" id="main-title">',"Hello", "World","</h1>"]
deque : adding
return_dequeas key word arguments signals theElementengine to render the element ascollections.dequeof strings being opening tag as first and closing tag as last
from probo import img, br, h1, Input
# Image
img(src="/images/logo.png", alt="Company Logo",return_deque=True)
# → deque(['<img src="/images/logo.png" alt="Company Logo"/>'])
# Line break
br(return_deque=True)
# → deque(["<br/>"])
# Input field
Input(type="email", placeholder="you@example.com", required=True,return_deque=True)
# → deque(["<input type="email" placeholder="you@example.com" required/>"])
# Simple heading
h1("Hello World",return_deque=True)
# → deque(["<h1>","Hello World","</h1>"])
# With attributes
h1("Hello","World", Class="title", Id="main-title",return_deque=True)
# → deque(['<h1 class="title" id="main-title">',"Hello", "World","</h1>"])
Building a Component
from probo import div, h1, h2, p, a, ul, li, img, hr
def welcome_component():
return div(
div(
img(src="/logo.png", alt="Logo"),
h1("My Awesome App"),
p("Build beautiful UIs in pure Python."),
a("Get Started →", href="/docs", Class="btn btn-primary"),
Class="hero"
),
hr(),
div(
h2("Features"),
ul(
li("🐍 100% Python — no templates needed"),
li("🌳 Server-Side DOM tree manipulation"),
li("⚡ Streaming rendering for huge pages"),
li("🎨 CSS-in-Python styling system"),
),
Class="features"
),
Class="landing-page"
)
The Limit of Tag Functions
Tag functions are the bread and butter of Probo-ui for static content. You'll use them everywhere you need blazing-fast, immutable HTML generation.
But because they return raw strings, they are permanently locked in once called. What if you need to build a UI tree, inspect it, find specific elements, and inject new data before sending the HTML to the browser?
For that, we need Server-Side DOM Nodes (the Class flavors like DIV()). And that is exactly what we are covering in upcomming Part 3!
Top comments (0)