DEV Community

YOUNESS MOJAHID
YOUNESS MOJAHID

Posted on

Introduction to Probo-ui — Write HTML Entirely in Python series Part: 02

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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"
)
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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/>

Enter fullscreen mode Exit fullscreen mode

⚠️ 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_list as key word arguments signals the Element engine 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>"]

Enter fullscreen mode Exit fullscreen mode

deque : adding return_deque as key word arguments signals the Element engine to render the element as collections.deque 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_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>"])

Enter fullscreen mode Exit fullscreen mode

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"
    )
Enter fullscreen mode Exit fullscreen mode

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)