cotton
for
Docs syntax
<c> tags: Snippets will be shown in Cotton's HTML-like tag syntax.
Native: Snippets will be shown in native Django template syntax.

Thinking in Components

Already comfortable with components from React, Vue, Svelte, Blade or similar? Feel free to skip ahead to the Quickstart. This page is a primer for anyone coming from vanilla Django templates.

If you've built Django sites, you've composed pages with {% include %}, {% extends %} / {% block %} and the occasional custom template tag. These work, but they were designed for page-level layout and value substitution, not for building small, self-contained pieces of UI you reuse and nest. That gap is what components fill.

The Django way, and where it stops

  • {% include %} pulls in another template, but you can only hand it flat context values. You can't pass a block of markup, or nest other pieces inside it.
  • {% extends %} / {% block %} is great for one page-level skeleton, but it's single inheritance and top-down: a template fills a parent's holes, it can't be dropped in repeatedly like a widget.
  • Custom template tags can encapsulate logic, but each one needs a registered Python function, even for something purely presentational.

What is a component?

A component is a single, self-contained piece of UI that you use like an HTML tag. It bundles three things:

  • Markup: the HTML it renders.
  • Inputs: attributes you pass in, like <c-card title="Welcome">.
  • A slot: the content you nest between its tags, which can be text, HTML or other components.
cotton/card.html
<div class="card">
    <h2>{{ title }}</h2>
    {{ slot }}
</div>

Now use it like a tag, passing an attribute and nesting whatever content you like, including other components:

my_view.html
<c-card title="Welcome">
    <p>Any HTML, or even <c-icon name="star" />, goes here.</p>
</c-card>
{% cotton card title="Welcome" %}
    <p>Any HTML, or even {% cotton icon name="star" %}{% endcotton %}, goes here.</p>
{% endcotton %}

The payoff

  • Reuse: define the markup once, use it anywhere and change it in a single place.
  • Composition: nest components inside components and pass rich content as the slot, building complex UI out of small, understandable parts.
  • Encapsulation: a component's markup, styling and behaviour live together in one file. No Python, nothing scattered across base templates.

Coming from DTL

The instincts you already have map directly onto components:

When you'd reach for... Use a component
{% include %} with context A tag with attributes: <c-card title="..." />
{% block %} / {% extends %} A <c-slot> for each content hole
A presentational custom tag A component, just an HTML file, no Python
back Home
next Quickstart