---
title: "Give each template one root element · Agent Wranglers"
url: https://agentwranglers.se/playbook/html-css/html-structure-and-reuse/one-root-per-template
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Give each template one root element

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

For AI agents: [llms.txt](https://agentwranglers.se/llms.txt) is a short guide that sends you to the rules your problem needs, and [rules.json](https://agentwranglers.se/playbook/html-css/rules.json) holds every rule of this playbook as JSON.

- Level: Recommended
- Chapter: [HTML structure and reuse](https://agentwranglers.se/playbook/html-css/html-structure-and-reuse)
- Rule: Make every template return exactly one root element that carries the module's root class. Callers never wrap it in an extra element to change how it looks.
- How: One root gives the component one place for its class, its custom properties and its container query. Spacing between components belongs to the layout that holds them, not to a wrapper added by each caller. Controls such as buttons come from the shared library in [Build each control once](https://agentwranglers.se/playbook/app-ui/styles-and-components/shared-components). Name the root class as [Use one naming pattern for every class](https://agentwranglers.se/playbook/html-css/naming-and-state/one-class-name-pattern) describes.
- Check: A unit test parses each template's output. It finds exactly 1 top-level element, and that element's class list starts with the module prefix.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
import { parseFragment } from 'parse5';
const roots = parseFragment(priceTag({ name: 'Rye loaf', price: '4.50' })).childNodes.filter(node => node.tagName);
assert.equal(roots.length, 1);
assert.match(roots[0].attrs.find(a => a.name === 'class').value, /^price-tag\b/);
```

### Python example

```python
from html.parser import HTMLParser

class Roots(HTMLParser):
    def __init__(self):
        super().__init__(); self.depth = 0; self.roots = []
    def handle_starttag(self, tag, attrs):
        if self.depth == 0: self.roots.append(dict(attrs).get("class", ""))
        self.depth += 1
    def handle_endtag(self, tag):
        self.depth -= 1

parser = Roots(); parser.feed(price_tag("Rye loaf", "4.50"))
assert len(parser.roots) == 1 and parser.roots[0].startswith("price-tag")
```

## Related rules

- [Build each control once](https://agentwranglers.se/playbook/app-ui/styles-and-components/shared-components) in App interface
- [Use one naming pattern for every class](https://agentwranglers.se/playbook/html-css/naming-and-state/one-class-name-pattern) in HTML and CSS

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/html-css/html-structure-and-reuse/one-root-per-template">Agent Wranglers HTML and CSS playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Pass data to templates instead of markup](https://agentwranglers.se/playbook/html-css/html-structure-and-reuse/partials-take-data)
- Next: [Keep ids unique and stable](https://agentwranglers.se/playbook/html-css/html-structure-and-reuse/unique-stable-ids)
- [HTML structure and reuse](https://agentwranglers.se/playbook/html-css/html-structure-and-reuse)
