1. The Schema Contract (tags.json)
Single Source of Truth
Every <label> compiled by json-to-dom v7 is checked against this contract before touching the DOM:
"label": {
"allowsTextContent": true,
"allowsChildren": true,
"allowedAttributes": [
"for",
"class",
"id"
]
}
true: Text strings represent the visual caption.
Strictly for, class, id. All other attributes are purged.
Dedicated to captioning. Does not contain input controls.
2. What is RIGHT (Valid Patterns)
4 Valid Types
In json-to-dom, these patterns represent correct, optimal declarations for the <label> element:
A clean text caption linked to an input control via the for attribute matching the input's id.
{
"tagName": "label",
"textContent": "Customer Email Address",
"attributes": {
"for": "user-email"
}
}
Applying styling classes (e.g. form-label, fw-semibold, text-primary) via attributes.class.
{
"tagName": "label",
"textContent": "Mobile Phone Number",
"attributes": {
"for": "cust-mobile",
"class": "form-label fw-semibold text-primary"
}
}
A standalone uppercase or muted caption used as a group header or fieldset descriptor.
{
"tagName": "label",
"textContent": "BILLING AND SHIPPING ADDRESS",
"attributes": {
"class": "text-uppercase text-muted small fw-bold tracking-wide"
}
}
Providing an explicit id for automated testing (Playwright, Cypress) or aria-labelledby bindings.
{
"tagName": "label",
"textContent": "Tax Identification (GSTIN)",
"attributes": {
"id": "lbl-tax-id",
"for": "input-tax-id",
"class": "form-label fw-medium text-dark"
}
}
3. What is WRONG (Anti-Patterns & Violations)
4 Common Violations
These anti-patterns violate HTML grammar or the tags.json schema contract.
In v7, the compiler will actively filter these attributes or flag validation errors:
Attempting to pass placeholder, type, or value to a <label>.
Labels are captions, not inputs.
{
"tagName": "label",
"textContent": "Full Name",
"attributes": {
"for": "user-fullname",
"placeholder": "Enter full name", // ❌ WRONG: Belongs to <input>
"type": "text", // ❌ WRONG: Belongs to <input>
"value": "John Doe" // ❌ WRONG: Belongs to <input>
}
}
filterAttributes.js purges placeholder, type, and value. The real DOM node only receives <label for="user-fullname">Full Name</label>.
Passing colspan, rowspan, or border on a label.
{
"tagName": "label",
"textContent": "Voucher Total",
"attributes": {
"colspan": 2, // ❌ WRONG: Belongs to <td> or <th>
"rowspan": 1 // ❌ WRONG: Belongs to <td> or <th>
}
}
tags.json schema validation. Stripped completely from DOM.
Labels do not have interactive state. State belongs to the input element.
{
"tagName": "label",
"textContent": "Agree to Terms",
"attributes": {
"for": "agree-chk",
"disabled": "true", // ❌ WRONG: Label cannot be disabled
"checked": "true" // ❌ WRONG: Label cannot be checked
}
}
text-muted opacity-50).
Wrapping <input> inside <label> children creates deeply coupled, non-reusable trees.
// ❌ ANTI-PATTERN in json-to-dom:
{
"tagName": "label",
"children": [
{ "tagName": "span", "textContent": "Name: " },
{ "tagName": "input", "attributes": { "type": "text" } } // ❌ Non-composable
]
}
<label> and <input> as separate siblings in a composite group, bound via for="id". This allows independent styling, validation, and layout flexibility.
4. Attribute Reference Matrix
Allowed Attributes (tags.json)
| Attribute | Type | Purpose | Example |
|---|---|---|---|
for |
string | References the id of the associated form input. Critical for accessibility. |
for: "user-name" |
class |
string | CSS styling classes (Bootstrap, Tailwind, custom utility classes). | class: "form-label fw-bold" |
id |
string | Unique DOM identifier for test hooks and ARIA labelling. | id: "lbl-username" |
Common Forbidden Attributes
| Forbidden | Belongs To | Why It Is Disallowed on <label> |
|---|---|---|
placeholder |
<input>, <textarea> |
Labels are permanent visual titles, not ghost input prompts. |
type |
<input>, <button> |
Labels have no data type; they render text content. |
value |
<input>, <option> |
Labels do not carry form submission state. |
disabled |
<input>, <button> |
Labels cannot be disabled. Use CSS (e.g. opacity-50) instead. |
colspan, rowspan |
<td>, <th> |
Table layout attributes cannot be applied to labels. |
5. Classes & Visual Styling (Pure Labels)
Inspect how different CSS utility classes shape the appearance of the <label> alone:
class: "form-label fw-semibold text-dark"
class: "text-uppercase text-muted small fw-bold"
class: "badge bg-primary px-2.5 py-1.5"
class: "text-light fw-medium small"