Skip to main content

plain.elements

Build reusable HTML components using a tag-based syntax.

Overview

Elements give you a component-like syntax for HTML templates. Instead of using Jinja {% include %} or macros, you write components as .html files and use them with capitalized HTML tags like <Button> or <Card>.

To create an element, add a template in templates/elements/. The filename becomes the tag name.

<!-- templates/elements/Button.html -->
<button type="button" class="btn btn-primary">
    {{ children }}
</button>

To use elements in a template, add {% use_elements %} at the top. Then use your element with its capitalized tag name.

{% use_elements %}

<div class="actions">
    <Button>Click me</Button>
</div>

The output will be:

<div class="actions">
    <button type="button" class="btn btn-primary">
        Click me
    </button>
</div>

Passing attributes

You can pass attributes to elements in two ways: as strings or as Python expressions.

String attributes use standard HTML syntax:

{% use_elements %}

<Button type="submit">Save</Button>

Python expressions use single braces {}:

{% use_elements %}

<FormInput field={form.email} label="Email address" />

Inside the element template, attributes become template variables:

<!-- templates/elements/FormInput.html -->
<label for="{{ field.html_id }}">{{ label }}</label>
<input
    id="{{ field.html_id }}"
    type="{{ type|default('text') }}"
    name="{{ field.html_name }}"
    value="{{ field.value() or '' }}"
    {% if field.field.required %}required{% endif %}
/>

By default, Plain raises an error for undefined variables. Use the |default filter or is defined test for optional attributes.

Nested content with children

Content between opening and closing tags is available as the children variable.

<!-- templates/elements/Card.html -->
<div class="card">
    <div class="card-body">
        {{ children }}
    </div>
</div>
{% use_elements %}

<Card>
    <h2>Welcome</h2>
    <p>This content appears inside the card body.</p>
</Card>

Self-closing elements don't have children:

{% use_elements %}

<Divider />

Namespaced elements

You can organize elements into subdirectories. This is particularly useful for reusable packages or grouping related components.

Put the element template in a subdirectory of templates/elements/:

<!-- templates/elements/forms/Input.html -->
<input type="text" class="form-input" />

Use the dot-separated path as the tag name:

{% use_elements %}

<forms.Input />

FAQs

Can I nest the same element inside itself?

No. Elements cannot be nested inside themselves to prevent infinite recursion. If you need recursive structures, split them into separate element types.

Why use capitalized tag names?

Capitalized names like <Button> distinguish your elements from built-in HTML tags like <button>. This prevents conflicts and makes it clear which tags are custom components.

How does this compare to Jinja macros?

Elements are simpler for component-style usage. Macros require import statements and use function-call syntax. Elements look like HTML and feel more natural when building UIs. Use macros when you need complex logic or multiple return values.

Can I use elements without {% use_elements %}?

No. The {% use_elements %} tag enables element processing for that template. Without it, capitalized tags will be treated as literal text.

Installation

Install the plain.elements package:

uv add plain.elements

Add it to your INSTALLED_PACKAGES:

# app/settings.py
INSTALLED_PACKAGES = [
    # ...
    "plain.elements",
]

Create your first element template:

<!-- templates/elements/Alert.html -->
<div class="alert alert-{{ type|default('info') }}">
    {{ children }}
</div>

Use it in any template:

{% use_elements %}

<Alert type="success">
    Your changes have been saved.
</Alert>

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

plain_elements-0.11.7.tar.gz (8.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

plain_elements-0.11.7-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file plain_elements-0.11.7.tar.gz.

File metadata

  • Download URL: plain_elements-0.11.7.tar.gz
  • Upload date:
  • Size: 8.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for plain_elements-0.11.7.tar.gz
Algorithm Hash digest
SHA256 a3f4a0938c1e6a6b4e59137bffd3dd1f27e8ab62ea0a7a4dbf2c08cae9cb1749
MD5 52d6ca1f9d454e2399a99ae6c5bd1ee3
BLAKE2b-256 179a55fbb27aaee436661de50f9b259fad10b5527e8194651fd0932afa0a2621

See more details on using hashes here.

File details

Details for the file plain_elements-0.11.7-py3-none-any.whl.

File metadata

  • Download URL: plain_elements-0.11.7-py3-none-any.whl
  • Upload date:
  • Size: 10.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for plain_elements-0.11.7-py3-none-any.whl
Algorithm Hash digest
SHA256 ea8c88cdc61066d0703f44f912821f10c0839e872a8c9665ec4d3b10aa230eb6
MD5 cd9c9f01febadb62e5421d7f35b4e440
BLAKE2b-256 f7fff2f7b19eb9f5b97584d91b584e832f9fdb120554c0528bcd567d990bb268

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.11.7 This release

2 files

0.11.6

2 files

0.11.5

2 files

0.11.4

2 files

0.11.3

2 files

0.11.2

2 files

0.11.1

2 files

0.11.0

2 files

0.10.3

2 files

0.10.2

2 files

0.10.1

2 files

0.10.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.2

2 files

0.7.1

2 files

0.7.0

2 files

0.6.0

2 files

0.5.1

2 files

0.5.0

2 files

0.4.3

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 files

0.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page